Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add AWS CDK project and Helm charts for Beckn-Onix deployment o… #233

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions aws-cdk/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out
.env
44 changes: 44 additions & 0 deletions aws-cdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Beckn-ONIX, one-click deployment on AWS


### Description
Beckn-ONIX is **[FIDE](https://fide.org/)** project aimed at easing setup and maintainance of a **[Beckn](https://becknprotocol.io/)** Network using reference implementations. Objectives include setting up reliable, configurable and fast Beckn network as a virtual appliance. This initiative is independent of the evolution of the Beckn protocol. This effort is also aimed at inviting contributions from the community to create secure, reliable builds for production environments.

> **Info:** Disclaimer : Beckn-onix is a reference implementation of the Beckn-onix stack. It is a reference application only and has not been tested for production environmens. However, implementers can fork this repository and build it for scale. The maintainer of this repository holds no liabillity for deployments of this application in production environments.


### Packaging overview
This packaging initiative provides a robust solution for deploying and managing Beckn-ONIX services on AWS. It is designed to ensure high availability, scalability, and resilience of Beckn-ONIX components like the Gateway, Registry, BAP, and BPP, making them ready for a Kubernetes-based environment. Additionally, it allows users the flexibility to choose managed AWS services, optimizing for production-scale deployments while reducing operational overhead.

The packaging supports a fully automated, one-click deployment solution aligned with the reference architecture, ensuring that each layer of the Beckn-ONIX stack is designed with fault tolerance, load balancing, and scaling in mind. This approach not only simplifies the deployment process but also promotes best practices in infrastructure as code, making it easier to maintain and evolve the platform in a cost-effective manner.

### Beckn-ONIX Deployment
This repository contains the source code and configuration for deploying Beckn-ONIX services stack that leverages the power of Amazon Web Services (AWS) **[Cloud Development Kit (CDK)](https://aws.amazon.com/cdk)** for infrastructure provisioning and **[Helm](https://helm.sh)** for deploying services within an Amazon Elastic Kubernetes Service (EKS) cluster.

Two mode of deployments, catering to different deployment scenarios.

#### Mode One: AWS CDK + Helm
This mode offers a comprehensive solution for users who prefer a one-click deployment approach to provisioning AWS infrastructure and deploying the Beckn-ONIX services, all in automated fashion.

* [AWS CDK One Click Deployment](documentations/01-Deployment-CDK-Beckn-ONIX.md)

#### Mode Two: Direct Helm Chart Invocation
An alternative deployment approach accommodates users with existing essential AWS infrastructure components like Amazon RDS Postgres and an Amazon EKS cluster. This mode enables the direct installation of the Sunbird RC 2.0 Helm chart without relying on AWS CDK scripts. Alternatively, you can combine both methods, utilizing CDK for provisioning specific services like the EKS cluster.

* [Helm Chart Deployment](documentations/02-Deployment-Helm-Beckn-ONIX.md)

### Beckn-ONIX reference architecture
#### Mendatory AWS services
Required AWS services to deploy and operate the Beckn-ONIX services:
* Amazon VPC
* Amazon RDS for PostgreSQL (registry and gateway)
* Amazon EKS
* Amazon ALB
* Amazon EBS and EFS volumes

#### Optional AWS services - Only for BAP and BPP
* Amazon DocumentDB with MongoDB compatibility
* Amazon Elasticache - Redis
* Amazon MQ - RabbitMQ

![Architecture](documentations/images/Beckn-ONIX-AWS-reference-arch-master.png)
9 changes: 9 additions & 0 deletions aws-cdk/beckn-cdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out
.env
6 changes: 6 additions & 0 deletions aws-cdk/beckn-cdk/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.ts
!*.d.ts

# CDK asset staging directory
.cdk.staging
cdk.out
14 changes: 14 additions & 0 deletions aws-cdk/beckn-cdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Welcome to your CDK TypeScript project

This is a blank project for CDK development with TypeScript.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

## Useful commands

* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `npx cdk deploy` deploy this stack to your default AWS account/region
* `npx cdk diff` compare deployed stack with current state
* `npx cdk synth` emits the synthesized CloudFormation template
220 changes: 220 additions & 0 deletions aws-cdk/beckn-cdk/bin/beckn-cdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { StackProps } from 'aws-cdk-lib';
import { ConfigProps, getConfig } from '../lib/config';

import { VpcStack } from '../lib/vpc-stack';
import { RdsStack } from '../lib/rds-stack';
import { EksStack } from '../lib/eks-stack';
import { RedisStack } from '../lib/redis-stack';
import { DocumentDbStack } from '../lib/documentdb-stack';
import { RabbitMqStack } from '../lib/rabbitmq-stack';

import { HelmRegistryStack } from '../lib/helm-registry';
import { HelmGatewayStack } from '../lib/helm-gateway';
import { HelmCommonServicesStack } from '../lib/helm-beckn-common-services';
import { HelmBapStack } from '../lib/helm-bap';
import { HelmBppStack } from '../lib/helm-bpp';


const config = getConfig();
const app = new cdk.App();

type AwsEnvStackProps = StackProps & {
config: ConfigProps;
};

// Retrieve AWS Account ID and Region from the environment
const accountId = config.ACCOUNT;
const region = config.REGION;

if (!accountId || !region) {
console.error("AWS_ACCOUNT_ID or AWS_REGION is missing from .env file");
process.exit(1);
}

// Common environment configuration for all stacks
const env = { account: accountId, region: region };

// Function to deploy registry environment
const deployRegistry = () => {
var envC = "registry";
const vpcStack = new VpcStack(app, 'RegistryVpcStack', { config: config, env });
const eksStack = new EksStack(app, 'RegistryEksStack', { config: config, vpc: vpcStack.vpc, env });
const rdsStack = new RdsStack(app, 'RegistryRdsStack', { config: config, vpc: vpcStack.vpc, envC: envC, env });

new HelmRegistryStack(app, 'HelmRegistryStack', {
config: config,
rdsHost: rdsStack.rdsHost,
rdsPassword: rdsStack.rdsPassword,
eksCluster: eksStack.cluster,
env,
});
};

// Function to deploy gateway environment
const deployGateway = () => {
var envC = "gateway";
const vpcStack = new VpcStack(app, 'GatewayVpcStack', { config: config, env });
const eksStack = new EksStack(app, 'GatewayEksStack', { config: config, vpc: vpcStack.vpc, env });
const rdsStack = new RdsStack(app, 'GatewayRdsStack', { config: config, vpc: vpcStack.vpc, envC: envC, env });

new HelmGatewayStack(app, 'HelmGatewayStack', {
config: config,
rdsHost: rdsStack.rdsHost,
rdsPassword: rdsStack.rdsPassword,
eksCluster: eksStack.cluster,
env,
});

};

// Function to deploy BAP environment
const deployBAP = () => {
const vpcStack = new VpcStack(app, 'BapVpcStack', { config: config, env });
const eksStack = new EksStack(app, 'BapEksStack', {config: config, vpc: vpcStack.vpc, env });

// aws common services deployed through aws managed services
// rabbit mq -
// new DocumentDbStack(app, 'BapDocumentDbStack', { config: config, vpc: vpcStack.vpc, env });
// new RedisStack(app, 'BapRedisStack', { vpc: vpcStack.vpc, env });
// new RabbitMqStack(app, 'BapRabbitMqStack', { config: config, vpc: vpcStack.vpc, env });

// bitnami - common services on eks - self hosted
new HelmCommonServicesStack(app, 'HelmBapCommonServicesStack', {
config: config,
eksCluster: eksStack.cluster,
service: 'bap',
env,
});

new HelmBapStack(app, 'HelmBapStack', {
config: config,
eksCluster: eksStack.cluster,
vpc: vpcStack.vpc,
eksSecGrp: eksStack.eksSecGrp,
isSandbox: false,
env,
});

};

// Function to deploy BPP environment
const deployBPP = () => {
const vpcStack = new VpcStack(app, 'BppVpcStack', {config: config, env });
const eksStack = new EksStack(app, 'BppEksStack', {config: config, vpc: vpcStack.vpc, env });

//if aws
// new DocumentDbStack(app, 'BppDocumentDbStack', { config: config, vpc: vpcStack.vpc, env });
// new RedisStack(app, 'BppRedisStack', { vpc: vpcStack.vpc, env });
// new RabbitMqStack(app, 'BppRabbitMqStack', { config: config, vpc: vpcStack.vpc, env });

// if bitnami
new HelmCommonServicesStack(app, 'HelmBapCommonServicesStack', {
config: config,
eksCluster: eksStack.cluster,
service: 'bpp',
env,
});

new HelmBppStack(app, 'HelmBppStack', {
config: config,
eksCluster: eksStack.cluster,
vpc: vpcStack.vpc,
eksSecGrp: eksStack.eksSecGrp,
isSandbox: false,
env,
});
};

// Function to deploy sandbox environment (all stacks)
const deploySandbox = () => {
var envC = "sandbox";
const vpcStack = new VpcStack(app, 'VpcStack', {config: config, env });
const eksStack = new EksStack(app, 'EksStack', {config: config, vpc: vpcStack.vpc, env });
const rdsStack = new RdsStack(app, 'RdsStack', { config: config, vpc: vpcStack.vpc, envC: envC, env });

new HelmRegistryStack(app, 'HelmRegistryStack', {
config: config,
rdsHost: rdsStack.rdsHost,
rdsPassword: rdsStack.rdsPassword,
eksCluster: eksStack.cluster,
env,
});

new HelmGatewayStack(app, 'HelmGatewayStack', {
config: config,
rdsHost: rdsStack.rdsHost,
rdsPassword: rdsStack.rdsPassword,
eksCluster: eksStack.cluster,
env,
});

// aws
// new DocumentDbStack(app, 'DocumentDbStack', { config: config, vpc: vpcStack.vpc, env });
// new RedisStack(app, 'RedisStack', { vpc: vpcStack.vpc, env });
// new RabbitMqStack(app, 'RabbitMqStack', { config: config, vpc: vpcStack.vpc, env });

// default - bitnami
new HelmCommonServicesStack(app, 'BapHelmCommonServicesStack', {
config: config,
eksCluster: eksStack.cluster,
service: 'bap',
env,
});

new HelmCommonServicesStack(app, 'BppHelmCommonServicesStack', {
config: config,
eksCluster: eksStack.cluster,
service: 'bpp',
env,
});

new HelmBapStack(app, 'HelmBapStack', {
config: config,
eksCluster: eksStack.cluster,
vpc: vpcStack.vpc,
eksSecGrp: eksStack.eksSecGrp,
isSandbox: true,
env,
});

new HelmBppStack(app, 'HelmBppStack', {
config: config,
eksCluster: eksStack.cluster,
vpc: vpcStack.vpc,
eksSecGrp: eksStack.eksSecGrp,
isSandbox: true,
env,
});
};

// Retrieve the environment from CDK context
const environment = app.node.tryGetContext('env');

// Deploy based on the selected environment
switch (environment) {
case 'sandbox':
console.log('Deploying sandbox environment...');
deploySandbox();
break;
case 'registry':
console.log('Deploying registry environment...');
deployRegistry();
break;
case 'gateway':
console.log('Deploying gateway environment...');
deployGateway();
break;
case 'bap':
console.log('Deploying BAP environment...');
deployBAP();
break;
case 'bpp':
console.log('Deploying BPP environment...');
deployBPP();
break;
default:
console.error('Unknown environment specified.');
process.exit(1);
}
12 changes: 12 additions & 0 deletions aws-cdk/beckn-cdk/cdk.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"availability-zones:account=365975017663:region=ap-south-1": [
"ap-south-1a",
"ap-south-1b",
"ap-south-1c"
],
"availability-zones:account=471112672919:region=ap-south-1": [
"ap-south-1a",
"ap-south-1b",
"ap-south-1c"
]
}
72 changes: 72 additions & 0 deletions aws-cdk/beckn-cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"app": "npx ts-node --prefer-ts-exts bin/beckn-cdk.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false
}
}
Loading