def add_cloudtrail(c, TrailName, model, named=False): cfn_name = c.scrub_name(TrailName + "Trail") kw_args = {"IncludeGlobalServiceEvents": True} if named: kw_args["TrailName"] = TrailName if "logging" in model: kw_args["IsLogging"] = model["logging"] if "bucket" in model: kw_args["DependsOn"] = c.scrub_name(model["bucket"] + "Bucket") kw_args["S3BucketName"] = model["bucket"] if "multiregion" in model: kw_args["IsMultiRegionTrail"] = model["multiregion"] if "GlobalEvents" in model: kw_args["IncludeGlobalServiceEvents"] = model["GlobalEvents"] _LOGGER.debug("Adding Trail to :{}".format(c.current_account)) c.template[c.current_account].add_resource(Trail(cfn_name, **kw_args)) if c.config['global']['template_outputs'] == "enabled": c.template[c.current_account].add_output([ Output(cfn_name + "Arn", Description="Bucket " + TrailName + " ARN", Value=GetAtt(cfn_name, "Arn"), Export=Export(Sub("${AWS::StackName}-" + cfn_name + "Arn"))) ])
def gen_cloudtrail(): trail = Trail("CloudTrail", TrailName="CloudTrail", IsLogging=True, IsMultiRegionTrail=True, IncludeGlobalServiceEvents=True, S3BucketName=Ref(parameters['LogBucket']), SnsTopicName=Ref(parameters['SnsTopic'])) return trail
"Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Resource": Join("", [ "arn:aws:s3:::", Ref("S3Bucket"), "/AWSLogs/", Ref("AWS::AccountId"), "/*" ]), "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } }] }, )) t.add_resource( Trail("Trail", S3BucketName=Ref("S3Bucket"), IsLogging=True, EnableLogFileValidation=True, IncludeGlobalServiceEvents=True, IsMultiRegionTrail=True, DependsOn=["BucketPolicy"])) print(t.to_json())
def generate_template(service_name): t = Template() t.add_version('2010-09-09') t.add_description("""\ AWS CloudFormation Template for AWS Exploitation Lab """) t.add_mapping("PublicRegionMap", ami_public_mapping) t.add_mapping("PrivateRegionMap", ami_private_mapping) keyname_param = t.add_parameter( Parameter( 'KeyName', ConstraintDescription= 'must be the name of an existing EC2 KeyPair.', Description= 'Name of an existing EC2 KeyPair to enable SSH access to \ the instance', Type='AWS::EC2::KeyPair::KeyName', )) sshlocation_param = t.add_parameter( Parameter( 'SSHLocation', Description= ' The IP address range that can be used to SSH to the EC2 \ instances', Type='String', MinLength='9', MaxLength='18', Default='0.0.0.0/32', AllowedPattern= "(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})", ConstraintDescription=( "must be a valid IP CIDR range of the form x.x.x.x/x."), )) instanceType_param = t.add_parameter( Parameter( 'InstanceType', Type='String', Description='WebServer EC2 instance type', Default='t2.micro', AllowedValues=[ 't2.micro', 't2.small', 't2.medium', 'm3.medium', 'm3.large', 'm3.xlarge', 'm3.2xlarge', ], ConstraintDescription='must be a valid EC2 instance type.', )) ref_stack_id = Ref('AWS::StackId') ec2_role = t.add_resource( Role("%sEC2Role" % service_name, AssumeRolePolicyDocument=awacs.aws.Policy(Statement=[ awacs.aws.Statement( Effect=awacs.aws.Allow, Action=[awacs.aws.Action("sts", "AssumeRole")], Principal=awacs.aws.Principal("Service", ["ec2.amazonaws.com"])) ]))) ec2_role.ManagedPolicyArns = ["arn:aws:iam::aws:policy/ReadOnlyAccess"] ec2_snapshot_policy_document = awacs.aws.Policy(Statement=[ awacs.aws.Statement(Sid="PermitEC2Snapshots", Effect=awacs.aws.Allow, Action=[ awacs.aws.Action("ec2", "CreateSnapshot"), awacs.aws.Action("ec2", "ModifySnapshotAttribute"), ], Resource=["*"]) ]) ec2_snapshot_policy = Policy(PolicyName="EC2SnapshotPermissions", PolicyDocument=ec2_snapshot_policy_document) priv_ec2_role = t.add_resource( Role("%sPrivEC2Role" % service_name, AssumeRolePolicyDocument=awacs.aws.Policy(Statement=[ awacs.aws.Statement( Effect=awacs.aws.Allow, Action=[awacs.aws.Action("sts", "AssumeRole")], Principal=awacs.aws.Principal("Service", ["ec2.amazonaws.com"])) ]), Policies=[ec2_snapshot_policy])) priv_ec2_role.ManagedPolicyArns = [ "arn:aws:iam::aws:policy/ReadOnlyAccess" ] VPC_ref = t.add_resource( VPC('VPC', CidrBlock='10.0.0.0/16', Tags=Tags(Application=ref_stack_id))) instanceProfile = t.add_resource( InstanceProfile("InstanceProfile", InstanceProfileName="%sInstanceRole" % (service_name), Roles=[Ref(ec2_role)])) privInstanceProfile = t.add_resource( InstanceProfile("PrivInstanceProfile", InstanceProfileName="%sPrivInstanceRole" % (service_name), Roles=[Ref(priv_ec2_role)])) public_subnet = t.add_resource( Subnet('%sSubnetPublic' % service_name, MapPublicIpOnLaunch=True, CidrBlock='10.0.1.0/24', VpcId=Ref(VPC_ref), Tags=Tags(Application=ref_stack_id, Name="%sSubnet_public" % (service_name)))) private_subnet = t.add_resource( Subnet('%sSubnetPrivate' % service_name, MapPublicIpOnLaunch=False, CidrBlock='10.0.2.0/24', VpcId=Ref(VPC_ref), Tags=Tags(Application=ref_stack_id, Name="%sSubnet_private" % (service_name)))) internetGateway = t.add_resource( InternetGateway('InternetGateway', Tags=Tags(Application=ref_stack_id, Name="%sInternetGateway" % service_name))) gatewayAttachment = t.add_resource( VPCGatewayAttachment('AttachGateway', VpcId=Ref(VPC_ref), InternetGatewayId=Ref(internetGateway))) routeTable = t.add_resource( RouteTable('RouteTable', VpcId=Ref(VPC_ref), Tags=Tags(Application=ref_stack_id, Name="%sRouteTable" % service_name))) route = t.add_resource( Route( 'Route', DependsOn='AttachGateway', GatewayId=Ref('InternetGateway'), DestinationCidrBlock='0.0.0.0/0', RouteTableId=Ref(routeTable), )) # Only associate this Route Table with the public subnet subnetRouteTableAssociation = t.add_resource( SubnetRouteTableAssociation( 'SubnetRouteTableAssociation', SubnetId=Ref(public_subnet), RouteTableId=Ref(routeTable), )) instanceSecurityGroup = t.add_resource( SecurityGroup( 'InstanceSecurityGroup', GroupDescription='%sSecurityGroup' % service_name, SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp=Ref(sshlocation_param)), SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='0', ToPort='65535', CidrIp="10.0.0.0/8"), ], VpcId=Ref(VPC_ref), )) public_instance = t.add_resource( Instance( "Public%sInstance" % service_name, ImageId=FindInMap("PublicRegionMap", Ref("AWS::Region"), "AMI"), InstanceType=Ref(instanceType_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty(GroupSet=[Ref(instanceSecurityGroup)], AssociatePublicIpAddress='true', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(public_subnet)) ], UserData=Base64(public_instance_userdata), Tags=Tags(Application=ref_stack_id, Name='%sPublicInstance' % (service_name)))) private_instance = t.add_resource( Instance( "Private%sInstance" % service_name, ImageId=FindInMap("PrivateRegionMap", Ref("AWS::Region"), "AMI"), InstanceType=Ref(instanceType_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty(GroupSet=[Ref(instanceSecurityGroup)], DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(private_subnet)) ], UserData=Base64(private_instance_userdata), Tags=Tags(Application=ref_stack_id, Name='%sPrivateInstance' % (service_name)), IamInstanceProfile="%sPrivInstanceRole" % (service_name))) outputs = [] outputs.append( Output( "PublicIP", Description="IP Address of Public Instance", Value=GetAtt(public_instance, "PublicIp"), )) t.add_output(outputs) # Set up S3 Bucket and CloudTrail S3Bucket = t.add_resource(Bucket("S3Bucket", DeletionPolicy="Retain")) S3PolicyDocument = awacs.aws.PolicyDocument( Id='EnforceServersideEncryption', Version='2012-10-17', Statement=[ awacs.aws.Statement( Sid='PermitCTBucketPut', Action=[s3.PutObject], Effect=awacs.aws.Allow, Principal=awacs.aws.Principal("Service", ["cloudtrail.amazonaws.com"]), Resource=[Join('', [s3.ARN(''), Ref(S3Bucket), "/*"])], ), awacs.aws.Statement( Sid='PermitCTBucketACLRead', Action=[s3.GetBucketAcl], Effect=awacs.aws.Allow, Principal=awacs.aws.Principal("Service", ["cloudtrail.amazonaws.com"]), Resource=[Join('', [s3.ARN(''), Ref(S3Bucket)])], ) ]) S3BucketPolicy = t.add_resource( BucketPolicy("BucketPolicy", PolicyDocument=S3PolicyDocument, Bucket=Ref(S3Bucket), DependsOn=[S3Bucket])) myTrail = t.add_resource( Trail( "CloudTrail", IsLogging=True, S3BucketName=Ref(S3Bucket), DependsOn=["BucketPolicy"], )) myTrail.IsMultiRegionTrail = True myTrail.IncludeGlobalServiceEvents = True return t.to_json()
"Action": "s3:PutObject", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Resource": Join("", [ "arn:aws:s3:::", Ref(S3Bucket), "/AWSLogs/", Ref("AWS::AccountId"), "/*" ]), "Effect": "Allow", "Sid": "AWSCloudTrailWrite", "Condition": { "StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"} } }] }, Bucket=Ref(S3Bucket), )) myTrail = t.add_resource(Trail( "myTrail", IsLogging=True, S3BucketName=Ref(S3Bucket), SnsTopicName=GetAtt(Topic, "TopicName"), DependsOn=["BucketPolicy", "TopicPolicy"], )) print(t.to_json())
# CloudWatch Log Group where CloudTrail will log CloudTrailLogs = t.add_resource(LogGroup("CloudTrailLogs")) CloudTrail = t.add_resource( Trail( "CloudTrail", DependsOn=["LogPolicy"], # ARN of a log group to which CloudTrail logs will be delivered CloudWatchLogsLogGroupArn=GetAtt("CloudTrailLogs", "Arn"), # Role that Amazon CloudWatch Logs assumes to write logs to a log group CloudWatchLogsRoleArn=GetAtt("CloudTrailLoggingRole", "Arn"), # Indicates whether CloudTrail validates the integrity of log files EnableLogFileValidation=True, # Whether the trail is publishing events from global services, such as IAM, to the log files IncludeGlobalServiceEvents=True, # Indicates whether the CloudTrail trail is currently logging AWS API calls IsLogging=True, # Whether the trail is created in the region in which you create the stack or in all regions IsMultiRegionTrail=True, # The AWS KMS key ID that you want to use to encrypt CloudTrail logs KMSKeyId=Ref("MasterKey"), # The name of the Amazon S3 bucket where CloudTrail publishes log files S3BucketName=Ref("LogBucket"), # An Amazon S3 object key prefix that precedes the name of all log files # S3KeyPrefix="", # The name of an Amazon SNS topic that is notified when new log files are published # SnsTopicName=GetAtt(Topic, "TopicName"), )) # The AWS KMS key used to encrypt CloudTrail logs # https://docs.aws.amazon.com/awscloudtrail/latest/userguide/default-cmk-policy.html MasterKey = t.add_resource(
TopicPolicy("CloudtrailTopicPolicy", Topics=[Ref(cloudtrail_topic)], PolicyDocument=Policy(Statement=[ Statement(Sid="AWSCloudTrailSNSPolicy", Effect=Allow, Principal=Principal( "Service", ["cloudtrail.amazonaws.com"]), Action=[Action("sns", "publish")], Resource=[Ref(cloudtrail_topic)]) ]))) cloudtrail = t.add_resource( Trail("CloudTrail", IncludeGlobalServiceEvents=True, IsLogging=True, IsMultiRegionTrail=True, S3BucketName=Ref(bucket), SnsTopicName=Ref(cloudtrail_topic), DependsOn="BucketPolicy")) t.add_resource( Alarm( "LambdaErrorsAlarm", ComparisonOperator='GreaterThanThreshold', EvaluationPeriods=1, MetricName='Errors', Namespace='AWS/Lambda', Dimensions=[MetricDimension(Name='FunctionName', Value=Ref(function))], Period=300, Statistic='Maximum', Threshold='0',
} ] }, Bucket=Ref(AWSCloudTrailBucket), )) S3DeliveryTrail = t.add_resource(Trail( "S3DeliveryTrail", IsLogging=True, S3BucketName=Ref(AWSCloudTrailBucket), DependsOn=["BucketPolicy"], EventSelectors=[ EventSelector( IncludeManagementEvents=True, DataResources=[ DataResource( Values=[ Join("",["arn:aws:s3:::",Ref(IncommingBucket),"/",S3_OBJECT_Key]) ], Type="AWS::S3::Object", ), ], ReadWriteType="All", ), ], )) # Show cerated ressources t.add_output( [Output( "S3DeliveryTrail", Description="Cloudtrail to detect drift changes within S3",
def __init__(self, unit_title, template): """ AWS - http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudtrail-trail.html Troposphere - https://github.com/cloudtools/troposphere/blob/master/troposphere/cloudtrail.py :param unit_title: Name of the Cloudtrail Unit e.g. MyCloudTrail :param template: The troposphere template to add the Cloudtrail and s3 troposphere objects to. """ trail_title = unit_title + 'Trail' s3_title = (trail_title + 'AmzS3').lower() policy = { "Version": "2012-10-17", "Statement": [{ "Sid": "AWSCloudTrailAclCheck20150319", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::mycloudtrailamzs3" }, { "Sid": "AWSCloudTrailWrite20150319", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "s3:PutObject", "Resource": Join('', [ "arn:aws:s3:::", s3_title, "/AWSLogs/", { 'Ref': 'AWS::AccountId' }, "/*" ]), "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } }] } # Create S3 Bucket for Cloud Trail Log self.s3_b_trail = S3(unit_title=trail_title, template=template, s3_access='BucketOwnerFullControl', bucket_policy=policy) # Create Cloudtrail Trail self.trail = template.add_resource( Trail(trail_title, IsLogging=True, S3BucketName=self.s3_b_trail.s3_b.title, EnableLogFileValidation=True, IncludeGlobalServiceEvents=True, IsMultiRegionTrail=True, DependsOn=[self.s3_b_trail.s3_b_policy.title])) template.add_output( Output( trail_title, Value=Join('', [ Ref(self.trail), ' is a managed AWS Cloudtrail Trail, created with Amazonia as part of stack name - ', Ref('AWS::StackName') ]), Description='Amazonia Cloudtrail'))
"/AWSLogs/", Ref("AWS::AccountId"), "/*", ], ), "Effect": "Allow", "Sid": "AWSCloudTrailWrite", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } }, }, ], }, Bucket=Ref(S3Bucket), )) myTrail = t.add_resource( Trail( "myTrail", IsLogging=True, S3BucketName=Ref(S3Bucket), SnsTopicName=GetAtt(topic, "TopicName"), DependsOn=[bucket_policy, topic_policy], )) print(t.to_json())