def __init__( self, scope: cdk.Construct, id_: str, data_project: str, workflow_projects: List[str], ica_base_url: str, slack_host_ssm_name: str, slack_webhook_ssm_name: str, ): super().__init__(scope, id_) master = self.create_master_secret() jwt_portal_secret, jwt_portal_func = self.create_jwt_secret( master, ica_base_url, id_ + "Portal", data_project) jwt_workflow_secret, jwt_workflow_func = self.create_jwt_secret( master, ica_base_url, id_ + "Workflow", workflow_projects) # set the policy for the master secret to deny everyone except the rotators access self.add_deny_for_everyone_except(master, [jwt_portal_func, jwt_workflow_func]) # log rotation events to slack self.create_event_handling( [jwt_portal_secret, jwt_workflow_secret], slack_host_ssm_name, slack_webhook_ssm_name, ) # create an AWS user specifically for allowing github to come over to AWS # and get an up to date JWT set (only of the workflows JWTs) workflow_user = iam.User(self, "WorkflowUser") jwt_workflow_secret.grant_read(workflow_user)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create the IAM User to Be the Data Analyst iam.User( self, id="datalake_user", managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( "AmazonAthenaFullAccess") ], ).attach_inline_policy( iam.Policy( self, id="DatalakeUserBasic", statements=[ iam.PolicyStatement( actions=[ "lakeformation:GetDataAccess", "glue:GetTable", "glue:GetTables", "glue:SearchTables", "glue:GetDatabase", "glue:GetDatabases", "glue:GetPartitions", ], effect=iam.Effect.ALLOW, resources=["*"], ) ], )) # Create an Amazon S3 Bucket for the Data Lake _s3.Bucket(self, "cc-hiroga-datalake-cloudtrail")
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) user = Iam.User(self, "brev-user") policy_json = get_role_policy_json() policy_document = Iam.PolicyDocument.from_json(policy_json) role = Iam.Role( self, "brev-role", inline_policies={"brev-policy": policy_document}, assumed_by=Iam.ServicePrincipal("sagemaker.amazonaws.com")) policy_statements = get_user_policy_statements() allow_role_statement = Iam.PolicyStatement( actions=["iam:GetRole", "iam:PassRole"], effect=Iam.Effect.ALLOW, resources=[role.role_arn]) policy_statements.append(allow_role_statement) policy = Iam.Policy(self, "brev-policy", statements=policy_statements) policy.attach_to_user(user) access_key = Iam.CfnAccessKey(self, 'brev_access_key', user_name=user.user_name) core.CfnOutput(self, "access_key_id", value=access_key.ref) core.CfnOutput(self, "secret_access_key", value=access_key.attr_secret_access_key) core.CfnOutput(self, "iam_role", value=role.role_name)
def __init__(self, scope: core.Construct, id: str, props: SharkProps, **kwargs) -> None: super().__init__(scope, id, **kwargs) local_user = iam.User(self, "MyIAMUser") self._child_name = local_user.user_arn
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: """Instantiate class.""" super().__init__(scope, id, **kwargs) hello = HelloConstruct(self, "MyHelloConstruct", num_buckets=1) user = iam.User(self, "MyUser") hello.grant_read(user)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.pushover = get_lambda(self, "%s-lambda-pushover" % id, code='lib/stacks/%s/lambdas' % id, handler="send_to_pushover.handler", environment={ "PUSHOVER_TOKEN": env["PUSHOVER_TOKEN"], "PUSHOVER_USERKEY": env["PUSHOVER_USERKEY"], "LAMBDA_FUNCTIONS_LOG_LEVEL": "INFO", }) self.mailjet = get_lambda(self, "%s-lambda-mailjet" % id, code='lib/stacks/%s/lambdas' % id, handler="send_to_mailjet.handler", environment={ "MAILJET_API_KEY": env["MAILJET_API_KEY"], "MAILJET_API_SECRET": env["MAILJET_API_SECRET"], "MAILJET_DEFAULT_TO_ADDRESS": env["MAILJET_DEFAULT_TO_ADDRESS"], "MAILJET_FROM_ADDRESS": env["MAILJET_FROM_ADDRESS"], }) self.mailjet.grant_invoke(aws_iam.User(self, f"{id}-mail-sender"))
def create_iam(self, stream_arn ,user_name, policy_name): user = iam.User( self, "iam_user_stock_stream", user_name=user_name ) policy = iam.Policy( self, "iam_policy_stock_stream", policy_name=policy_name, statements=[ iam.PolicyStatement( resources=[ stream_arn ], actions=[ "kinesis:DescribeStream", "kinesis:PutRecord", "kinesis:PutRecords", "kinesis:GetShardIterator", "kinesis:GetRecords", "kinesis:ListShards", "kinesis:DescribeStreamSummary", "kinesis:RegisterStreamConsumer" ], ), iam.PolicyStatement( resources=[ stream_arn + "/*" ], actions=[ "kinesis:SubscribeToShard", "kinesis:DescribeStreamConsumer" ], ), iam.PolicyStatement( resources=[ # dynamodbのテーブルができたら修正するとりあえず "*" ], actions=[ "dynamodb:*" ], ), iam.PolicyStatement( resources=[ "*" ], actions=[ "cloudwatch:PutMetricData" ], ) ], users = [ user ] )
def __init__(self, scope: _core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) ks_resource, cassandra_keyspace_arn = self.create_cassandra_keyspace( 'cassandra_demo') table_resource, cassandra_table_arn = self.create_cassandra_table( table_name='country_cities', keyspace_name='cassandra_demo', keyspace_ref=ks_resource.ref, partitionkey_columns=[{ 'ColumnName': 'country', 'ColumnType': 'TEXT', }], clustering_key_columns=[{ 'Column': { 'ColumnName': 'city_name', 'ColumnType': 'TEXT', }, 'OrderBy': 'ASC' }], regular_columns=[ { 'ColumnName': 'population', 'ColumnType': 'INT' }, ], ) user = _iam.User(self, 'CassandraDemoUser', user_name='CassandraDemoUser') policy = _iam.Policy(self, 'CassandraFullDataAccess') policy.add_statements( _iam.PolicyStatement( resources=[cassandra_table_arn], actions=['cassandra:Select', 'cassandra:Modify'])) policy.attach_to_user(user) secrets = _secretsmanager.Secret(self, 'cassandra_demo_creds', secret_name='cassandra_demo_creds') code = _lambda.Code.asset('lambda/.dist/lambda.zip') cassandra_function = _lambda.Function( self, 'cassandra-demo', function_name='cassandra-demo', runtime=_lambda.Runtime.PYTHON_3_6, memory_size=1024, code=code, handler='demo_handler.handler', tracing=_lambda.Tracing.ACTIVE, environment={'CASSANDRA_CREDS': secrets.secret_arn}, ) secrets.grant_read(cassandra_function) api = _apigateway.LambdaRestApi(self, 'cassandra-demo-api', handler=cassandra_function)
def __init__(self, scope: core.Construct, id: str, shark_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) local_user = iam.User(self, "MyIAMUser", user_name=hashlib.md5( bytes(shark_name, encoding="utf-8")).hexdigest())
def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # create new IAM group and user group = iam.Group(self, "RekGroup") user = iam.User(self, "RekUser") # add IAM user to the new group user.add_to_group(group) # create S3 bucket to hold images # give new user access to the bucket bucket = s3.Bucket(self, 'Bucket') bucket.grant_read_write(user) # create DynamoDB table to hold Rekognition results table = ddb.Table(self, 'Classifications', partition_key={ 'name': 'image_name', 'type': ddb.AttributeType.STRING }) # create Lambda function lambda_function = _lambda.Function( self, 'RekFunction', runtime=_lambda.Runtime.PYTHON_3_8, handler='rekfunction.handler', code=_lambda.Code.from_asset( 'rekognition_lambda_s3_trigger/lambda'), environment={ 'BUCKET_NAME': bucket.bucket_name, 'TABLE_NAME': table.table_name }) # add Rekognition permissions for Lambda function statement = iam.PolicyStatement() statement.add_actions("rekognition:DetectLabels") statement.add_resources("*") lambda_function.add_to_role_policy(statement) # create trigger for Lambda function with image type suffixes notification = s3_notifications.LambdaDestination(lambda_function) notification.bind(self, bucket) bucket.add_object_created_notification( notification, s3.NotificationKeyFilter(suffix='.jpg')) bucket.add_object_created_notification( notification, s3.NotificationKeyFilter(suffix='.jpeg')) bucket.add_object_created_notification( notification, s3.NotificationKeyFilter(suffix='.png')) # grant permissions for lambda to read/write to DynamoDB table and bucket table.grant_read_write_data(lambda_function) bucket.grant_read_write(lambda_function)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id) # IAM Group hands_on_cdk_developers = iam.Group(self, "HandsOnCdkDevelopers", group_name="HandsOnCdkDevelopers") groups_map = {"HandsOnCdk": hands_on_cdk_developers} # IAM User for user in read_config_users(): iam.User( self, f"{user['group']}Developer-{user['first_name']}{user['last_name']}", user_name= f"{user['group']}Developer-{user['first_name']}{user['last_name']}", password=core.SecretValue.plain_text(user['password']), groups=[groups_map[user["group"]]]) # IAM Role iam.Role(self, "HandsOnCdkDevelopers-Role-PowerUserAccess", role_name="HandsOnCdkDevelopers-Role-PowerUserAccess", assumed_by=iam.AccountPrincipal( core.ScopedAws(scope).account_id), managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( "PowerUserAccess") ]) # IAM Policy iam.Policy( self, "HandsOnCdkDevelopers-Policy-SourceMfaRestriction", policy_name="HandsOnCdkDevelopers-Policy-SourceMfaRestriction", force=True, groups=[hands_on_cdk_developers], statements=[ statement for statement in read_config_source_mfa_restriction() ]) iam.Policy(self, "HandsOnCdkDevelopers-Policy-OnlySwitchRole", policy_name="HandsOnCdkDevelopers-Policy-OnlySwitchRole", force=True, groups=[hands_on_cdk_developers], statements=[ statement for statement in read_config_only_switch_role() ])
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) user = iam.User(self, 'myuser', managed_policies=[iam.ManagedPolicy.from_aws_managed_policy_name('AdministratorAccess')]) trail = cloudtrail.Trail(self, 's3-account-activity', enable_file_validation=True, include_global_service_events=True, is_multi_region_trail=True, management_events=cloudtrail.ReadWriteType.ALL) fn = _lambda.Function(self, 'cloudtrail_reactivator', description='Reactivates stopped CloudTrail logs', code=_lambda.Code.from_asset('./lambda'), handler='cloudtrail_reactivator.handler', runtime=_lambda.Runtime.PYTHON_3_8, initial_policy=[ # Allow Lambda to re-activate CloudTrail logging. iam.PolicyStatement(resources=[trail.trail_arn], actions=['cloudtrail:DescribeTrails', 'cloudtrail:GetTrailStatus', 'cloudtrail:StartLogging'], effect=iam.Effect.ALLOW), # Allow Lambda to attach policies to user. iam.PolicyStatement(resources=[user.user_arn], actions=['iam:AttachUserPolicy'], effect=iam.Effect.ALLOW, conditions={'ArnEquals': {"iam:PolicyARN": "arn:aws:iam::aws:policy/AWSDenyAll"}}) ]) topic = sns.Topic(self, 'CloudTrailLoggingStateTransition') topic.add_subscription(subs.EmailSubscription('*****@*****.**')) topic.grant_publish(fn) fn.add_environment('SNS_ARN', topic.topic_arn) # Event Pattern that defines the CloudTrail events that should trigger # the Lambda. event_pattern = events.EventPattern(source=['aws.cloudtrail'], detail={'eventName': ['StopLogging', 'DeleteTrail', 'UpdateTrail', 'RemoveTags', 'AddTags', 'CreateTrail', 'StartLogging', 'PutEventSelectors'], 'eventSource': ['cloudtrail.amazonaws.com']}) trail.on_cloud_trail_event('CloudTrailStateChange', description='Detects CloudTrail log state changes', target=events_targets.LambdaFunction(fn), event_pattern=event_pattern)
def __init__(self, scope: core.Construct, id: str, ** kwargs) -> None: super().__init__(scope, id, **kwargs) # Let us IAM Users & Groups): user1_pass = _secretsmanager.Secret(self, "user1Pass", description="Password for User1", secret_name="user1_pass" ) # Add User1 with SecretsManager Password user1 = _iam.User(self, "user1", password=user1_pass.secret_value, user_name="user1" ) # Add User2 with Literal Password user2 = _iam.User(self, "user2", password=core.SecretValue.plain_text( "Dont-Use-B@d-Passw0rds" ), user_name="user2" ) # Add IAM Group konstone_group = _iam.Group(self, "konStoneGroup", group_name="konstone_group" ) konstone_group.add_user(user2) # Login Url Autogeneration output_1 = core.CfnOutput(self, "user2LoginUrl", description="LoginUrl for User2", value=f"https://{core.Aws.ACCOUNT_ID}.signin.aws.amazon.com/console" )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here key = kms.Key.from_key_arn(self, 'kms-key', "arn:aws:kms:us-east-1:481877421625:key/46f9b783-09b8-4b81-b0f5-e9b6b3b096f7" ) secret = sm.Secret.from_secret_attributes(self,"secret", secret_arn="arn:aws:secretsmanager:us-east-1:481877421625:secret:user_password-7pv8IQ", encryption_key=key ) iam.User(self,"user", password=secret.secret_value)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) queue = sqs.Queue(self, "MyFirstQueue", visibility_timeout=core.Duration.seconds(300)) topic = sns.Topic(self, "MyFirstTopic", display_name="My First Topic") topic.add_subscription(subs.SqsSubscription(queue)) hello = CloudendureConstruct(self, "MyHelloConstruct", num_buckets=4) user = iam.User(self, "MyUser") hello.grant_read(user)
def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) ''' Create x number of users with a password with x number of random characters. This CDK script can be used to create a number of users for use in workshops or similar. Modify the permissions as needed for your purposes. ''' bucket = s3.Bucket( self, "MyFirstBucket", versioned=True, ) statement = iam.PolicyStatement(actions=permissions, resources=["*"]) group = iam.Group( self, 'test_group', managed_policies=[ iam.ManagedPolicy.from_managed_policy_arn( self, 'AWSCloud9User', managed_policy_arn="arn:aws:iam::aws:policy/AWSCloud9User") ]) group.add_to_policy(statement) users = [] for i in range(number_of_users): account = { 'password': get_random_string(password_length), 'user': f"user-{i}" } user = iam.User(self, account['user'], groups=[group], password=cdk.SecretValue.plain_text( account['password'])) # access_key = iam.CfnAccessKey(self, f"access_key-{i}", user_name = user.user_name) # print(type(access_key.attr_secret_access_key)) cloud9_env = c9.CfnEnvironmentEC2(self, f"cloud9_env_{i}", instance_type='t2.micro', automatic_stop_time_minutes=30, owner_arn=user.user_arn) users.append(account) cdk.CfnOutput(self, f"user-{i}:arn", value=user.user_name) with open('output.csv', "w") as f: dict_writer = csv.DictWriter(f, users[0].keys()) dict_writer.writeheader() dict_writer.writerows(users)
def __init__(self, app: core.App, id: str, **kwargs) -> None: super().__init__(app, id) #create an S3 bucket domainName = 'accelerate.dev' myBucket = s3.Bucket(self, 'accelerate.dev-s3bucket', bucket_name='accelerate-website', public_read_access=True, website_index_document='index.html', website_error_document='404.html', removal_policy=core.RemovalPolicy.DESTROY) myBucket.grant_public_access myBucket.add_to_resource_policy( #Grant read access to everyone in your account iam.PolicyStatement( actions=['s3:GetObject'], resources=[myBucket.arn_for_objects('*')], principals=[ iam.AccountPrincipal(account_id=core.Aws.ACCOUNT_ID) ])) myUser = iam.User(self, 'deploy_' + domainName) #Grant write access to a specific user myBucket.grant_write(myUser) hostedZone = route53.HostedZone.from_hosted_zone_attributes( self, "HostedZone_" + domainName, hosted_zone_id='Z00154093I7THXRTRF8QB', zone_name=domainName) cert = certmgr.DnsValidatedCertificate(self, "cert_" + domainName, domain_name=domainName, hosted_zone=hostedZone) distribution = cloudfront.CloudFrontWebDistribution( self, "accelerate.dev-distribution", price_class=cloudfront.PriceClass.PRICE_CLASS_100, origin_configs=[ cloudfront.SourceConfiguration( s3_origin_source=cloudfront.S3OriginConfig( s3_bucket_source=myBucket), behaviors=[cloudfront.Behavior(is_default_behavior=True)]) ], viewer_certificate=cloudfront.ViewerCertificate. from_acm_certificate(cert, aliases=['accelerate.dev'])) route53.ARecord(self, "Alias_" + domainName, zone=hostedZone, target=route53.RecordTarget.from_alias( targets.CloudFrontTarget(distribution)))
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) cfn_role = iam.Role( self, 'CloudFormationRole', assumed_by=iam.ServicePrincipal('cloudformation.amazonaws.com'), managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( 'AmazonEC2FullAccess'), iam.ManagedPolicy.from_aws_managed_policy_name( 'IAMFullAccess'), ]) alice = iam.User( self, 'Alice', user_name='alice', password=SecretValue.ssm_secure( parameter_name='/demo/permission-boundary/password', version='2', ), managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( 'AmazonEC2ReadOnlyAccess'), iam.ManagedPolicy.from_aws_managed_policy_name( 'AWSCloudFormationFullAccess'), ], ) alice.add_to_principal_policy( iam.PolicyStatement( actions=['iam:PassRole'], resources=[cfn_role.role_arn], )) alice.add_to_principal_policy( iam.PolicyStatement( actions=['iam:ListRoles'], resources=['*'], )) template = assets.Asset( self, 'Template', path='./files/template.yml', readers=[alice, cfn_role], ) CfnOutput(self, 'TemplateUrl', value=template.http_url)
def __init__(self, app: cdk.App, id: str, **kwargs) -> None: super().__init__(app, id, **kwargs) queue = sqs.Queue( self, "MyFirstQueue", visibility_timeout_sec=300, ) topic = sns.Topic(self, "MyFirstTopic", display_name="My First Topic") topic.subscribe_queue(queue) hello = HelloConstruct(self, "MyHelloConstruct", num_buckets=4) user = iam.User(self, "MyUser") hello.grant_read(user)
def __init__(self, scope: core.Construct, id: str, num: int, password: str, group: iam.Group) -> None: super().__init__(scope, id) self._buckets = [] self._users = [] for i in range(1, num + 1): user = iam.User( self, f"workshop-user-{i}", password = core.SecretValue.plain_text(password), groups = [group] ) self._users.append(user) bucket = s3.Bucket(self, f"bucket-for-user-{i}") self._buckets.append(bucket) bucket.grant_read_write(user)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here # This method will pull a String from parameter store at deployment string_param = ssm.StringParameter.value_for_string_parameter( self, "string-parameter") # This method will pull a String from parameter store at syhtnesis synth_string_param = ssm.StringParameter.value_from_lookup( self, "string-parameter") # This method will pull a SecretString that can be used as a password in another resource secure_string_param = core.SecretValue.ssm_secure( 'secure-parameter', "1") iam.User(self, "user", password=secure_string_param) core.CfnOutput(self, "deployment-parameter", value=string_param) core.CfnOutput(self, "synthesis-parameter", value=synth_string_param)
def __init__(self, scope: core.Construct, id: str, users, **kwargs) -> None: super().__init__(scope, id, **kwargs) nb_role = iam.Role( self, id, assumed_by=iam.ServicePrincipal('sagemaker.amazonaws.com')) # XXX: add ro access to some S3 bucket for user_data in users: user = user_data['email'] iam_user = iam.User(self, user, user_name=user, password=core.SecretValue.plain_text( user_data['password'])) nb = sagemaker.CfnNotebookInstance( self, 'nb_%s' % user, instance_type='ml.t2.medium', role_arn=nb_role.role_arn, notebook_instance_name='nb-%s-%s' % (id, user.translate(str.maketrans('@.', '--')))) nb_policy = iam.Policy( self, 'nb_policy_%s' % user, statements=[ iam.PolicyStatement(actions=[ 'sagemaker:CreatePresignedNotebookInstanceUrl' ], resources=[nb.ref]), iam.PolicyStatement( actions=['sagemaker:ListNotebookInstances'], resources=["*"]) ]) iam_user.attach_inline_policy(nb_policy)
def __init__(self, scope: core.Construct, id: str, bucket: s3.Bucket, capture_bucket: s3.Bucket, write_topic: sns.Topic, **kwargs) -> None: super().__init__(scope, id, **kwargs) # create an iam user "RaspberryPiUser" rasberry_pi_user = iam.User( self, "RaspberryPiUser", managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( "AWSCodeCommitPowerUser"), iam.ManagedPolicy.from_aws_managed_policy_name( "AWSIoTFullAccess") ]) # create an iam policy statement for "WriteToS3Policy" write_to_s3_policy_statement = iam.PolicyStatement( actions=["s3:PutObject"], resources=[bucket.bucket_arn, capture_bucket.bucket_arn]) # create an iam policy "WriteToS3Policy" write_to_s3_policy = iam.Policy( self, "WriteToS3Policy", statements=[write_to_s3_policy_statement], users=[rasberry_pi_user]) # create an iam policy statement to allow RaspberryPiUser to publish to sns topic publish_to_sns_topic_policy_statement = iam.PolicyStatement( actions=["sns:Publish"], resources=[write_topic.topic_arn]) # create an iam policy "PublishToSnsTopic" publish_to_sns_topic_policy = iam.Policy( self, "PublishToSnsTopicPolicy", statements=[publish_to_sns_topic_policy_statement], users=[rasberry_pi_user])
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) local_user = iam.User(self, "MyIAMUser") InnerStack(self, "InnerStack", user=local_user, **kwargs)
def create_circleci_release_user(self) -> None: self.circleci_user = aws_iam.User( self, "circleci_iam_user", user_name="CircleCIReleaseProcessIAMUser")
def __init__(self, scope: core.Construct, id: str, *, app_env: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) password = core.SecretValue.plain_text(Param.value_for_string_parameter(self, f'/{app_env}/ssm/IAM_PASSWORD')) user = iam.User(self, "staff-user", password=password) user.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("AdministratorAccess")) # FIXME: subset of required permissions
def __init__(self, scope: core.Construct, id: str, props: SharkProps, **kwargs) -> None: super().__init__(scope, id, **kwargs) local_user = iam.User(self, "MyIAMUser", user_name=props.baby_name)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) pvt_bkt = s3.Bucket( self, "abacBucket", versioned=True, # encryption=s3.BucketEncryption.KMS_MANAGED, block_public_access=s3.BlockPublicAccess(block_public_policy=True), removal_policy=core.RemovalPolicy.DESTROY ) pvt_bkt.add_to_resource_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, # actions=["s3:GetObject"], actions=["s3:*"], # resources=[pvt_bkt.arn_for_objects("file.txt")], resources=[pvt_bkt.arn_for_objects("*")], principals=[iam.AccountRootPrincipal()] ) ) # Create 3 Users: 1 Admin & 2 Normal Users # Lets generate a password for our user redRosy_new_pass = random_string_generator( self, "redRosyNewPasswordGenerator", Length=20 ) redRosy = iam.User( self, "redRosy", user_name="redRosy", password=core.SecretValue.plain_text(redRosy_new_pass.response) ) blueBob_new_pass = random_string_generator( self, "blueBobNewPasswordGenerator", Length=20 ) blueBob = iam.User( self, "blueBob", user_name="blueBob", password=core.SecretValue.plain_text(blueBob_new_pass.response) ) annoyingAdmin_new_pass = random_string_generator( self, "annoyingAdminNewPasswordGenerator", Length=20 ) annoyingAdmin = iam.User( self, "annoyingAdmin", user_name="annoyingAdmin", password=core.SecretValue.plain_text(annoyingAdmin_new_pass.response) ) teamUnicornGrp = iam.Group( self, "teamUnicorn", group_name="teamUnicorn" ) # Add Users To Group teamUnicornGrp.add_user(redRosy) teamUnicornGrp.add_user(blueBob) teamUnicornGrp.add_user(annoyingAdmin) # blueGrp1.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("AmazonS3ReadOnlyAccess")) ############################################## # We need a custom resource to TAG IAM Users # ############################################## iamUserTaggerResp = iam_user_tagger( self, "iamTagger", message=[ {"user":redRosy.user_name, "tags":[{'Key': 'teamName','Value':'teamUnicorn'}, {'Key': 'projectName','Value':'projectRed'} ] }, {"user":blueBob.user_name, "tags":[{'Key': 'teamName','Value':'teamUnicorn'}, {'Key': 'projectName','Value':'projectBlue'} ] }, {"user":annoyingAdmin.user_name, "tags":[{'Key': 'teamName','Value':'teamUnicorn'}, {'Key': 'teamAdmin','Value':'yes'} ] } ] ) """ resource = MyCustomResource( self, "iamTagger", message=[ {"user":redRosy.user_name, "tags":[{'Key': 'teamName','Value':'teamUnicorn'}, {'Key': 'projectName','Value':'projectRed'} ] }, {"user":blueBob.user_name, "tags":[{'Key': 'teamName','Value':'teamUnicorn'}, {'Key': 'projectName','Value':'projectBlue'} ] }, {"user":annoyingAdmin.user_name, "tags":[{'Key': 'teamName','Value':'teamUnicorn'}, {'Key': 'teamAdmin','Value':'yes'} ] } ] ) """ # Lets Create the IAM Role # Uses belonging to this group, will be able to asume this role accountId=core.Aws.ACCOUNT_ID teamUnicornProjectRedRole = iam.Role( self, 'teamUnicornProjectRedRoleId', assumed_by=iam.AccountPrincipal(f"{accountId}"), role_name="teamUnicornProjectRedRole" ) core.Tag.add(teamUnicornProjectRedRole, key="teamName",value="teamUnicorn") core.Tag.add(teamUnicornProjectRedRole, key="projectName",value="projectRed") teamUnicornProjectBlueRole = iam.Role( self, 'teamUnicornProjectBlueRoleId', assumed_by=iam.AccountPrincipal(f"{accountId}"), role_name="teamUnicornProjectBlueRole" ) core.Tag.add(teamUnicornProjectBlueRole, key="teamName",value="teamUnicorn") core.Tag.add(teamUnicornProjectBlueRole, key="projectName",value="projectBlue") teamUnicornTeamAdminRole = iam.Role( self, 'teamUnicornTeamAdminRoleId', assumed_by=iam.AccountPrincipal(f"{accountId}"), role_name="teamUnicornTeamAdminRole" ) core.Tag.add(teamUnicornTeamAdminRole, key="teamName",value="teamUnicorn") core.Tag.add(teamUnicornTeamAdminRole, key="teamAdmin",value="yes") # Allow Group to Assume Role grpStmt1=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[f"arn:aws:iam::{accountId}:role/teamUnicornProject*"], actions=["sts:AssumeRole"], conditions={ "StringEquals": { "iam:ResourceTag/teamName": "${aws:PrincipalTag/teamName}", "iam:ResourceTag/projectName": "${aws:PrincipalTag/projectName}" } } ) grpStmt1.sid="AllowGroupMembersToAssumeRoleMatchingTeamName" grpStmt2=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[f"arn:aws:iam::{accountId}:role/teamUnicornTeamAdminRole"], actions=["sts:AssumeRole"], conditions={ "StringEquals": { "iam:ResourceTag/teamName": "${aws:PrincipalTag/teamName}", "iam:ResourceTag/teamAdmin": "yes" } } ) grpStmt2.sid="AllowTeamAdminToAssumeRoleMatchingTeamName" teamUnicornGrp.add_to_policy( grpStmt1 ) teamUnicornGrp.add_to_policy( grpStmt2 ) # Add Permissions to the Role roleStmt1=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=["*"], actions=["s3:ListAllMyBuckets", "s3:HeadBucket"] ) roleStmt1.sid="AllowGroupToSeeBucketListInTheConsole" roleStmt2=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[pvt_bkt.bucket_arn], actions=["s3:ListBucket","s3:ListBucketVersions"], # Below condition can be used to enable listing a particular prefix in another statement # conditions={ "StringEquals" : { "s3:prefix":[""], "s3:delimiter":["/"] } } ) roleStmt2.sid="AllowRootLevelListingOfBucket" roleStmt3=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[pvt_bkt.arn_for_objects("*")], actions=["s3:Get*","s3:DeleteObjectTagging"], conditions={ "StringEquals": { "s3:ExistingObjectTag/teamName" : "${aws:PrincipalTag/teamName}", "s3:ExistingObjectTag/projectName" : "${aws:PrincipalTag/projectName}" } } ) roleStmt3.sid="ReadOnlyAccessToTeams" roleStmt4=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[pvt_bkt.arn_for_objects("*")], actions=["s3:PutObject","s3:PutObjectTagging","s3:PutObjectVersionTagging"], conditions={ "StringEquals": { "s3:RequestObjectTag/teamName" : "${aws:PrincipalTag/teamName}", "s3:RequestObjectTag/projectName" : "${aws:PrincipalTag/projectName}" } } ) roleStmt4.sid="WriteTaggedObjectOwnedByThem" roleStmt5=iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[pvt_bkt.bucket_arn, pvt_bkt.arn_for_objects("*")], actions=["s3:*"], conditions={ "StringEquals" : { "${aws:PrincipalTag/teamAdmin}": [ "yes" ] } } ) roleStmt5.sid="FullAccessToAdminsFromSameTeam" teamUnicornProjectRedRole.add_to_policy( roleStmt1 ) teamUnicornProjectRedRole.add_to_policy( roleStmt2 ) teamUnicornProjectRedRole.add_to_policy( roleStmt3 ) teamUnicornProjectRedRole.add_to_policy( roleStmt4 ) teamUnicornProjectRedRole.add_to_policy( roleStmt5 ) # Add same permissions to projectBlueRole teamUnicornProjectBlueRole.add_to_policy( roleStmt1 ) teamUnicornProjectBlueRole.add_to_policy( roleStmt2 ) teamUnicornProjectBlueRole.add_to_policy( roleStmt3 ) teamUnicornProjectBlueRole.add_to_policy( roleStmt4 ) teamUnicornProjectBlueRole.add_to_policy( roleStmt5 ) # Add same permissions to teamAdminRole teamUnicornTeamAdminRole.add_to_policy( roleStmt1 ) teamUnicornTeamAdminRole.add_to_policy( roleStmt2 ) teamUnicornTeamAdminRole.add_to_policy( roleStmt3 ) teamUnicornTeamAdminRole.add_to_policy( roleStmt4 ) teamUnicornTeamAdminRole.add_to_policy( roleStmt5 ) ########################################### ################# OUTPUTS ################# ########################################### output0 = core.CfnOutput(self, "SecuirtyAutomationFrom", value=f"{global_args.SOURCE_INFO}", description="To know more about this automation stack, check out our github page." ) output1_r = core.CfnOutput(self, "User:redRosy", value=redRosy_new_pass.response, description=f"Red Rosy User Password" ) output1_b = core.CfnOutput(self, "User:blueBob", value=blueBob_new_pass.response, description=f"Red Rosy User Password" ) output1_a = core.CfnOutput(self, "User:annoyingAdmin", value=annoyingAdmin_new_pass.response, description=f"Red Rosy User Password" ) output2 = core.CfnOutput(self, "SecurePrivateBucket", value=( f"https://console.aws.amazon.com/s3/buckets/" f"{pvt_bkt.bucket_name}" ), description=f"S3 Bucket to Test ABAC" ) output3 = core.CfnOutput(self, "Rosy-Assume-RedRole-Url", value=( f"https://signin.aws.amazon.com/switchrole?roleName=" f"{teamUnicornProjectRedRole.role_name}" f"&account=" f"{core.Aws.ACCOUNT_ID}" ), description=f"The URL for Rosy to assume teamRed Role" ) output4 = core.CfnOutput(self, "blueBob-Assume-RedRole-Url", value=( f"https://signin.aws.amazon.com/switchrole?roleName=" f"{teamUnicornProjectBlueRole.role_name}" f"&account=" f"{core.Aws.ACCOUNT_ID}" ), description=f"The URL for Bob to assume teamBlue Role" ) output5 = core.CfnOutput(self, "SampleS3UploadCommands", value=( f"aws s3api put-object-tagging --bucket {pvt_bkt.bucket_name} --key YOUR-OBJECT --tagging 'TagSet=[{{Key=projectName,Value=teamRed}}]'" ), description=f"For ProjectRed" ) output10 = core.CfnOutput(self, "User-Login-Url", value=( f"https://{core.Aws.ACCOUNT_ID}.signin.aws.amazon.com/console" ), description=f"The URL for Rosy to assume teamRed Role" )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Message timeout; used by SQS and Lambda message_timeout = core.Duration.seconds(15) # SQS queue that the Raspberry Pi will write to queue = sqs.Queue( self, 'Queue', visibility_timeout=message_timeout, receive_message_wait_time=core.Duration.seconds(20), retention_period=core.Duration.hours(1), ) # DynamoDB table that the web app will read from icao_address = dynamodb.Attribute( name='IcaoAddress', type=dynamodb.AttributeType.STRING, ) table = dynamodb.Table( self, 'Table', partition_key=icao_address, billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST, removal_policy=core.RemovalPolicy.DESTROY, ) database = timestream.CfnDatabase( self, 'Database', database_name='aircraft-database', ) table2 = timestream.CfnTable(self, 'Table2', database_name=database.ref, table_name='aircraft-table', retention_properties={ 'MemoryStoreRetentionPeriodInHours': 1, 'MagneticStoreRetentionPeriodInDays': 1, }) # IAM user for the Raspberry Pi user = iam.User(self, 'RaspberryPi') queue.grant_send_messages(user) access_key = iam.CfnAccessKey( self, 'AccessKey', user_name=user.user_name, ) # IAM role for Lambda function, so it can write to DynamoDB lambda_role = iam.Role( self, 'LambdaRole', assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( 'service-role/AWSLambdaBasicExecutionRole'), ], ) lambda_role.add_to_policy( iam.PolicyStatement( actions=[ 'timestream:CancelQuery', 'timestream:DescribeEndpoints', 'timestream:DescribeTable', 'timestream:ListMeasures', 'timestream:Select', 'timestream:WriteRecords' ], resources=['*'], # TODO: narrow down permissions )) table.grant_read_write_data(lambda_role) # Integration between SQS and Lambda event = lambda_event_sources.SqsEventSource( queue=queue, batch_size=10, ) # Lambda function that processes messages from SQS queue and updates DynamoDB table import_function = lambda_.Function( self, 'ImportFunction', description='Reads SQS messages and writes to DynamoDB', runtime=lambda_.Runtime.PYTHON_3_8, code=lambda_.Code.from_asset('lambda_import/'), timeout=message_timeout, handler='index.handler', role=lambda_role, events=[event], environment={ 'TABLE_NAME': table2.ref, }, ) # TODO: add custom log group # TODO: add metric filters for number of succesfull updates and failed updates # Lambda function that reads from DynamoDB and returns data to API Gateway api_function = lambda_.Function( self, 'ApiFunction', description='Reads from DynamoDB and returns to API GW', runtime=lambda_.Runtime.PYTHON_3_8, code=lambda_.Code.from_asset('lambda_api/'), timeout=message_timeout, handler='index.handler', role=lambda_role, environment={ 'TABLE_NAME': table.table_name, }, ) # API Gateway for requesting aircraft data api = apigateway.RestApi( self, 'Api', endpoint_types=[apigateway.EndpointType.REGIONAL], cloud_watch_role=False, ) aircraft_resource = api.root.add_resource('aircraft') aircraft_resource.add_method( http_method='GET', integration=apigateway.LambdaIntegration( api_function, proxy=True, ), ) # Static website bucket = s3.Bucket(self, 'StaticWebsite') s3_deployment.BucketDeployment( self, 'Deployment', sources=[ s3_deployment.Source.asset('html/'), ], destination_bucket=bucket, ) # Permissions between CloudFront and S3 origin_identity = cloudfront.OriginAccessIdentity(self, 'Identity') bucket.grant_read(origin_identity.grant_principal) # CloudFront distribution pointing to both S3 and API Gateway s3_origin = cloudfront.SourceConfiguration( s3_origin_source=cloudfront.S3OriginConfig( s3_bucket_source=bucket, origin_access_identity=origin_identity, ), behaviors=[ cloudfront.Behavior( default_ttl=core.Duration.days(0), min_ttl=core.Duration.days(0), max_ttl=core.Duration.days(31), is_default_behavior=True, ) ]) api_origin = cloudfront.SourceConfiguration( origin_path='/{}'.format(api.deployment_stage.stage_name), custom_origin_source=cloudfront.CustomOriginConfig( domain_name='{}.execute-api.{}.{}'.format( api.rest_api_id, self.region, self.url_suffix), ), behaviors=[ cloudfront.Behavior( default_ttl=core.Duration.seconds(0), min_ttl=core.Duration.seconds(0), max_ttl=core.Duration.seconds(0), path_pattern='/aircraft/*', ) ]) domain_name = self.node.try_get_context('domain_name') # If domain name is specified, create a certificate and alias configuration for CloudFront if domain_name is None: alias_configuration = None else: subdomain = 'aircraft.{}'.format(domain_name) zone = route53.HostedZone.from_lookup( self, 'Zone', domain_name=domain_name, ) certificate = acm.DnsValidatedCertificate( self, 'Certificate', domain_name=subdomain, hosted_zone=zone, region='us-east-1', ) alias_configuration = cloudfront.AliasConfiguration( acm_cert_ref=certificate.certificate_arn, names=[subdomain], ) distribution = cloudfront.CloudFrontWebDistribution( self, 'CDN', price_class=cloudfront.PriceClass.PRICE_CLASS_ALL, alias_configuration=alias_configuration, origin_configs=[ s3_origin, api_origin, ], ) # If domain name is specified, create a DNS record for CloudFront if domain_name is not None: route53.ARecord( self, 'DnsRecord', record_name=subdomain, target=route53.AddressRecordTarget.from_alias( alias_target=route53_targets.CloudFrontTarget( distribution)), zone=zone, ) # Outputs that are needed on the Raspberry Pi core.CfnOutput( self, 'QueueUrl', value=queue.queue_url, ) core.CfnOutput( self, 'AccessKeyId', value=access_key.ref, ) core.CfnOutput( self, 'SecretAccessKey', value=access_key.attr_secret_access_key, ) core.CfnOutput( self, 'Region', value=self.region, )
def __init__(self, parent: core.App, name: str): super().__init__(parent, name) accessible_apps = ['GWJR', 'Dev'] accessible_lamb_app_regs = [ 'arn:aws:{}:{}:{}:function:*{}*'.format(LambdaActions.name, self.region, self.account, app) for app in accessible_apps ] accessible_cfn_app_regs = [ 'arn:aws:{}:{}:{}:*{}*'.format(CFNActions.name, self.region, self.account, app) for app in accessible_apps ] accessible_iam_app_regs = [ 'arn:aws:{}::{}:role/*{}*'.format(IAMIAMActions.name, self.account, app) for app in accessible_apps ] accessible_app_regs = accessible_cfn_app_regs + accessible_iam_app_regs + accessible_lamb_app_regs self.app_access_statement = iam.PolicyStatement( actions=[ CFNActions.FULL_ACCESS, IAMIAMActions.FULL_ACCESS, LambdaActions.INVOKE_FUNCTION ], resources=accessible_app_regs) self.sb_user = iam.User( self, 'SBUser', managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( 'AWSLambdaReadOnlyAccess'), iam.ManagedPolicy.from_aws_managed_policy_name( 'IAMReadOnlyAccess'), iam.ManagedPolicy.from_aws_managed_policy_name( 'AWSCloudFormationReadOnlyAccess'), iam.ManagedPolicy.from_aws_managed_policy_name( 'AmazonRoute53ReadOnlyAccess'), iam.ManagedPolicy.from_aws_managed_policy_name( 'AmazonS3FullAccess'), iam.ManagedPolicy(self, 'SBUserPolicy', statements=[self.app_access_statement]) ]) self.sb_user_access_key = iam.CfnAccessKey( self, 'SBUserAccessKey', user_name=self.sb_user.user_name, status='Active') creds = json.dumps({ 'AWS_ACCESS_KEY_ID': self.sb_user_access_key.ref, 'AWS_SECRET_ACCESS_KEY': self.sb_user_access_key.attr_secret_access_key }) self.aws_cred_secret = PreDefinedSecret('SBCreds', creds) self.secret_stack = Secrets(self, "Secrets", authorized_users=[self.sb_user], predefined_secrets=[self.aws_cred_secret]) self.deploy_role = iam.Role( self, 'DepRol', assumed_by=pyiam.CFN_PRINCIPAL, inline_policies={ 'Pol': iam.PolicyDocument(statements=[ iam.PolicyStatement( actions=[ CFNActions.FULL_ACCESS, IAMIAMActions.FULL_ACCESS, SecretsManagerActions.FULL_ACCESS, KMSActions.FULL_ACCESS ], resources=[ 'arn:aws:{}:{}:{}:*'.format( KMSActions.name, self.region, self.account), 'arn:aws:{}:{}:{}:*{}*'.format( CFNActions.name, self.region, self.account, self.stack_name), 'arn:aws:{}::{}:role/*{}*'. format(IAMIAMActions.name, self.account, self. stack_name), 'arn:aws:{}::{}:user/*{}*'. format(IAMIAMActions.name, self.account, self. stack_name), 'arn:aws:{}::{}:policy/*{}*'. format(IAMIAMActions.name, self.account, self. stack_name), 'arn:aws:{}:{}:{}:*{}*'.format( SecretsManagerActions.name, self.region, self.account, self.stack_name), 'arn:aws:{}:{}:{}:*{}*'.format( SecretsManagerActions.name, self.region, self.account, self.aws_cred_secret.secret_name) ] + [ 'arn:aws:{}::{}:role/*{}*'.format( IAMIAMActions.name, self.account, accessible_app) for accessible_app in accessible_apps ]), iam.PolicyStatement(actions=[KMSActions.FULL_ACCESS], resources=['*']) ]) }) core.CfnOutput(self, 'DeployRoleArn', value=self.deploy_role.role_arn) core.CfnOutput(self, 'SBUserName', value=self.sb_user.user_name)