Skip to content

Commit

Permalink
add policy and state management
Browse files Browse the repository at this point in the history
  • Loading branch information
leej3 committed Dec 23, 2024
1 parent 95ddd17 commit e478547
Show file tree
Hide file tree
Showing 17 changed files with 445 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ crash.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
*_override.tf.json
*lock.hcl
65 changes: 65 additions & 0 deletions terraform/modules/iam/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
terraform {
required_version = ">= 1.0.0, < 2.0.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = var.region
}

data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"

principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}

actions = ["sts:AssumeRole"]
}
}

resource "aws_iam_role" "profile" {
name = "${var.instance_profile_role_name}-${var.environment}"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

resource "aws_iam_role_policy_attachment" "profile" {
role = aws_iam_role.profile.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}

resource "aws_iam_instance_profile" "profile" {
name = "${var.instance_profile_name}-${var.environment}"
role = aws_iam_role.profile.name
}

resource "aws_iam_policy" "cd" {
name = "${var.cd_iam_policy_name}-dsst-${var.environment}"
policy = file("${path.module}/policies/gha-policy.json")
}

resource "aws_iam_role" "cd" {
name = "${var.cd_iam_role_policy_name}-dsst-${var.environment}"
assume_role_policy = templatefile("${path.module}/policies/assume-role.json.tftpl",
{
AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
},
)
}

resource "aws_iam_role_policy_attachment" "cd" {
role = aws_iam_role.cd.name
policy_arn = aws_iam_policy.cd.arn
}

data "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
}
3 changes: 3 additions & 0 deletions terraform/modules/iam/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "instance_profile_name" {
value = aws_iam_instance_profile.profile.name
}
23 changes: 23 additions & 0 deletions terraform/modules/iam/policies/assume-role.json.tftpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": [
"repo:nimh-dsst/dsst-etl:*"
]
},
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}

58 changes: 58 additions & 0 deletions terraform/modules/iam/policies/gha-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds:CreateDBInstance",
"rds:DeleteDBInstance",
"rds:ModifyDBInstance",
"rds:DescribeDBInstances",

"rds:CreateDBSnapshot",
"rds:DeleteDBSnapshot",
"rds:DescribeDBSnapshots",
"rds:RestoreDBInstanceFromDBSnapshot",
"rds:StartDBInstance",
"rds:StopDBInstance",

"rds:DescribeEvents",
"rds:DescribeDBLogFiles",
"rds:DownloadDBLogFilePortion",
"rds:DescribeDBInstanceAutomatedBackups",

"rds:AddRoleToDBInstance",
"rds:RemoveRoleFromDBInstance",
"rds:DescribeDBSecurityGroups",
"rds:AuthorizeDBSecurityGroupIngress",
"rds:RevokeDBSecurityGroupIngress",

"rds:DescribeDBParameterGroups",
"rds:ModifyDBParameterGroup",
"rds:DescribeDBClusterParameterGroups"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:PassRole",
"iam:GetRole",
"iam:CreateRole",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"rds:*",
"ec2:DescribeSecurityGroups",
"ec2:CreateSecurityGroup",
"ec2:DeleteSecurityGroup"
],
"Resource": "*"
}
]
}
40 changes: 40 additions & 0 deletions terraform/modules/iam/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
variable "environment" {
description = "The name of the environment. Usually `shared`, `stage`, or `prod`."
type = string
}

variable "region" {
description = "AWS region"
default = "us-east-1"
type = string
}

variable "instance_profile_name" {
description = "The name of the instance profile"
default = "dsst-etl-instance-profile"
type = string
}

variable "instance_profile_role_name" {
description = "The name of the instance profile"
default = "dsst-etl-instance-profile-role"
type = string
}

variable "cd_iam_policy_name" {
description = "The name of the IAM policy for continuous deployment to ECR"
default = "etl-github-actions-policy"
type = string
}

variable "cd_iam_role_policy_name" {
description = "The name of the IAM role policy for continuous deployment to ECR"
default = "etl-github-actions-role"
type = string
}

variable "AWS_ACCOUNT_ID" {
# All caps variable name because this is read in as an environment variable
description = "The ID of your AWS account. This should be set as an environment variable `TF_VAR_AWS_ACCOUNT_ID`."
type = string
}
35 changes: 35 additions & 0 deletions terraform/modules/networking/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
terraform {
required_version = ">= 1.0.0, < 2.0.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = var.region
}

# Use data source to reference existing VPC
data "aws_vpc" "selected" {
id = var.environment == "shared" ? "vpc-0da7e09c28aed91d4" : (
var.environment == "stage" ? "vpc-04e9bc794785725bd" : "vpc-08907c4cf973b8351"
)
}

# Get existing subnets in the VPC
data "aws_subnets" "existing" {
filter {
name = "vpc-id"
values = [data.aws_vpc.selected.id]
}
}

# Get existing security groups
data "aws_security_group" "default" {
vpc_id = data.aws_vpc.selected.id
name = "default"
}
14 changes: 14 additions & 0 deletions terraform/modules/networking/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
output "vpc_id" {
description = "ID of the VPC"
value = data.aws_vpc.selected.id
}

output "subnet_ids" {
description = "List of subnet IDs"
value = data.aws_subnets.existing.ids
}

output "default_security_group_id" {
description = "ID of the default security group"
value = data.aws_security_group.default.id
}
10 changes: 10 additions & 0 deletions terraform/modules/networking/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
variable "environment" {
description = "The name of the environment. Usually `shared`, `stage`, or `prod`."
type = string
}

variable "region" {
description = "AWS region"
default = "us-east-1"
type = string
}
72 changes: 72 additions & 0 deletions terraform/modules/state/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
terraform {
required_version = ">= 1.0.0, < 2.0.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = var.aws_region
}

resource "aws_s3_bucket" "tf_state" {
bucket = "${var.bucket_name}-${var.environment}"

tags = {
Name = "${var.bucket_name}-${var.environment}"
}
}

resource "aws_s3_bucket_lifecycle_configuration" "tf_state" {
bucket = aws_s3_bucket.tf_state.id
rule {
id = "tf_state_${var.environment}"
status = "Enabled"

transition {
days = 30
storage_class = "STANDARD_IA"
}

expiration {
days = 365
}
}
}

resource "aws_s3_bucket_versioning" "enabled" {
bucket = aws_s3_bucket.tf_state.id

versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
bucket = aws_s3_bucket.tf_state.id

rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

resource "aws_dynamodb_table" "tf_locks" {
name = "${var.table_name}-${var.environment}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"

attribute {
name = "LockID"
type = "S"
}

tags = {
Name = "${var.bucket_name}-${var.environment}"
}
}
9 changes: 9 additions & 0 deletions terraform/modules/state/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "s3_bucket_arn" {
value = aws_s3_bucket.tf_state.arn
description = "The ARN of the S3 bucket"
}

output "dynamodb_table_name" {
value = aws_dynamodb_table.tf_locks.name
description = "The name of the DynamoDB table"
}
22 changes: 22 additions & 0 deletions terraform/modules/state/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
variable "bucket_name" {
description = "The name of the S3 bucket to store Terraform state. Must be globally unique."
type = string
default = "dsst-etl-terraform-state-storage"
}

variable "table_name" {
description = "The name of the DynamoDB table. Must be unique in this AWS account."
type = string
default = "dsst-etl-state-locks"
}

variable "aws_region" {
description = "The AWS region used by the deployment"
type = string
default = "us-east-1"
}

variable "environment" {
description = "The name of the development environment. Usually `stage` or `prod`."
type = string
}
Loading

0 comments on commit e478547

Please sign in to comment.