Skip to content

Commit

Permalink
Merge pull request #26 from liatrio/finalized-demo
Browse files Browse the repository at this point in the history
Finalized demo
  • Loading branch information
jburns24 authored Oct 13, 2023
2 parents 31c8a5c + 84a8699 commit fbe94ad
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 141 deletions.
13 changes: 5 additions & 8 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ name: Deploy
on:
push:
branches:
- demo
- main

# permissions:
# id-token: write # Needed to modify JWT token for OIDC
# contents: read # Needed for actions/checkout
permissions:
id-token: write # Needed to modify JWT token for OIDC
contents: read # Needed for actions/checkout

jobs:
run:
Expand All @@ -29,10 +29,7 @@ jobs:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@50ac8dd1e1b10d09dac7b8727528b91bed831ac0 # v3
with:
aws-access-key-id: ${{ secrets.PERSONAL_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.PERSONAL_SECRET_ACCESS_KEY }}
role-to-assume: ${{ secrets.ROLE_TO_ASSUME }}
# role-to-assume: ${{ vars.OIDC_ROLE }}
role-to-assume: ${{ vars.OIDC_ROLE }}
aws-region: ${{ vars.AWS_REGION }}
role-skip-session-tagging: true

Expand Down
8 changes: 8 additions & 0 deletions Brewfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Install AWS CLI
brew 'awscli'

# Install Terraform
brew 'terraform'

# Install Terragrunt
brew 'terragrunt'
81 changes: 29 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,64 +1,41 @@
# DevOps Knowledge Share DOB UI
# OIDC Demo

### Prerequisites
This repo is intended to be a self contained demo of how to leverage OIDC in a workflow to authenticate with AWS and deploy a simple containerized application. This repo contains:

- nvm (`brew install nvm`)
- Node 16.x (`nvm install` & `nvm use` - These commands will read the `.nvmrc` file included in the project)
- npm 8.x (`npm install -g npm@8`)
- Docker Desktop
* Simple Next-js application
* Terraform module to create all required infrastructure (VPC, ECR, ECS Fargate Cluster, and an application LB)
* Dockerfile to build the application
* A GitHub Actions workflow to demonstrate deploying the docker image to an ECS cluster
## Setup
### For MacOS
run `brew bundle` to install dependencies

### Run locally
### For Windows (untested)
```π
# Install AWS CLI
choco install awscli
1. Change your working directory to application root folder
# Install Terraform
choco install terraform
2. Install dependencies using below command
# Install Terragrunt
choco install terragrunt
```
### Configure AWS CLI
Follow these instructions to configure AWS CLI. https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html

```bash
npm install
```

3. Start the DevOps Knowledge Share API locally. Set the `KNOWLEDGE_SHARE_API` environment variable for API communication.
## Initialize
When running this at home you will need to provide your own 'organization' so that the trust policy on the IAM role will allow your workflow to run.
This can be done by running `init.sh <organization>`. Simply replace `<organization>` with your username. So if you fork the repo and the url for your repo is,
`https://github.com/jburns24/keyless-workflow-demo` then you would run `init.sh jburns24`.

```bash
# if running on Host machine
export KNOWLEDGE_SHARE_API=http://localhost:8080
After this finishes you will see a DNS name output as `front_end_dns_name`. Copy that DNS name and hit it in a browser. If you get a 503 Service Not Available you were too fast, just give it a min and refresh.

# if running on Remote Container such as VS Code
export KNOWLEDGE_SHARE_API=<your host machine ip>
After the init script runs copy the output of `gha_role_arn`. Then go to GitHub > Settings > Secrets and variables > Actions. In here create a *Variable* named `OIDC_ROLE` and popualte it with the value you copied for `gha_role_arn`.

# for example, docker is
export KNOWLEDGE_SHARE_API=http://host.docker.internal:8080
```

4. To run the application with hot reloading, run the below command
## Clean up
To save on money make sure you do not leave your AWS resources up and running. To do this navigate to the `terraform` directory and run `terragrunt destroy`. You will be prompted to confirm the deletion and that is it!

```bash
npm run dev
```

5. Navigate to `http://localhost:3000` to view your application

6. To execute testcases, run the below command

```bash
npm run test
```

### Build and Run via Docker

