├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── awsconfig-guard-cft-gd.yaml ├── awsconfig-guard-cft.yaml ├── awsconfig-guard-tf-ec2vol.json ├── awsconfig-guard-tf-example.json ├── awsconfig-guard-tf-gd.json ├── images ├── ExampleEc2VolumeAWSConfigConfigurationItem.png ├── Scenario1-EC2VolumeJSON.png └── Scenario2-GuardDutyJSON.png ├── reinvent-sec314 ├── freetier.guard ├── guardduty.guard ├── prohibitedresources.guard └── securitygroup.guard └── reinvent24-sec314 ├── bucketpolicy.guard ├── bucketpolicy.yaml ├── demo-full.guard ├── demo-full.yaml ├── encryption.guard ├── encryption.yaml ├── prohibited-resources.guard ├── prohibited-resources.yaml ├── scenario.txt └── tags.guard /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT No Attribution 2 | 3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS Config with CloudFormation Guard 2 | 3 | AWS Config CloudFormation Guard Custom rules fit as a middle ground between Managed Rules and fully custom Lambda methods. This provides engineers and architects the ability to quickly build rules without needing to know Python, NodeJS, Java required in the other method to deploy custom rules. 4 | This guide aims to accelerate the adoption of the feature by providing workable templates, code and deployment methods. By using this quick start document, an administrator will be able to leverage AWS Config to build custom compliance rules using Configuration Item attributes. 5 | 6 | ## Prerequisites 7 | 8 | - An active AWS account. 9 | - AWS Config must be enabled in your AWS account. 10 | 11 | ## Limitations 12 | 13 | CloudFormation Guard Custom rules are only able to query key/value pairs in a given AWS Config Configuration Item JSON record. 14 | 15 | 16 | ## Document Outcomes 17 | As a Security Engineer or Operational Engineer, I want to be able to: 18 | - Understand how CloudFormation Guard (cfn-guard) policy code interacts with the AWS Config service. 19 | - Scenario 1 - Deploy a custom AWS Config Custom Rule using cfn-guard syntax to identify compliance for encrypted volumes, status of the drive as in-use AND of type GP3 for compliance. 20 | - Scenario 2 - Deploy a custom AWS Config Custom Rule using cfn-guard syntax to identify all GuardDuty recorders are compliant by having S3 Protection and Kubernetes Protection enabled. 21 | 22 | ## AWS Config & CloudFormation Guard Overview 23 | Integration Overview 24 | AWS Config provides another method to build custom rules without having to use AWS Lambda functions written in NodeJS, Java or Python. This new method leverages CloudFormation Guard (cfn-guard), as a domain-specific-language (DSL) to build policies and check AWS Config Configuration Items (CI). 25 | 26 | The cfn-guard syntax is applied to an AWS Config rule as a custom policy for the service to crawl the hierarchical JSON of each of the AWS Config resources specified. 27 | 28 | The AWS Config Configuration Item JSON, which key-value attributes, will be used in the cfn-guard policy syntax as variables assigned to their corresponding value. The variables when called in the syntax will be prepended with the ‘%’ value. In the following screenshot, there are three values used as variables and a key of ‘resourceType’ is called out and used as a filter. 29 | 30 | Example: EC2 Volume AWS Config - Configuration Item 31 | 32 | ![Ec2Config](images/ExampleEc2VolumeAWSConfigConfigurationItem.png) 33 | 34 | ## cfn-guard Syntax 35 | 36 | ### Syntax explanation of the cfn-guard 37 | 38 | # declare variable 39 | let = <'value'> 40 | 41 | # create rule and assign condition and policy 42 | rule when 43 | == <"CI json value"> { 44 | . == % 45 | } 46 | 47 | ### Implementation of cfn-guard syntax used in Scenario 1 48 | 49 | let volumestatus = 'available' 50 | let volumetype = 'gp3' 51 | let volumeencryptionstatus = true 52 | 53 | rule compliancecheck when 54 | resourceType == "AWS::EC2::Volume" { 55 | configuration.state == %volumestatus 56 | configuration.encrypted == %volumeencryptionstatus 57 | configuration.volumeType == %volumetype 58 | } 59 | 60 | ## Scenario 1 - EC2 Volume 61 | This scenario would set a custom AWS Config rule that would ensure all EC2 volumes that are not attached to an instance, are encrypted AND of the volume type GP3 would be compliant if matching the cfn-guard policy, otherwise it would be marked noncompliant. 62 | 63 | In the following text block, the first three lines define the variables by using the ‘let’ command.  They are assigned a name and value, derived from attributes from the AWS Config CI JSON previously mentioned. 64 | 65 | This next section of code is a rule block named ‘compliancecheck’ which adds a ‘when’ conditional dependency that looks for a key/value pair of ‘resourceType’ in the JSON of the CI matching ‘AWS::EC2::Volume’ and if it matched it will step through the rest of the JSON attributes and look for matches on the following three conditions of state, encrypted and volumeType.  66 | 67 | let volumestatus = 'available' 68 | let volumetype = 'gp3' 69 | let volumeencryptionstatus = true 70 | 71 | rule compliancecheck when 72 | resourceType == "AWS::EC2::Volume" { 73 | configuration.state == %volumestatus 74 | configuration.encrypted == %volumeencryptionstatus 75 | configuration.volumeType == %volumetype 76 | } 77 | 78 | ![Scenario1](images/Scenario1-EC2VolumeJSON.png) 79 | 80 | ## Scenario 1 - EC2 Volume Solution CloudFormation Code 81 | AWSTemplateFormatVersion: "2010-09-09" 82 | Description: Create AWS Config Rule using CloudFormation Guard DSL 83 | Parameters: 84 | ConfigRuleName01: 85 | Type: String 86 | Default: GUARD-Rule-01 87 | Description: Name of the AWS Config Rule 88 | 89 | 90 | Resources: 91 | 92 | ConfigGuardRule01: 93 | Type: AWS::Config::ConfigRule 94 | Properties: 95 | ConfigRuleName: !Ref ConfigRuleName01 96 | Description: Compliant if volume is available, type gp3, and encrypted conditions are met in resource 97 | Scope: 98 | ComplianceResourceTypes: 99 | - "AWS::EC2::Volume" 100 | Source: 101 | Owner: CUSTOM_POLICY 102 | CustomPolicyDetails: 103 | EnableDebugLogDelivery: "True" 104 | PolicyRuntime: guard-2.x.x 105 | PolicyText: | 106 | let volumestatus = 'available' 107 | let volumetype = 'gp3' 108 | let volumeencryptionstatus = true 109 | 110 | rule compliancecheck when 111 | resourceType == "AWS::EC2::Volume" { 112 | configuration.state == %volumestatus 113 | configuration.encrypted == %volumeencryptionstatus 114 | configuration.volumeType == %volumetype 115 | } 116 | SourceDetails: 117 | - 118 | EventSource: "aws.config" 119 | MessageType: "ConfigurationItemChangeNotification" 120 | 121 | ## Scenario 1 - EC2 Volume Solution TerraForm Code 122 | resource "aws_config_config_rule" "example" { 123 | name = "GUARD-Ec2Volume-TF" 124 | description = "compliant if volume is available, encrypted and GP3" 125 | 126 | scope { 127 | compliance_resource_types = ["AWS::EC2::Volume"] 128 | } 129 | 130 | 131 | source { 132 | owner = "CUSTOM_POLICY" 133 | 134 | source_detail { 135 | event_source = "aws.config" 136 | message_type = "ConfigurationItemChangeNotification" 137 | } 138 | 139 | custom_policy_details { 140 | policy_runtime = "guard-2.x.x" 141 | policy_text = < | | 256 | |----------------------------------------------------------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 257 | | Can I test the CloudFormation Guard code outside of AWS Config? | Unit testing can be done locally on your local device or something like Cloud9

