diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000..7992b82f3 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,9 @@ +# Examples + +## [federated-setup](./federated-setup/README.md) + +The directory contains templates for setting up the `configure-aws-credentials` federation between your GitHub Organization/repository and your AWS account. + +## [cfn-deploy-example](./cfn-deploy-example/README.md) + +Repository example uses aws-action `configure-aws-credentials` with OIDC federation template [github-actions-oidc-federation-and-role](./github-actions-oidc-federation-and-role.yml). Example demonstrates a repository that deploys AWS CloudFormation template using cfn-deploy GitHub Action. diff --git a/examples/cfn-deploy-example/.github/workflows/compliance.yml b/examples/cfn-deploy-example/.github/workflows/compliance.yml new file mode 100644 index 000000000..55470d07c --- /dev/null +++ b/examples/cfn-deploy-example/.github/workflows/compliance.yml @@ -0,0 +1,15 @@ +name: 'compliance' +## run ci testing on all push events +on: [push] +jobs: + ## Guard rule set + sast-guard: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: grolston/guard-action@main + with: + data_directory: './cloudformation/' ## change to your template directory + rule_set: 'FedRAMP-Moderate' + show_summary: 'all' + output_format: 'single-line-summary' \ No newline at end of file diff --git a/examples/cfn-deploy-example/.github/workflows/deploy.yml b/examples/cfn-deploy-example/.github/workflows/deploy.yml new file mode 100644 index 000000000..513122562 --- /dev/null +++ b/examples/cfn-deploy-example/.github/workflows/deploy.yml @@ -0,0 +1,38 @@ +--- +name: deploy +on: + push: + branches: + - main +env: + AWS_DEFAULT_REGION: us-east-1 + AWS_DEFAULT_OUTPUT: json + +jobs: + deploy-cfn: + name: deploy + runs-on: ubuntu-latest + # These permissions are needed to interact with GitHub’s OIDC Token endpoint. + permissions: + id-token: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1-node16 + with: + aws-region: us-east-1 + ## the following creates an ARN based on the values entered into github secrets + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_DEPLOY_ROLE }} + role-session-name: myGitHubActions + - name: Deploy EC2 Bastion + uses: aws-actions/aws-cloudformation-github-deploy@v1.0.3 + with: + name: myEC2bastion + ## change to path to template in your github repo + template: cloudformation/ec2-bastion.yml + capabilities: CAPABILITY_IAM, CAPABILITY_NAMED_IAM + no-fail-on-empty-changeset: "1" + ## parameter set in github secrets + parameter-overrides: "pVpc=${{ secrets.VPC_ID }},pSubnet=${{ secrets.SUBNET_ID }}" diff --git a/examples/cfn-deploy-example/README.md b/examples/cfn-deploy-example/README.md new file mode 100644 index 000000000..4deedcc49 --- /dev/null +++ b/examples/cfn-deploy-example/README.md @@ -0,0 +1,14 @@ +# cfn-deploy example + +Example uses aws-action `configure-aws-credentials` with OIDC federation. Prior to using this example project, the user needs to deploy the [github-actions-oidc-federation-and-role](../federated-setup/github-actions-oidc-federation-and-role.yml) template in the AWS account they want to deploy the CloudFormation template into. Specify the GitHub Organization name, repository name, and the specific branch you want to deploy on. + +Within the [github/workflows](./.github/workflows/) directory there is a [compliance.yml](./.github/workflows/compliance.yml) and a [deploy.yml](./.github/workflows/deploy.yml). The deploy.yml file leverages the aws-action `configure-aws-credentials` and accesses GitHub Action Secrets for some of the variables. The compliance.yml runs static application security testing using cfn-guard. + +To use the example you will need to set the following GitHub Action Secrets: + +| Secret Key | Used With | Description | +| --------- | -------- | -----------| +| AWS_ACCOUNT_ID | configure-aws-credentials | The AWS account ID | +| AWS_DEPLOY_ROLE | configure-aws-credentials | The name of the IAM role | +| VPC_ID | aws-cloudformation-github-deploy | VPC ID the EC2 Bastion is deployed to | +| SUBNET_ID | aws-cloudformation-github-deploy | Subnet ID the EC2 Bastion is deployed to | diff --git a/examples/cfn-deploy-example/ec2-bastion.yml b/examples/cfn-deploy-example/ec2-bastion.yml new file mode 100644 index 000000000..28c6a92a5 --- /dev/null +++ b/examples/cfn-deploy-example/ec2-bastion.yml @@ -0,0 +1,150 @@ +--- +AWSTemplateFormatVersion: "2010-09-09" +Description: EC2 bastion for latest AWS Linux 2 EC2 deployment +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: "EC2 Configuration" + Parameters: + - pTagNameValue + - pOperatingSystem + - pInstanceType + - pVolumeSize + - pEbsDeleteOnTermination + - Label: + default: "Network Configuration" + Parameters: + - pVpc + - pSubnet + ParameterLabels: + pOperatingSystem: + default: "Operating System" + pInstanceType: + default: "Instance Type" + pTagNameValue: + default: "EC2 Name" + pVolumeSize: + default: "Volume Size" + pEbsDeleteOnTermination: + default: "Delete EBS Volume on Termination" + pSubnet: + default: "Subnet" + pVpc: + default: "VPC" +Parameters: + pSubnet: + Description: The subnet to launch the instance in to. It must be part of the VPC chosen above. + Type: AWS::EC2::Subnet::Id + pVpc: + Description: The VPC to launch the EC2 instance in to. + Type: AWS::EC2::VPC::Id + pOperatingSystem: + Type: "AWS::SSM::Parameter::Value" + Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs" + pInstanceType: + Description: Desired Instance Size + Type: String + Default: t3.small + AllowedValues: + - t3.small + - t3.medium + - t3.nano + pTagNameValue: + Description: "Required: Enter the tag name you'd like applied to the instance. Tag Name gives the name to the EC2 instance." + Type: String + MinLength: 1 + Default: "myBastion" + pVolumeSize: + Description: + Enter the number of GBs you want your volume to be. The minimum value + is 8 GBs + Type: Number + Default: 50 + MinValue: 8 + pEbsDeleteOnTermination: + Description: "Specify if the EBS volume should be deleted if EC2 is deleted." + Type: String + Default: true + AllowedValues: + - true + - false +Rules: + SubnetInVPC: + Assertions: + - Assert: !EachMemberIn + - !ValueOfAll + - AWS::EC2::Subnet::Id + - VpcId + - !RefAll "AWS::EC2::VPC::Id" + AssertDescription: All subnets must in the VPC +Resources: + rSecurityGroupDefault: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: !Sub "Default SG for SC Product ${pTagNameValue} " + VpcId: !Ref pVpc + SecurityGroupEgress: + - Description: Outbound unrestricted traffic + IpProtocol: "-1" + CidrIp: 0.0.0.0/0 + Tags: + - Key: Name + Value: !Ref pTagNameValue + rLinuxEc2: + Type: AWS::EC2::Instance + Metadata: + guard: + SuppressedRules: + - 'EC2_INSTANCE_DETAILED_MONITORING_ENABLED' + Properties: + ImageId: !Ref pOperatingSystem + IamInstanceProfile: !Ref rec2InstanceProfile + Monitoring: false + InstanceType: !Ref pInstanceType + EbsOptimized: true + SourceDestCheck: true + SubnetId: !Ref pSubnet + SecurityGroupIds: + - !Ref rSecurityGroupDefault + BlockDeviceMappings: + - DeviceName: "/dev/xvda" + Ebs: + VolumeSize: !Ref pVolumeSize + DeleteOnTermination: !Ref pEbsDeleteOnTermination + Tags: + - Key: Name + Value: !Ref pTagNameValue + UserData: + Fn::Base64: + yum update -y + ## Instance Profiles + ## EC2 IAM Roles + rEc2Role: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "ec2-role-${AWS::StackName}" + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: [ec2.amazonaws.com] + Action: ['sts:AssumeRole'] + Path: / + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' + rec2InstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + InstanceProfileName: !Sub "ec2-profile-${AWS::StackName}" + Path: / + Roles: + - !Ref rEc2Role +Outputs: + oLinuxEc2InstanceId: + Description: Resource ID of the newly created EC2 instance + Value: !Ref rLinuxEc2 + oLinuxEc2PrivateIP: + Description: Private IP Address for EC2 + Value: !GetAtt rLinuxEc2.PrivateIp diff --git a/examples/federated-setup/README.md b/examples/federated-setup/README.md new file mode 100644 index 000000000..209f43e51 --- /dev/null +++ b/examples/federated-setup/README.md @@ -0,0 +1,9 @@ +# federated-setup + +## [github-action-oidc-federation](./github-actions-odic-federation.yml) + +Setup of the OIDC federation between your GitHub Organization/repository and your AWS account. + +## [github-actions-oidc-federation-and-role](./github-actions-oidc-federation-and-role.yml) + +Setup of the OIDC federation between your GitHub Organization/repository and your AWS account along with a role that only executes on specific branch. diff --git a/examples/federated-setup/github-actions-odic-federation.yml b/examples/federated-setup/github-actions-odic-federation.yml new file mode 100644 index 000000000..b0dadf2c6 --- /dev/null +++ b/examples/federated-setup/github-actions-odic-federation.yml @@ -0,0 +1,43 @@ +--- +AWSTemplateFormatVersion: "2010-09-09" +Description: Github Actions configuration - OIDC IAM IdP Federation + +Parameters: + + GitHubOrganization: + Type: String + Description: This is the root organization or personal account where repos are stored (Case Sensitive) + Default: "" + + RepositoryName: + Type: String + Description: The repo(s) these roles will have access to. (Use * for all org or personal repos) + Default: "*" + + RoleName: + Type: String + Description: Name the Role + Default: "" + + +Resources: + + IdpGitHubOidc: + Type: AWS::IAM::OIDCProvider + Properties: + Url: https://token.actions.githubusercontent.com + ClientIdList: + - sts.amazonaws.com + - !Sub https://github.com/${GitHubOrganization}/${RepositoryName} + ThumbprintList: + - 6938fd4d98bab03faadb97b34396831e3780aea1 + Tags: + - Key: Name + Value: !Sub ${RoleName}-OIDC-Provider + + +Outputs: + + IdpGitHubOidc: + Description: "ARN of Github OIDC Provider" + Value: !GetAtt IdpGitHubOidc.Arn diff --git a/examples/federated-setup/github-actions-oidc-federation-and-role.yml b/examples/federated-setup/github-actions-oidc-federation-and-role.yml new file mode 100644 index 000000000..0c8de29d4 --- /dev/null +++ b/examples/federated-setup/github-actions-oidc-federation-and-role.yml @@ -0,0 +1,82 @@ +--- +AWSTemplateFormatVersion: "2010-09-09" +Description: Github Actions configuration - OIDC IAM IdP and associated role CI/CD + +Parameters: + + GitHubOrganization: + Type: String + Description: This is the root organization or personal account where repos are stored (Case Sensitive) + + RepositoryName: + Type: String + Description: The repo(s) these roles will have access to. (Use * for all org or personal repos) + Default: "*" + + BranchName: + Type: String + Description: Name of the git branch to to trust. (Use * for all branches) + Default: "*" + + RoleName: + Type: String + Description: Name the Role + + UseExistingProvider: + Type: String + Description: "Only one GitHub Provider can exists. Choose yes if one is already present in account" + Default: "no" + AllowedValues: + - "yes" + - "no" + +Conditions: + + CreateProvider: !Equals ["no", !Ref UseExistingProvider] + +Resources: + + IdpGitHubOidc: + Type: AWS::IAM::OIDCProvider + Condition: CreateProvider + Properties: + Url: https://token.actions.githubusercontent.com + ClientIdList: + - sts.amazonaws.com + - !Sub https://github.com/${GitHubOrganization}/${RepositoryName} + ThumbprintList: + - 6938fd4d98bab03faadb97b34396831e3780aea1 + Tags: + - Key: Name + Value: !Sub ${RoleName}-OIDC-Provider + + RoleGithubActions: + Type: AWS::IAM::Role + Properties: + RoleName: !Ref RoleName + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRoleWithWebIdentity + Principal: + Federated: !If + - CreateProvider + - !Ref IdpGitHubOidc + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com + Condition: + StringLike: + token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrganization}/${RepositoryName}:ref:refs/heads/${BranchName} + ManagedPolicyArns: + ## edit the managed policy to give least privileges + - !Sub arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess + +Outputs: + + IdpGitHubOidc: + Condition: CreateProvider + Description: "ARN of Github OIDC Provider" + Value: !GetAtt IdpGitHubOidc.Arn + + RoleGithubActionsARN: + Description: "CICD Role for GitHub Actions" + Value: !GetAtt RoleGithubActions.Arn