From 2147d3e5ec97e509de1b74176b7ec90b09e61083 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 23:57:23 +0000 Subject: [PATCH 1/5] Initial plan From bd58f5bff82245dea93fcff671b583241dc69e59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 00:00:34 +0000 Subject: [PATCH 2/5] Add GitHub Actions workflow for SAM deployment Co-authored-by: vmanam0451 <25410102+vmanam0451@users.noreply.github.com> --- .github/workflows/README.md | 189 +++++++++++++++++++++++++++++++ .github/workflows/deploy-sam.yml | 65 +++++++++++ 2 files changed, 254 insertions(+) create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/deploy-sam.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..f8371c9 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,189 @@ +# GitHub Actions CI/CD Setup + +This repository uses GitHub Actions to automate the deployment of AWS SAM (Serverless Application Model) stacks. + +## Prerequisites + +Before you can use the automated deployment workflow, you need to set up the following: + +### 1. AWS IAM Role for GitHub Actions (OIDC) + +Create an IAM role in AWS that GitHub Actions can assume using OpenID Connect (OIDC). This is the recommended approach as it doesn't require storing long-lived AWS credentials. + +#### Steps to create the IAM role: + +1. **Create an OIDC Identity Provider in AWS**: + - Go to IAM → Identity providers → Add provider + - Provider type: OpenID Connect + - Provider URL: `https://token.actions.githubusercontent.com` + - Audience: `sts.amazonaws.com` + +2. **Create an IAM Role**: + - Go to IAM → Roles → Create role + - Select "Web identity" + - Choose the OIDC provider you just created + - Audience: `sts.amazonaws.com` + - Add a trust policy condition to restrict to your repository: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::YOUR_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" + }, + "StringLike": { + "token.actions.githubusercontent.com:sub": "repo:YOUR_GITHUB_USERNAME/distributed-path-tracer:*" + } + } + } + ] + } + ``` + +3. **Attach Policies to the Role**: + The role needs the following permissions: + - CloudFormation full access + - Lambda full access + - IAM role creation/update + - S3 access for artifacts bucket + - ECR access for Docker images + - API Gateway access + - SNS and SQS access + + Example policy: + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "cloudformation:*", + "lambda:*", + "iam:*", + "s3:*", + "ecr:*", + "apigateway:*", + "sns:*", + "sqs:*", + "logs:*" + ], + "Resource": "*" + } + ] + } + ``` + +### 2. AWS Resources + +Create the following AWS resources: + +1. **S3 Bucket for SAM Artifacts**: + - Create an S3 bucket to store SAM deployment artifacts + - Example: `distributed-path-trace-function-artifacts` + +2. **ECR Repository for Docker Images**: + - Create an ECR repository for the Lambda container images + - Example: `distributed-path-tracer` + +### 3. GitHub Repository Configuration + +#### Secrets + +Add the following secrets to your GitHub repository (Settings → Secrets and variables → Actions → Secrets): + +- `AWS_ROLE_ARN`: The ARN of the IAM role created above + - Example: `arn:aws:iam::123456789012:role/GitHubActionsDeployRole` +- `SAM_ARTIFACTS_BUCKET`: The name of the S3 bucket for SAM artifacts + - Example: `distributed-path-trace-function-artifacts` +- `ECR_REPOSITORY`: The URI of the ECR repository + - Example: `123456789012.dkr.ecr.us-east-1.amazonaws.com/distributed-path-tracer` + +#### Variables (Optional) + +Add the following variables (Settings → Secrets and variables → Actions → Variables): + +- `AWS_REGION`: AWS region for deployment (default: `us-east-1`) + +#### Environments (Recommended) + +For better control, create GitHub environments: + +1. Go to Settings → Environments +2. Create an environment named `prod` +3. (Optional) Add protection rules like required reviewers +4. Add environment-specific secrets/variables if needed + +## Usage + +### Automatic Deployment + +The workflow automatically triggers on: +- **Push to main branch**: Deploys to the `prod` environment + +### Manual Deployment + +You can manually trigger a deployment: + +1. Go to Actions → Deploy SAM Application +2. Click "Run workflow" +3. Select the branch and environment +4. Click "Run workflow" + +## Workflow Details + +The deployment workflow performs the following steps: + +1. **Checkout code**: Retrieves the repository code +2. **Configure AWS credentials**: Assumes the IAM role using OIDC +3. **Setup SAM CLI**: Installs the AWS SAM CLI +4. **SAM Build**: Builds the SAM application (including Docker images) +5. **SAM Deploy**: Deploys the stack to AWS +6. **Output Stack Info**: Displays the stack outputs (API endpoints, Lambda ARNs, etc.) + +## Troubleshooting + +### Build Failures + +- Check that all required build tools are available +- Verify Docker images build correctly locally first +- Review CloudWatch logs for Lambda build errors + +### Deployment Failures + +- Verify IAM role has sufficient permissions +- Check that S3 bucket and ECR repository exist +- Ensure region settings are correct +- Review CloudFormation events in AWS Console + +### Authentication Issues + +- Verify OIDC provider is correctly configured +- Check IAM role trust policy matches your repository +- Ensure `AWS_ROLE_ARN` secret is correct + +## Local Development + +To deploy locally: + +```bash +# Build the SAM application +sam build --cached + +# Deploy with your AWS profile +sam deploy --profile your-profile-name +``` + +## Additional Resources + +- [AWS SAM Documentation](https://docs.aws.amazon.com/serverless-application-model/) +- [GitHub Actions OIDC with AWS](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) +- [SAM CLI Reference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html) diff --git a/.github/workflows/deploy-sam.yml b/.github/workflows/deploy-sam.yml new file mode 100644 index 0000000..9c6284b --- /dev/null +++ b/.github/workflows/deploy-sam.yml @@ -0,0 +1,65 @@ +name: Deploy SAM Application + +on: + workflow_dispatch: + inputs: + environment: + description: 'Environment to deploy to' + required: true + default: 'prod' + type: choice + options: + - prod + - staging + push: + branches: + - main + +permissions: + id-token: write + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + environment: ${{ github.event.inputs.environment || 'prod' }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: ${{ vars.AWS_REGION || 'us-east-1' }} + + - name: Setup SAM CLI + uses: aws-actions/setup-sam@v2 + with: + use-installer: true + + - name: SAM Build + run: sam build --cached + + - name: SAM Deploy + run: | + sam deploy \ + --no-confirm-changeset \ + --no-fail-on-empty-changeset \ + --stack-name distributed-path-tracer-stack \ + --s3-bucket ${{ secrets.SAM_ARTIFACTS_BUCKET }} \ + --s3-prefix distributed-path-tracer-stack \ + --region ${{ vars.AWS_REGION || 'us-east-1' }} \ + --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \ + --image-repository ${{ secrets.ECR_REPOSITORY }} \ + --parameter-overrides ENV=${{ github.event.inputs.environment || 'prod' }} \ + --on-failure DELETE + + - name: Output Stack Info + run: | + aws cloudformation describe-stacks \ + --stack-name distributed-path-tracer-stack \ + --region ${{ vars.AWS_REGION || 'us-east-1' }} \ + --query 'Stacks[0].Outputs' \ + --output table From 0e110bb43c7573b671b0c1badb0ddc69e9324320 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 00:02:06 +0000 Subject: [PATCH 3/5] Address code review feedback - require manual deployments and fix validation workflow Co-authored-by: vmanam0451 <25410102+vmanam0451@users.noreply.github.com> --- .github/workflows/README.md | 7 +------ .github/workflows/deploy-sam.yml | 7 ++----- .github/workflows/validate-sam.yml | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/validate-sam.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md index f8371c9..a1bf9a2 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -124,14 +124,9 @@ For better control, create GitHub environments: ## Usage -### Automatic Deployment - -The workflow automatically triggers on: -- **Push to main branch**: Deploys to the `prod` environment - ### Manual Deployment -You can manually trigger a deployment: +Deployments are triggered manually for better control and to prevent accidental production deployments: 1. Go to Actions → Deploy SAM Application 2. Click "Run workflow" diff --git a/.github/workflows/deploy-sam.yml b/.github/workflows/deploy-sam.yml index 9c6284b..f63f0fb 100644 --- a/.github/workflows/deploy-sam.yml +++ b/.github/workflows/deploy-sam.yml @@ -11,9 +11,6 @@ on: options: - prod - staging - push: - branches: - - main permissions: id-token: write @@ -22,7 +19,7 @@ permissions: jobs: deploy: runs-on: ubuntu-latest - environment: ${{ github.event.inputs.environment || 'prod' }} + environment: ${{ github.event.inputs.environment }} steps: - name: Checkout code @@ -53,7 +50,7 @@ jobs: --region ${{ vars.AWS_REGION || 'us-east-1' }} \ --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \ --image-repository ${{ secrets.ECR_REPOSITORY }} \ - --parameter-overrides ENV=${{ github.event.inputs.environment || 'prod' }} \ + --parameter-overrides ENV=${{ github.event.inputs.environment }} \ --on-failure DELETE - name: Output Stack Info diff --git a/.github/workflows/validate-sam.yml b/.github/workflows/validate-sam.yml new file mode 100644 index 0000000..b907f55 --- /dev/null +++ b/.github/workflows/validate-sam.yml @@ -0,0 +1,29 @@ +name: Validate SAM Template + +on: + pull_request: + branches: + - main + paths: + - 'template.yml' + - 'cloudformation/**' + - '.github/workflows/validate-sam.yml' + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup SAM CLI + uses: aws-actions/setup-sam@v2 + with: + use-installer: true + + - name: Validate SAM Template + run: sam validate --lint + + - name: SAM Build (Dry Run) + run: sam build --cached From cd987648a9e688a1f76edb67c60731632c5aaf39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 00:03:46 +0000 Subject: [PATCH 4/5] Make stack name configurable and improve IAM policy documentation Co-authored-by: vmanam0451 <25410102+vmanam0451@users.noreply.github.com> --- .github/workflows/README.md | 166 +++++++++++++++++++++++++++---- .github/workflows/deploy-sam.yml | 11 +- 2 files changed, 153 insertions(+), 24 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index a1bf9a2..5bf068b 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -49,38 +49,162 @@ Create an IAM role in AWS that GitHub Actions can assume using OpenID Connect (O ``` 3. **Attach Policies to the Role**: - The role needs the following permissions: - - CloudFormation full access - - Lambda full access - - IAM role creation/update - - S3 access for artifacts bucket - - ECR access for Docker images - - API Gateway access - - SNS and SQS access - - Example policy: + The role needs the following permissions. Here's a more restrictive policy (adjust resource ARNs as needed): + ```json { "Version": "2012-10-17", "Statement": [ { + "Sid": "CloudFormationPermissions", "Effect": "Allow", "Action": [ - "cloudformation:*", - "lambda:*", - "iam:*", - "s3:*", - "ecr:*", - "apigateway:*", - "sns:*", - "sqs:*", - "logs:*" + "cloudformation:CreateStack", + "cloudformation:UpdateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStacks", + "cloudformation:DescribeStackEvents", + "cloudformation:DescribeStackResource", + "cloudformation:DescribeStackResources", + "cloudformation:GetTemplate", + "cloudformation:ValidateTemplate", + "cloudformation:CreateChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:ExecuteChangeSet", + "cloudformation:DeleteChangeSet", + "cloudformation:ListStackResources" + ], + "Resource": [ + "arn:aws:cloudformation:*:*:stack/distributed-path-tracer-stack/*", + "arn:aws:cloudformation:*:*:stack/distributed-path-tracer-stack-*/*" + ] + }, + { + "Sid": "LambdaPermissions", + "Effect": "Allow", + "Action": [ + "lambda:CreateFunction", + "lambda:DeleteFunction", + "lambda:UpdateFunctionCode", + "lambda:UpdateFunctionConfiguration", + "lambda:GetFunction", + "lambda:GetFunctionConfiguration", + "lambda:AddPermission", + "lambda:RemovePermission", + "lambda:InvokeFunction", + "lambda:CreateFunctionUrlConfig", + "lambda:UpdateFunctionUrlConfig", + "lambda:DeleteFunctionUrlConfig", + "lambda:GetFunctionUrlConfig", + "lambda:TagResource", + "lambda:UntagResource" + ], + "Resource": "arn:aws:lambda:*:*:function:distributed-path-tracer-*" + }, + { + "Sid": "IAMPermissions", + "Effect": "Allow", + "Action": [ + "iam:CreateRole", + "iam:DeleteRole", + "iam:GetRole", + "iam:PassRole", + "iam:AttachRolePolicy", + "iam:DetachRolePolicy", + "iam:PutRolePolicy", + "iam:DeleteRolePolicy", + "iam:GetRolePolicy", + "iam:TagRole", + "iam:UntagRole" + ], + "Resource": "arn:aws:iam::*:role/distributed-path-tracer-*" + }, + { + "Sid": "S3Permissions", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject", + "s3:ListBucket", + "s3:GetBucketLocation" + ], + "Resource": [ + "arn:aws:s3:::distributed-path-tracer-*", + "arn:aws:s3:::distributed-path-tracer-*/*" + ] + }, + { + "Sid": "ECRPermissions", + "Effect": "Allow", + "Action": [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:PutImage", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload", + "ecr:DescribeRepositories", + "ecr:CreateRepository", + "ecr:SetRepositoryPolicy" + ], + "Resource": "*" + }, + { + "Sid": "APIGatewayPermissions", + "Effect": "Allow", + "Action": [ + "apigateway:POST", + "apigateway:GET", + "apigateway:PATCH", + "apigateway:DELETE", + "apigateway:PUT" + ], + "Resource": "arn:aws:apigateway:*::/*" + }, + { + "Sid": "SNSSQSPermissions", + "Effect": "Allow", + "Action": [ + "sns:CreateTopic", + "sns:DeleteTopic", + "sns:GetTopicAttributes", + "sns:SetTopicAttributes", + "sns:Subscribe", + "sns:Unsubscribe", + "sns:ListTopics", + "sns:TagResource", + "sns:UntagResource", + "sqs:CreateQueue", + "sqs:DeleteQueue", + "sqs:GetQueueAttributes", + "sqs:SetQueueAttributes", + "sqs:TagQueue", + "sqs:UntagQueue" ], "Resource": "*" + }, + { + "Sid": "CloudWatchLogsPermissions", + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:DeleteLogGroup", + "logs:TagResource", + "logs:UntagResource" + ], + "Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/distributed-path-tracer-*" } ] } ``` + + Note: Some resources like ECR authorization, SNS/SQS (with dynamic naming), require `*` in the resource field. Adjust ARNs based on your account and naming conventions. ### 2. AWS Resources @@ -88,7 +212,7 @@ Create the following AWS resources: 1. **S3 Bucket for SAM Artifacts**: - Create an S3 bucket to store SAM deployment artifacts - - Example: `distributed-path-trace-function-artifacts` + - Example: `distributed-path-tracer-artifacts` 2. **ECR Repository for Docker Images**: - Create an ECR repository for the Lambda container images @@ -103,7 +227,7 @@ Add the following secrets to your GitHub repository (Settings → Secrets and va - `AWS_ROLE_ARN`: The ARN of the IAM role created above - Example: `arn:aws:iam::123456789012:role/GitHubActionsDeployRole` - `SAM_ARTIFACTS_BUCKET`: The name of the S3 bucket for SAM artifacts - - Example: `distributed-path-trace-function-artifacts` + - Example: `distributed-path-tracer-artifacts` - `ECR_REPOSITORY`: The URI of the ECR repository - Example: `123456789012.dkr.ecr.us-east-1.amazonaws.com/distributed-path-tracer` diff --git a/.github/workflows/deploy-sam.yml b/.github/workflows/deploy-sam.yml index f63f0fb..684d59c 100644 --- a/.github/workflows/deploy-sam.yml +++ b/.github/workflows/deploy-sam.yml @@ -11,6 +11,11 @@ on: options: - prod - staging + stack_name: + description: 'CloudFormation stack name' + required: false + default: 'distributed-path-tracer-stack' + type: string permissions: id-token: write @@ -44,9 +49,9 @@ jobs: sam deploy \ --no-confirm-changeset \ --no-fail-on-empty-changeset \ - --stack-name distributed-path-tracer-stack \ + --stack-name ${{ github.event.inputs.stack_name || 'distributed-path-tracer-stack' }} \ --s3-bucket ${{ secrets.SAM_ARTIFACTS_BUCKET }} \ - --s3-prefix distributed-path-tracer-stack \ + --s3-prefix ${{ github.event.inputs.stack_name || 'distributed-path-tracer-stack' }} \ --region ${{ vars.AWS_REGION || 'us-east-1' }} \ --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \ --image-repository ${{ secrets.ECR_REPOSITORY }} \ @@ -56,7 +61,7 @@ jobs: - name: Output Stack Info run: | aws cloudformation describe-stacks \ - --stack-name distributed-path-tracer-stack \ + --stack-name ${{ github.event.inputs.stack_name || 'distributed-path-tracer-stack' }} \ --region ${{ vars.AWS_REGION || 'us-east-1' }} \ --query 'Stacks[0].Outputs' \ --output table From 7eac9c244fc4632837c8fcbd31621fe010d70d0b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 00:04:58 +0000 Subject: [PATCH 5/5] Add explicit permissions to validation workflow (security fix) Co-authored-by: vmanam0451 <25410102+vmanam0451@users.noreply.github.com> --- .github/workflows/validate-sam.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/validate-sam.yml b/.github/workflows/validate-sam.yml index b907f55..daf8c62 100644 --- a/.github/workflows/validate-sam.yml +++ b/.github/workflows/validate-sam.yml @@ -9,6 +9,9 @@ on: - 'cloudformation/**' - '.github/workflows/validate-sam.yml' +permissions: + contents: read + jobs: validate: runs-on: ubuntu-latest