Installation steps can be found here:
https://github.com/aws-cloudformation/cloudformation-guard#guard-cli

Once the CloudFormation Guard app is downloaded and installed with the dependencies the policy can be run against a local deployment of CloudFormation Guard on a laptop or virtual machine to validate if the cfn-guard syntax is correct. All that is needed is a test sample of JSON saved as a text file and the cfn-guard policy.

cfn-guard CLI command:

cfn-guard validate -d /home/ubuntu/cfng/templates/vol-json.txt -r /home/ubuntu/cfng/rulesets/ec2-volume-config.txt | 258 | | How can I debug my AWS Config Custom rule use cfn-guard? | The Boolean expression for enabling debug logging for your AWS Config Custom Policy rule. The default value is false. | -------------------------------------------------------------------------------- /awsconfig-guard-cft-gd.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Description: Create AWS Config Rule using CloudFormation Guard DSL 3 | Parameters: 4 | ConfigRuleName01: 5 | Type: String 6 | Default: GUARD-Rule-01-GD 7 | Description: Name of the AWS Config Rule 8 | 9 | Resources: 10 | 11 | ConfigGuardRule01: 12 | Type: AWS::Config::ConfigRule 13 | Properties: 14 | ConfigRuleName: !Ref ConfigRuleName01 15 | Description: Compliant if GuardDuty has S3 protection enabled, Kubernetes protection enabled AND Findings are published every 15 minutes. 16 | Scope: 17 | ComplianceResourceTypes: 18 | - "AWS::GuardDuty::Detector" 19 | Source: 20 | Owner: CUSTOM_POLICY 21 | CustomPolicyDetails: 22 | EnableDebugLogDelivery: "True" 23 | PolicyRuntime: guard-2.x.x 24 | PolicyText: | 25 | let s3protection = true 26 | let kubernetesprotection = true 27 | let publishfrequency = 'FIFTEEN_MINUTES' 28 | 29 | rule compliancecheck when 30 | resourceType == "AWS::GuardDuty::Detector" { 31 | configuration.DataSources.S3Logs.Enable == %s3protection 32 | configuration.DataSources.Kubernetes.AuditLogs.Enable == %kubernetesprotection 33 | configuration.FindingPublishingFrequency == %publishfrequency 34 | } 35 | SourceDetails: 36 | - 37 | EventSource: "aws.config" 38 | MessageType: "ConfigurationItemChangeNotification" 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /awsconfig-guard-cft.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Description: Create AWS Config Rule using CloudFormation Guard DSL 3 | Parameters: 4 | ConfigRuleName01: 5 | Type: String 6 | Default: GUARD-Rule-01 7 | Description: Name of the AWS Config Rule 8 | 9 | Resources: 10 | 11 | ConfigGuardRule01: 12 | Type: AWS::Config::ConfigRule 13 | Properties: 14 | ConfigRuleName: !Ref ConfigRuleName01 15 | Description: Compliant if volume is available, type gp3, and encrypted conditions are met in resource 16 | Scope: 17 | ComplianceResourceTypes: 18 | - "AWS::EC2::Volume" 19 | Source: 20 | Owner: CUSTOM_POLICY 21 | CustomPolicyDetails: 22 | EnableDebugLogDelivery: "True" 23 | PolicyRuntime: guard-2.x.x 24 | PolicyText: | 25 | let volumestatus = 'available' 26 | let volumetype = 'gp3' 27 | let volumeencryptionstatus = true 28 | 29 | rule compliancecheck when 30 | resourceType == "AWS::EC2::Volume" { 31 | configuration.state == %volumestatus 32 | configuration.encrypted == %volumeencryptionstatus 33 | configuration.volumeType == %volumetype 34 | } 35 | SourceDetails: 36 | - 37 | EventSource: "aws.config" 38 | MessageType: "ConfigurationItemChangeNotification" 39 | 40 | 41 | -------------------------------------------------------------------------------- /awsconfig-guard-tf-ec2vol.json: -------------------------------------------------------------------------------- 1 | resource "aws_config_config_rule" "example" { 2 | name = "GUARD-Ec2Volume-TF" 3 | description = "compliant if volume is available, encrypted and GP3" 4 | 5 | scope { 6 | compliance_resource_types = ["AWS::EC2::Volume"] 7 | } 8 | 9 | 10 | source { 11 | owner = "CUSTOM_POLICY" 12 | 13 | source_detail { 14 | event_source = "aws.config" 15 | message_type = "ConfigurationItemChangeNotification" 16 | } 17 | 18 | custom_policy_details { 19 | policy_runtime = "guard-2.x.x" 20 | policy_text = <> 16 | } 17 | -------------------------------------------------------------------------------- /reinvent-sec314/guardduty.guard: -------------------------------------------------------------------------------- 1 | rule guarddutyfeatures when 2 | resourceType == "AWS::GuardDuty::Detector" { 3 | 4 | let gdconfig = configuration.Features[ 5 | Name == /.*S3_DATA_EVENTS.*|.*EBS_MALWARE_PROTECTION.*/ 6 | ] 7 | 8 | when %gdconfig !empty{ 9 | %gdconfig.Status == 'ENABLED' 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /reinvent-sec314/prohibitedresources.guard: -------------------------------------------------------------------------------- 1 | rule prohibhitedresources { 2 | resourceId empty 3 | } 4 | -------------------------------------------------------------------------------- /reinvent-sec314/securitygroup.guard: -------------------------------------------------------------------------------- 1 | rule ec2LeastPrivilegeSecurityGroups when resourceType == 'AWS::EC2::SecurityGroup' { 2 | configuration.ipPermissions[ 3 | some ipv4Ranges[*].cidrIp == "0.0.0.0/0" or 4 | some ipv6Ranges[*].cidrIpv6 == "::/0" 5 | ] empty << IP Range overly permissive >> 6 | } 7 | -------------------------------------------------------------------------------- /reinvent24-sec314/bucketpolicy.guard: -------------------------------------------------------------------------------- 1 | 2 | 3 | let S3_BUCKET_CONDITION_EXISTS = Resources.*[ Type == 'AWS::S3::BucketPolicy' 4 | ] 5 | 6 | # S3 bucket policy - ""some" keyword emphasizes at least one instance present in list document 7 | 8 | rule s3_bucketpolicy_check when %S3_BUCKET_CONDITION_EXISTS !empty { 9 | let violations = %S3_BUCKET_CONDITION_EXISTS[ 10 | some Properties.PolicyDocument.Statement[*] { 11 | Condition{ 12 | 'ForAnyValue:StringEquals'.'aws:PrincipalOrgPaths' in ['o-lj8c55mjv1/ou-ds8b-bmjfeo1g/*/'] 13 | } 14 | } 15 | ] 16 | %violations !empty 17 | } -------------------------------------------------------------------------------- /reinvent24-sec314/bucketpolicy.yaml: -------------------------------------------------------------------------------- 1 | Resources: 2 | 3 | S3BucketPolicy: 4 | Type: AWS::S3::BucketPolicy 5 | Properties: 6 | Bucket: !Ref S3Bucket 7 | PolicyDocument: 8 | Version: 2012-10-17 9 | Statement: 10 | - Sid: AllowGetObject 11 | Effect: Allow 12 | Principal: "*" 13 | Action: s3:GetObject 14 | Resource: "arn:aws:s3:::cfguard-example-83urj/*" 15 | Condition: 16 | ForAnyValue:StringEquals: 17 | aws:PrincipalOrgPaths: 18 | # - o-lj8c55mjv1/r-nxuu/*/ 19 | # - o-dg88kxu48m/r-jlqc/ou-jlqc-e64koh7p/* 20 | - o-lj8c55mjv1/ou-ds8b-bmjfeo1g/*/ -------------------------------------------------------------------------------- /reinvent24-sec314/demo-full.guard: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ####################### S C E N A R I O ######################################## 3 | ################################################################################ 4 | 5 | # New sandbox OU requires security controls outside standard pipeline security 6 | 7 | # 1 Encryption using dedicated KMS key shared for the OU 8 | 9 | # 2 Tagging Strategy 10 | 11 | # 3 Bucketpolicy Statement allowing only the OU 12 | 13 | # 4 Prohibited resources per corporate standard for sandbox OU not creating unauthorized connections (TGW, VPC Peering, TGW attachment) 14 | 15 | 16 | ################################################################################ 17 | ############################# P O L I C Y ##################################### 18 | ################################################################################ 19 | 20 | # intro simple variables 21 | 22 | let s3_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ] 23 | let allowed_algos = ["aws:kms"] 24 | let allowed_s3_key = [""] 25 | let S3_BUCKET_CONDITION_EXISTS = Resources.*[ Type == 'AWS::S3::BucketPolicy' 26 | Metadata.cfn_nag.rules_to_suppress not exists or 27 | Metadata.cfn_nag.rules_to_suppress.*.id != "F15" 28 | Metadata.guard.SuppressedRules not exists or 29 | Metadata.guard.SuppressedRules.* != "S3_BUCKET_CONDITION_EXISTS" 30 | ] 31 | 32 | # variable query - queries for all prohobited resources and looks for them to exist, if exists, fail. 33 | 34 | let prohibited_resources_exist = Resources.*[ 35 | Type in [ /EC2::VPCPeeringConnection/, /EC2::TransitGatewayAttachment/, /AWS::EC2::TransitGateway/] 36 | ] 37 | 38 | # rule blocks 39 | 40 | # rule check to ensure prohobitied resources do not exists 41 | 42 | # S3 bucket tags 43 | 44 | rule check_tag when %s3_buckets !empty { 45 | let bucket_policy_check = Resources.*[ Type == 'AWS::S3::BucketPolicy' ] 46 | %bucket_policy_check exists 47 | #bucket_policy_check.Properties.PolicyDocument.Statement[*].Condition.ForAnyValue.StringEquals["aws:PrincipalOrgPaths"] in %allowed_org 48 | %bucket_policy_check.Properties.PolicyDocument.Statement !empty 49 | %s3_buckets.Properties.Tags[*] == {"Key": "Environment", "Value": "3rd Party Production"} 50 | << 51 | Violation: Missing Required 3rd Party Production Environment Tag 52 | Fix: Please fix tag per Security Project Exception 101 in RITM100200300 53 | >> 54 | } 55 | 56 | # S3 bucket policy 57 | 58 | rule s3_bucketpolicy_check when %S3_BUCKET_CONDITION_EXISTS !empty { 59 | let violations = %S3_BUCKET_CONDITION_EXISTS[ 60 | some Properties.PolicyDocument.Statement[*] { 61 | Condition{ 62 | 'ForAnyValue:StringEquals'.'aws:PrincipalOrgPaths' in [''] 63 | } 64 | } 65 | ] 66 | %violations !empty 67 | } 68 | 69 | #check S3 encryption algorithm & key 70 | 71 | let s3_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ] 72 | 73 | #check S3 bucket policy exists & encryption algorithm & key 74 | 75 | rule s3_encryption_checks when %s3_buckets !empty { 76 | # local variable 77 | let allowed_s3_key = [""] 78 | 79 | %s3_buckets.Properties.BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.KMSMasterKeyID == %allowed_s3_key 80 | 81 | 82 | } 83 | 84 | let prohibited_resources_exist = Resources.*[ 85 | Type in [ /EC2::VPCPeeringConnection/, /EC2::TransitGatewayAttachment/, /AWS::EC2::TransitGateway/] 86 | ] 87 | 88 | # Named ruleblock 89 | # if prohoibited resource TYPE matches variable in the CFN template it will 90 | # fail this named rule block statement and display message 91 | 92 | rule check_all_prohibited_resources_networking { 93 | %prohibited_resources_exist empty 94 | 95 | } 96 | 97 | -------------------------------------------------------------------------------- /reinvent24-sec314/demo-full.yaml: -------------------------------------------------------------------------------- 1 | Resources: 2 | S3Bucket: 3 | Type: AWS::S3::Bucket 4 | Properties: 5 | BucketName: cfguard-example-83urj 6 | BucketEncryption: 7 | ServerSideEncryptionConfiguration: 8 | - ServerSideEncryptionByDefault: 9 | SSEAlgorithm: aws:kms 10 | KMSMasterKeyID: 11 | LoggingConfiguration: 12 | DestinationBucketName: cfguard-reinvent-logging-bucket- 13 | LogFilePrefix: "production-logs-" 14 | Tags: 15 | # - {Key: Name, Value: 'reinvent2024-sec314'} 16 | - {Key: Environment, Value: 3rd Party Production} 17 | # - {Key: Environment, Value: 3rd Party - Production} 18 | 19 | Tgw-Fail: 20 | Type: AWS::EC2::TransitGateway 21 | Properties: 22 | 23 | VpcPeerConnection-Fail: 24 | Type: AWS::EC2::VPCPeeringConnection 25 | Properties: 26 | 27 | TgwAttachment-Fail: 28 | Type: AWS::EC2::TransitGatewayAttachment 29 | Properties: 30 | 31 | S3BucketPolicy: 32 | Type: AWS::S3::BucketPolicy 33 | Properties: 34 | Bucket: !Ref S3Bucket 35 | PolicyDocument: 36 | Version: 2012-10-17 37 | Statement: 38 | - Sid: AllowGetObject 39 | Effect: Allow 40 | Principal: "*" 41 | Action: s3:GetObject 42 | Resource: "arn:aws:s3:::cfguard-example-83urj/*" 43 | Condition: 44 | ForAnyValue:StringEquals: 45 | aws:PrincipalOrgPaths: 46 | - 47 | -------------------------------------------------------------------------------- /reinvent24-sec314/encryption.guard: -------------------------------------------------------------------------------- 1 | # intro rule level variables & yq 2 | 3 | # dyanmic vs static variables 4 | 5 | let s3_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ] 6 | 7 | #check S3 bucket policy exists & encryption algorithm & key 8 | 9 | rule s3_encryption_checks when %s3_buckets !empty { 10 | # local variable 11 | let allowed_s3_key = [""] 12 | 13 | %s3_buckets.Properties.BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.KMSMasterKeyID == %allowed_s3_key 14 | 15 | 16 | } -------------------------------------------------------------------------------- /reinvent24-sec314/encryption.yaml: -------------------------------------------------------------------------------- 1 | Resources: 2 | S3Bucket: 3 | Type: AWS::S3::Bucket 4 | Properties: 5 | BucketEncryption: 6 | ServerSideEncryptionConfiguration: 7 | - ServerSideEncryptionByDefault: 8 | SSEAlgorithm: aws:kms 9 | KMSMasterKeyID: 10 | 11 | -------------------------------------------------------------------------------- /reinvent24-sec314/prohibited-resources.guard: -------------------------------------------------------------------------------- 1 | 2 | # file/global level variable defined added queries for all prohobited resources in [ / / ]. 3 | 4 | let prohibited_resources_exist = Resources.*[ 5 | Type in [ /EC2::VPCPeeringConnection/, /EC2::TransitGatewayAttachment/, /AWS::EC2::TransitGateway/] 6 | ] 7 | 8 | # Named ruleblock 9 | # if prohoibited resource TYPE matches variable in the CFN template it will 10 | # fail this named rule block statement and display message 11 | 12 | rule check_all_prohibited_resources_networking { 13 | %prohibited_resources_exist empty 14 | 15 | } -------------------------------------------------------------------------------- /reinvent24-sec314/prohibited-resources.yaml: -------------------------------------------------------------------------------- 1 | Resources: 2 | Tgw-Fail: 3 | Type: AWS::EC2::TransitGateway 4 | Properties: 5 | Description: This is a transit gateway 6 | 7 | VpcPeerConnection-Fail: 8 | Type: AWS::EC2::VPCPeeringConnection 9 | Properties: 10 | Description: This is a vpc peering 11 | 12 | TgwAttachment-Fail: 13 | Type: AWS::EC2::TransitGatewayAttachment 14 | Properties: 15 | Description: This is a transit gateway attachment 16 | -------------------------------------------------------------------------------- /reinvent24-sec314/scenario.txt: -------------------------------------------------------------------------------- 1 | 2 | New sandbox OU requires security controls outside standard pipeline security 3 | 4 | 1 Encryption using dedicated KMS key shared for the OU 5 | 6 | 2 Tagging Strategy 7 | 8 | 3 Bucketpolicy Statement allowing only the OU 9 | 10 | 4 Prohibited resources per corporate standard for sandbox OU not creating unauthorized connections (TGW, VPC Peering, TGW attachment) 11 | 12 | 13 | -------------------------------------------------------------------------------- /reinvent24-sec314/tags.guard: -------------------------------------------------------------------------------- 1 | 2 | # intro simple variables 3 | 4 | let s3_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ] 5 | 6 | 7 | rule check_tag when %s3_buckets !empty { 8 | %s3_buckets.Properties.Tags[*] == {"Key": "Environment", "Value": "Sandbox"} 9 | << 10 | Violation: Missing Required 3rd Party Production Environment Tag 11 | Fix: Please fix tag per Security Project Exception 101 in RITM100200300 12 | >> 13 | } --------------------------------------------------------------------------------