1. Make sure that you have [Docker Desktop installed](https://docs.docker.com/desktop/mac/install/) and you have it running

2. Use the following command to build your Docker image

```bash
# Note: the --platform flag is required for building on Apple Silicon
docker build -t <repo>/devops-knowledge-share-ui . --platform linux/amd64
```

3. Use the following command to start the container with port `3000` forwarded to your local machine

```bash
docker run -e KNOWLEDGE_SHARE_API=http://host.docker.internal:8080 -p 3000:3000 -it <repo>/devops-knowledge-share-ui
```

4. Navigate to `http://localhost:3000` to view your application
Hope you find this informative and if there are bugs please open and issue and I will try to address them. Pull requests are also welcome!
20 changes: 18 additions & 2 deletions init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

set -e # Exit script on any error

# Grab first argument if there is one
if [ $# -eq 1 ]
then
# First argument expected to be the github org/username
GITHUB_ORG=$1
fi

# Define AWS region and profile
AWS_REGION="us-east-2"
AWS_PROFILE="admin-sandbox"
Expand Down Expand Up @@ -35,5 +42,14 @@ docker tag keyless-workflow-demo:latest $ECR_REPO_URL:latest
docker push $ECR_REPO_URL:latest

pushd terraform
# Step 6: Apply the rest of the terraform
${AWS_VAULT_PREFIX} terragrunt apply --auto-approve
# Step 6: Apply the rest of the terraform passing github org as a variable if it was provided
if [ -z ${GITHUB_ORG+x} ]
then
# GITHUB_ORG is not set, apply terraform without it
${AWS_VAULT_PREFIX} terragrunt apply --auto-approve
else
# GITHUB_ORG is set, apply terraform with it
${AWS_VAULT_PREFIX} terragrunt apply -var "github_organization=$GITHUB_ORG" --auto-approve
fi

popd
5 changes: 5 additions & 0 deletions terraform/_outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ output "front_end_dns_name" {
description = "The DNS name of the front end load balancer"
value = aws_lb.front_end.dns_name
}

output "gha_role_arn" {
description = "ARN of the GitHub Action OIDC role"
value = aws_iam_role.gha_role.arn
}
21 changes: 18 additions & 3 deletions terraform/_varibales.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,23 @@ variable "name" {
default = "keyless-workflow-demo"
}

variable "tfstate_bucket" {}
variable "github_organization" {
type = string
description = "The GitHub Organization"
default = "liatrio"
}

variable "tfstate_dynamodb_table" {}
variable "tfstate_bucket" {
description = "The S3 bucket to store the Terraform state file"
type = string
}

variable "aws_region" {}
variable "tfstate_dynamodb_table" {
description = "The DynamoDB table to lock the Terraform state file"
type = string
}

variable "aws_region" {
description = "The AWS region to deploy to"
type = string
}
47 changes: 25 additions & 22 deletions terraform/oidc/main.tf → terraform/oidc.tf
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
## Uncomment this block of code if you are testing this in a personal aws account
## This is a central resource that in my org is not managed via terraform and thus
## including this resouce causes issues.
# resource "aws_iam_openid_connect_provider" "github" {
# url = "https://token.actions.githubusercontent.com"
# Purpose: Create an OIDC provider for Github Actions to use to assume a role in AWS
data "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
}

# # All roles go here.
# # You can find these in the audience of the Github OIDC tokens
# client_id_list = ["sts.amazonaws.com"]
resource "aws_iam_openid_connect_provider" "github" {
# Only create the provider if it doesn't already exist
count = length(data.aws_iam_openid_connect_provider.github) == 0 ? 1 : 0

# thumbprint_list = [
# data.tls_certificate.github_thumbprint.certificates[0].sha1_fingerprint
# ]
# }
url = "https://token.actions.githubusercontent.com"

data "tls_certificate" "github_thumbprint" {
url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration"
# You can find these in the audience of the Github OIDC tokens
client_id_list = ["sts.amazonaws.com"]

thumbprint_list = [
data.tls_certificate.github_thumbprint.certificates[0].sha1_fingerprint
]
}

data "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
data "tls_certificate" "github_thumbprint" {
url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration"
}

# Purpose: Create a policy that gives permissions on specific ECS and ECR resources
resource "aws_iam_policy" "ecs_ecr_policy" {
name = "ecr_ecs_policy"
description = "Policy that gives permissions on specific ECS and ECR resources"
Expand All @@ -34,9 +35,9 @@ resource "aws_iam_policy" "ecs_ecr_policy" {
"ecs:*"
],
Resource = [
var.ecs_cluster_arn, # ARN of the ECS cluster
var.ecs_service_arn, # ARN of the ECS service
replace(var.ecs_task_arn, "/:\\d+$/", ":*") # ARN that matches all task-definition revisions for the task definition created in this repo
aws_ecs_cluster.knowledgeshare_ui_ecs_cluster.arn, # ARN of the ECS cluster
aws_ecs_service.knowledgeshare_ui_service.id, # ARN of the ECS service
replace(data.aws_ecs_task_definition.current_task.arn, "/:\\d+$/", ":*") # ARN that matches all task-definition revisions for the task definition created in this repo
]
},
{
Expand Down Expand Up @@ -69,13 +70,14 @@ resource "aws_iam_policy" "ecs_ecr_policy" {
"ecr:*"
],
Resource = [
var.ecr_repository_arn # Replace 'example' with your ECR repository resource name
aws_ecr_repository.knowledgeshare_ui_ecr.arn
]
}
]
})
}

# Purpose: Create a policy that gives permissions to read the backend s3 bucket the tf state file is stored
resource "aws_iam_policy" "terraform_read" {
name = "terraform_read"
description = "Policy that gives permissions to access the backend s3 bucket the tf state file is stored"
Expand Down Expand Up @@ -109,14 +111,14 @@ resource "aws_iam_policy" "terraform_read" {
})
}

# Purpose: Create a role that Github Actions can assume to deploy to ECS
data "aws_iam_policy_document" "gha_trust_policy" {
statement {
actions = [
"sts:TagSession",
"sts:AssumeRoleWithWebIdentity"
]

# We use StringLike on the Arn to control this
principals {
type = "Federated"
identifiers = [data.aws_iam_openid_connect_provider.github.arn]
Expand All @@ -125,11 +127,12 @@ data "aws_iam_policy_document" "gha_trust_policy" {
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:liatrio/keyless-workflow-demo:environment:demo"]
values = ["repo:${var.github_organization}/keyless-workflow-demo:environment:demo"]
}
}
}

# Purpose: Create a role that Github Actions can assume to deploy to ECS
resource "aws_iam_role" "gha_role" {
name = "gha_role"
assume_role_policy = data.aws_iam_policy_document.gha_trust_policy.json
Expand Down
4 changes: 0 additions & 4 deletions terraform/oidc/_outputs.tf

This file was deleted.

24 changes: 0 additions & 24 deletions terraform/oidc/_variables.tf

This file was deleted.

10 changes: 0 additions & 10 deletions terraform/oidc/backend.tf

This file was deleted.

16 changes: 0 additions & 16 deletions terraform/oidc/terragrunt.hcl

This file was deleted.

0 comments on commit fbe94ad

Please sign in to comment.