######################################################################################### # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # # SPDX-License-Identifier: MIT-0 # # # # Permission is hereby granted, free of charge, to any person obtaining a copy of this # # software and associated documentation files (the "Software"), to deal in the Software # # without restriction, including without limitation the rights to use, copy, modify, # # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # # permit persons to whom the Software is furnished to do so. # # # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ######################################################################################### from __future__ import print_function import boto3 import json import sys import os from policy import MFAuth from botocore import config if 'solution_identifier' in os.environ: solution_identifier= json.loads(os.environ['solution_identifier']) user_agent_extra_param = {"user_agent_extra":solution_identifier} boto_config = config.Config(**user_agent_extra_param) else: boto_config = None if 'cors' in os.environ: cors = os.environ['cors'] else: cors = '*' default_http_headers = { 'Access-Control-Allow-Origin': cors, 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload', 'Content-Security-Policy' : "base-uri 'self'; upgrade-insecure-requests; default-src 'none'; object-src 'none'; connect-src none; img-src 'self' data:; script-src blob: 'self'; style-src 'self'; font-src 'self' data:; form-action 'self';" } application = os.environ['application'] environment = os.environ['environment'] servers_table_name = '{}-{}-servers'.format(application, environment) apps_table_name = '{}-{}-apps'.format(application, environment) waves_table_name = '{}-{}-waves'.format(application, environment) servers_table = boto3.resource('dynamodb').Table(servers_table_name) apps_table = boto3.resource('dynamodb').Table(apps_table_name) waves_table = boto3.resource('dynamodb').Table(waves_table_name) def lambda_handler(event, context): # Verify user has access to run ec2 replatform functions. auth = MFAuth() authResponse = auth.getUserResourceCreationPolicy(event, 'EC2') if authResponse['action'] != 'allow': return {'headers': {**default_http_headers}, 'statusCode': 401, 'body': json.dumps(authResponse)} stackresultset = [] try: body = json.loads(event['body']) if 'waveid' not in body: return {'headers': {**default_http_headers}, 'statusCode': 400, 'body': 'waveid is required'} if 'accountid' not in body: return {'headers': {**default_http_headers}, 'statusCode': 400, 'body': 'Target AWS Account Id is required'} except Exception as e: print(e) return {'headers': {**default_http_headers}, 'statusCode': 400, 'body': 'malformed json input'} try: # Read Apps Dynamo DB Table getapp = scan_dynamodb_table('app') msgapp= 'Unable to Retrieve Data from Dynamo DB App Table' if getapp is not None and "ERROR" in getapp: return {'headers': {**default_http_headers}, 'statusCode': 400, 'body':msgapp } apps = sorted(getapp, key = lambda i: i['app_name']) # Read Waves Dynamo DB Table getwave = scan_dynamodb_table('wave') msgwave= 'Unable to Retrieve Data from Dynamo DB Wave Table' if getwave is not None and "ERROR" in getwave: return {'headers': {**default_http_headers}, 'statusCode': 400, 'body': msgwave} waves = sorted(getwave, key = lambda i: i['wave_name']) getserver = scan_dynamodb_table('server') msgserver= 'Unable to Retrieve Data from Dynamo DB Server Table' if getserver is not None and "ERROR" in getserver: return {'headers': {**default_http_headers}, 'statusCode': 400, 'body': msgserver} servers = sorted(getserver, key = lambda i: i['server_name']) # Get Wave name wavename='' for wave in waves: if str(wave['wave_id']) == body['waveid']: for character in wave['wave_name']: if character.isalnum(): wavename += character # App Table Attributes for S3 Path Generation for app in apps: appname='' appid='' projectname='' accountid='' if 'wave_id' in app: if str(app['wave_id']) == body['waveid']: for character in app['app_name']: if character.isalnum(): appname += character print('App Name :' + appname) for character in app['app_id']: if character.isalnum(): appid += character print('App Id :' + appid) for character in app['aws_accountid']: if character.isnumeric(): accountid += character #AWS Account Id to Create S3 Path aws_account_id = context.invoked_function_arn.split(":")[4] gfbuild_bucket = "{}-{}-{}-gfbuild-cftemplates".format( application, environment, aws_account_id) #gfbuild_bucket='mfcloudformationtemplates' print('S3 Bucket to Load Cloud formation Templates'+gfbuild_bucket) #S3 path and Json File s3_path=accountid+'/'+wavename+'/CFN_Template_'+appid+'_'+appname+'.yaml' #s3_path='CFN_Template_'+appid+'_'+appname+'.json' print('S3 Path Along with JSON File:'+ s3_path) #Later Enchancement to deploy the stack template_url='https://'+gfbuild_bucket+'.s3.amazonaws.com/'+s3_path; s3 = boto3.client('s3') try: result = s3.get_bucket_policy(Bucket=gfbuild_bucket) data = json.loads(result['Policy']) totalstatements=len(data['Statement']) except Exception: pass json_data = json.dumps({}) totalstatements = 0 data={"Statement": []} ObjectPermission = { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456:root" }, "Action": ["s3:GetObject","s3:GetObjectVersion"], "Resource": "arn:aws:s3:::s3bcucket/*" } i=0 accountarnval='arn:aws:iam::'+accountid+':root' s3bucketname='arn:aws:s3:::'+gfbuild_bucket s3bucketobjects='arn:aws:s3:::'+gfbuild_bucket+'/*' accountexists='No' while i