def __init__(self, scope: core.Construct, id: str, vpc: ec2.Vpc, lambdasg: ec2.SecurityGroup, bastionsg: ec2.SecurityGroup, kmskey, **kwargs) -> None: super().__init__(scope, id, **kwargs) prj_name = self.node.try_get_context('project_name') env_name = self.node.try_get_context('env') creds_json_template = {'username': '******'} db_creds = sm.Secret( self, id="db-secret", secret_name=f'{env_name}-rds-secret', generate_secret_string=sm.SecretStringGenerator( include_space=False, # no space in secret password_length=12, generate_string_key= 'rds-password', # key in json dictionary for the password exclude_punctuation=True, secret_string_template=json.dumps(creds_json_template))) db_name = f'pryancdkdb' db_mysql = rds.DatabaseCluster( self, id=f'{env_name}-mysql', default_database_name=db_name, engine=rds.DatabaseClusterEngine.aurora_mysql( version=rds.AuroraMysqlEngineVersion.VER_5_7_12), master_user=rds.Login( username='******', password=db_creds.secret_value_from_json('rds-password')), instance_props=rds.InstanceProps( vpc=vpc, vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.ISOLATED), # will pick one of the isolated Subnets from the vpc instance_type=ec2.InstanceType( instance_type_identifier='t3.small')), instances=1, storage_encrypted=True, storage_encryption_key=kmskey, removal_policy=core.RemovalPolicy.DESTROY) # we need to define the ingress rules for rds db_mysql.connections.allow_default_port_from( lambdasg, 'Access from Lambda Functions') db_mysql.connections.allow_default_port_from( bastionsg, "Access from bastion host") # ssm ssm.StringParameter(self, id=f'{env_name}-db-host', parameter_name=f"/{env_name}/db-host", string_value=db_mysql.cluster_endpoint.hostname) ssm.StringParameter(self, id=f'{env_name}-db-name', parameter_name=f"/{env_name}/db-name", string_value=db_name)
def __init__(self, scope: core.Construct, id: str, vpc, sg, redissg, kmskey, **kwargs) -> None: super().__init__(scope, id, **kwargs) rdskey = kms.Key.from_key_arn(self, "rdskey", key_arn=kmskey) db_mysql = rds.DatabaseCluster( self, "Dev_MySQL", default_database_name="msadev", engine=rds.DatabaseClusterEngine.AURORA_MYSQL, engine_version="5.7.12", master_user=rds.Login(username="******"), instance_props=rds.InstanceProps( vpc=vpc, vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.ISOLATED), instance_type=ec2.InstanceType( instance_type_identifier="t3.medium")), instances=1, parameter_group=rds.ClusterParameterGroup. from_parameter_group_name( self, "paramter-group-msadev", parameter_group_name="default.aurora-mysql5.7"), kms_key=rdskey) sgId = ec2.SecurityGroup.from_security_group_id(self, "sgid", sg) redis_sg = ec2.SecurityGroup.from_security_group_id( self, "redissgid", redissg) db_mysql.connections.allow_default_port_from(sgId, "Access from Bastion") db_mysql.connections.allow_default_port_from(redis_sg, "Access from Redis")
def __init__(self, scope: core.Construct, id: str, props, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Aurora RDS Cluster db_Aurora_cluster = rds.DatabaseCluster( self, "ghost_db_cluster", default_database_name=f"{props['namespace']}-db", engine=rds.DatabaseClusterEngine.AURORA_MYSQL, engine_version="5.7.12", master_user=rds.Login(username="******"), instance_props=rds.InstanceProps( vpc=props['vpc'], vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.ISOLATED), security_group=props['db_security_group'], instance_type=ec2.InstanceType( instance_type_identifier="t2.small")), instances=2, parameter_group=rds.ClusterParameterGroup. from_parameter_group_name( self, "para-group-aurora", parameter_group_name="default.aurora-mysql5.7"), )
def __init__(self, scope: core.Construct, id: str, vpc: ec2.Vpc, lambdasg: ec2.SecurityGroup, bastionsg: ec2.SecurityGroup, kmskey, **kwargs) -> None: super().__init__(scope, id, **kwargs) prj_name = self.node.try_get_context("project_name") env_name = self.node.try_get_context("env") json_template = {'username': '******'} db_creds = sm.Secret( self, 'db-secret', secret_name=env_name + '/rds-secret', generate_secret_string=sm.SecretStringGenerator( include_space=False, password_length=12, generate_string_key='password', exclude_punctuation=True, secret_string_template=json.dumps(json_template))) db_mysql = rds.DatabaseCluster( self, 'mysql', default_database_name=prj_name + env_name, engine=rds.DatabaseClusterEngine.AURORA_MYSQL, engine_version="5.7.12", master_user=rds.Login( username='******', password=db_creds.secret_value_from_json('password')), instance_props=rds.InstanceProps( vpc=vpc, vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.ISOLATED), instance_type=ec2.InstanceType( instance_type_identifier="t3.small")), instances=1, parameter_group=rds.ClusterParameterGroup. from_parameter_group_name( self, 'pg-dev', parameter_group_name='default.aurora-mysql5.7'), kms_key=kmskey, removal_policy=core.RemovalPolicy.DESTROY) db_mysql.connections.allow_default_port_from( lambdasg, "Access from Lambda functions") db_mysql.connections.allow_default_port_from( bastionsg, "Allow from bastion host") #SSM Parameter ssm.StringParameter(self, 'db-host', parameter_name='/' + env_name + '/db-host', string_value=db_mysql.cluster_endpoint.hostname) ssm.StringParameter(self, 'db-name', parameter_name='/' + env_name + '/db-name', string_value=prj_name + env_name)
def create_rds(self, vpc): # Create DB rds_cluster = rds.DatabaseCluster( self, 'Database', engine=rds.DatabaseClusterEngine.AURORA, master_user=rds.Login(username='******'), instance_props=rds.InstanceProps( instance_type=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.PRIVATE), vpc=vpc)) return rds_cluster
def __init__(self, scope: core.Construct, id: str, vpc, **kwargs) -> None: super().__init__(scope, id, **kwargs) master_user = _rds.Login( username="******", password=core.SecretValue.plain_text("password")) rds = _rds.DatabaseCluster( self, "rds", engine=_rds.DatabaseClusterEngine.aurora_mysql( version=_rds.AuroraMysqlEngineVersion.VER_5_7_12), master_user=master_user, instance_props=_rds.InstanceProps( vpc=vpc, instance_type=_ec2.InstanceType("t3.medium"), security_groups=[vpc.sg], vpc_subnets=_ec2.SubnetSelection( subnets=vpc.isolated_subnets)), instances=2)
def rds_cluster(self, vpc, ec2sg, rds_type, rds_param=None): postgres = rds.DatabaseCluster( self, "adl-" + rds_type, default_database_name="adldb", engine=getattr(rds.DatabaseClusterEngine, rds_type), instance_props=rds.InstanceProps( vpc=vpc['vpc'], vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.PRIVATE), instance_type=ec2.InstanceType( instance_type_identifier="t3.medium")), master_user=rds.Login(username="******"), backup=rds.BackupProps(retention=core.Duration.days(7), preferred_window='01:00-02:00'), parameter_group=rds_param, preferred_maintenance_window="Sun:23:45-Mon:00:15", removal_policy=core.RemovalPolicy.DESTROY, storage_encrypted=True) postgres.connections.allow_from(ec2sg['ec2-sg'], ec2.Port.all_tcp())
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) #create VPC self.vpc = ec2.Vpc( self, 'SonarVPC', max_azs=3 ) #DB Security Group with required ingress rules self.sg= ec2.SecurityGroup( self, "SonarQubeSG", vpc=self.vpc, allow_all_outbound=True, description="Aurora Security Group" ) self.sg.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp(5432), "SonarDBAurora") pgroup = rds.ParameterGroup.from_parameter_group_name( self, "SonarDBParamGroup", parameter_group_name='default.aurora-postgresql11' ) #create RDS Cluster self.db= rds.DatabaseCluster(self, 'SonarDBCluster', engine= rds.DatabaseClusterEngine.aurora_postgres(version=rds.AuroraPostgresEngineVersion.VER_11_6), default_database_name= 'sonarqube', parameter_group= pgroup, master_user=rds.Login(username= "******"), instance_props= rds.InstanceProps( instance_type= ec2.InstanceType.of( ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM ), security_groups= [self.sg], vpc= self.vpc ) ) #create Cluster self.cluster= ecs.Cluster(self, "SonarCluster", capacity= ecs.AddCapacityOptions( instance_type= ec2.InstanceType('m5.large')), vpc= self.vpc ) asg= self.cluster.autoscaling_group user_data= asg.user_data user_data.add_commands('sysctl -qw vm.max_map_count=262144') user_data.add_commands('sysctl -w fs.file-max=65536') user_data.add_commands('ulimit -n 65536') user_data.add_commands('ulimit -u 4096') #Create iam Role for Task self.task_role = iam.Role( self, id= "SonarTaskRole", role_name= "SonarTaskRole", assumed_by= iam.ServicePrincipal(service= "ecs-tasks.amazonaws.com"), managed_policies= [ iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AmazonECSTaskExecutionRolePolicy") ] ) #Grant permission for Task to read secret from SecretsManager self.db.secret.grant_read(self.task_role) url = 'jdbc:postgresql://{}/sonarqube'.format(self.db.cluster_endpoint.socket_address) #create task task= ecs_patterns.ApplicationLoadBalancedEc2Service(self, "SonarService", # if a cluster is provided use the same vpc cluster= self.cluster, cpu=512, desired_count=1, task_image_options= ecs_patterns.ApplicationLoadBalancedTaskImageOptions( image=ecs.ContainerImage.from_registry("sonarqube:8.2-community"), container_port=9000, secrets={ "sonar.jdbc.username": ecs.Secret.from_secrets_manager(self.db.secret, field="username"), "sonar.jdbc.password": ecs.Secret.from_secrets_manager(self.db.secret, field="password") }, environment={ 'sonar.jdbc.url': url }, task_role= self.task_role ), memory_limit_mib=2048, public_load_balancer=True ) container = task.task_definition.default_container container.add_ulimits( ecs.Ulimit( name=ecs.UlimitName.NOFILE, soft_limit=65536, hard_limit=65536 ) )
def __init__( self, scope: core.Construct, id: str, keycloak_domain: str, vpc: ec2.IVpc = None, cluster: ecs.ICluster = None, load_balancer: elbv2.IApplicationLoadBalancer = None, log_group: logs.ILogGroup = None, keycloak_database_name: str = 'keykloak', keycloak_database_user: str = 'admin', **kwargs ) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here keycloak_task_role = iam.Role( self, 'KeycloakTastRole', assumed_by=iam.ServicePrincipal('ecs-tasks.amazonaws.com') ) keycloak_database_secret = secretsmanager.Secret( self, 'KeycloakDatabaseSecret', description='Keycloak Database Password', generate_secret_string=secretsmanager.SecretStringGenerator(exclude_punctuation=True) ) keycloak_database_cluster = rds.DatabaseCluster( self, 'KeycloakDatabaseCluster', engine= rds.DatabaseClusterEngine.AURORA, instance_props=rds.InstanceProps( instance_type=ec2.InstanceType.of( instance_class=ec2.InstanceClass.BURSTABLE3, instance_size=ec2.InstanceSize.SMALL ), vpc=vpc, ), master_user= rds.Login( username=keycloak_database_user, password=keycloak_database_secret.secret_value, ), instances=1, default_database_name=keycloak_database_name, removal_policy=core.RemovalPolicy.DESTROY, ) keycloak_hosted_zone = route53.HostedZone.from_lookup( self, 'KeycloakHostedZone', domain_name=keycloak_domain ) keycloak_certificate = acm.DnsValidatedCertificate( self, 'KeycloakCertificate', hosted_zone=keycloak_hosted_zone, domain_name='keycloak.' + keycloak_domain ) keycloak_service = ecs_patterns.ApplicationLoadBalancedFargateService( self, 'KeycloakLoadBalancedFargateService', load_balancer=load_balancer, cluster=cluster, task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions( image=ecs.ContainerImage.from_asset('keycloak'), container_port=8080, enable_logging=True, task_role=keycloak_task_role, log_driver=ecs.AwsLogDriver( stream_prefix='keycloak', log_group=log_group, ), secrets={ 'DB_PASSWORD': ecs.Secret.from_secrets_manager(keycloak_database_secret), }, environment={ 'DB_VENDOR': 'mysql', 'DB_USER': keycloak_database_user, 'DB_ADDR': keycloak_database_cluster.cluster_endpoint.hostname, 'DB_DATABASE': keycloak_database_name, # 'KEYCLOAK_LOGLEVEL': 'DEBUG', 'PROXY_ADDRESS_FORWARDING': 'true', }, ), memory_limit_mib=512, cpu=256, desired_count=1, public_load_balancer=True, domain_name= 'keycloak.' + keycloak_domain, domain_zone= keycloak_hosted_zone, protocol=elbv2.ApplicationProtocol.HTTPS, ) keycloak_service.target_group.enable_cookie_stickiness(core.Duration.seconds(24 * 60 * 60)) keycloak_service.target_group.configure_health_check( port='8080', path='/auth/realms/master/.well-known/openid-configuration', timeout=core.Duration.seconds(20), healthy_threshold_count=2, unhealthy_threshold_count=10, interval=core.Duration.seconds(30), ) keycloak_service.listener.add_certificates( 'KeycloakListenerCertificate', certificates= [ keycloak_certificate ] ) keycloak_database_cluster.connections.allow_default_port_from(keycloak_service.service, 'From Keycloak Fargate Service')
def __init__(self, scope: core.Construct, config: dict, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # create the securty group that will allow to connect to this instance # I am lazy and create only 1 SG that allows TCP 5432 from itself # database clients (lambda functions) will have TCP 5432 authorized for themselves too, # which is not necessary but harmless self.db_security_group = ec2.SecurityGroup(self, "Database Security Group", vpc=config['vpc']) self.db_security_group.add_ingress_rule(self.db_security_group, ec2.Port.tcp(5432)) self.cluster = rds.DatabaseCluster( self, config['rds']['name'], engine=rds.DatabaseClusterEngine.aurora_postgres( version=rds.AuroraPostgresEngineVersion.VER_11_7), default_database_name=config['rds']['databaseName'], master_user=rds.Login(username=config['rds']['masterUsername']), instance_props=rds.InstanceProps( vpc=config['vpc'], security_groups=[self.db_security_group])) # Add Secrets Manager Password rotation self.cluster.add_rotation_single_user() # aurora serverless is not yet support by CDK, https://github.com/aws/aws-cdk/issues/929 # escape hatch https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_raw # cfn_aurora_cluster = cluster.node.default_child # cfn_aurora_cluster.add_override("Properties.EngineMode", "serverless") # cfn_aurora_cluster.add_override("Properties.EnableHttpEndpoint",True) # Enable Data API # cfn_aurora_cluster.add_override("Properties.ScalingConfiguration", { # 'AutoPause': True, # 'MaxCapacity': 4, # 'MinCapacity': 1, # 'SecondsUntilAutoPause': 600 # }) # cluster.node.try_remove_child('Instance1') # Remove 'Server' instance that isn't required for serverless Aurora # create a custom resource to initialize the data schema function = _lambda.Function( self, config['custom resource lambda']['name'], runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.asset('./custom_resources'), handler='app.on_event', vpc=config['vpc'], environment={ 'DB_SECRET_ARN': self.get_secret_arn(), 'PYTHON_LOGLEVEL': 'DEBUG' }, security_groups=[self.db_security_group]) # add permission to access the secret function.add_to_role_policy( iam.PolicyStatement(resources=[self.get_secret_arn()], actions=["secretsmanager:GetSecretValue"])) custom_resource_provider = cr.Provider(self, 'Custom Resource Provider', on_event_handler=function) custom_resource = core.CustomResource( self, 'Custom Resource', service_token=custom_resource_provider.service_token) # Tell CFN to wait for the database to be ready before ot create the custom resource custom_resource.node.add_dependency(self.cluster)