Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
KyMidd committed Nov 29, 2019
0 parents commit 90923b9
Show file tree
Hide file tree
Showing 13 changed files with 942 additions and 0 deletions.
16 changes: 16 additions & 0 deletions buildspec_terraform_apply.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: 0.2

phases:
install:
runtime-versions:
python: 3.7
commands:
- tf_version=$TERRAFORM_VERSION
- wget https://releases.hashicorp.com/terraform/"$TERRAFORM_VERSION"/terraform_"$TERRAFORM_VERSION"_linux_amd64.zip
- unzip terraform_"$TERRAFORM_VERSION"_linux_amd64.zip
- mv terraform /usr/local/bin/
build:
commands:
- terraform --version
- terraform init -input=false
- terraform apply -auto-approve -input=false
17 changes: 17 additions & 0 deletions buildspec_terraform_plan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 0.2

phases:
install:
runtime-versions:
python: 3.7
commands:
- tf_version=$TERRAFORM_VERSION
- wget https://releases.hashicorp.com/terraform/"$TERRAFORM_VERSION"/terraform_"$TERRAFORM_VERSION"_linux_amd64.zip
- unzip terraform_"$TERRAFORM_VERSION"_linux_amd64.zip
- mv terraform /usr/local/bin/
build:
commands:
- terraform --version
- terraform init -input=false
- terraform validate
- terraform plan -lock=false -input=false
71 changes: 71 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Require TF version to be same as or greater than 0.12.16
terraform {
required_version = ">=0.12.16"
backend "s3" {
bucket = "kyler-codebuild-demo-terraform-tfstate"
key = "terraform.tfstate"
region = "us-east-1"
dynamodb_table = "codebuild-dynamodb-terraform-locking"
encrypt = true
}
}

# Download any stable version in AWS provider of 2.36.0 or higher in 2.36 train
provider "aws" {
region = "us-east-1"
version = "~> 2.36.0"
assume_role {
# Remember to update this account ID to yours
role_arn = "arn:aws:iam::718626770228:role/TerraformAssumedIamRole"
session_name = "terraform"
}
}


## Step 1: Build an IAM user with administrative rights
# Export the access key and secret access key into global bash variables. The commands will look like this:
# export AWS_ACCESS_KEY_ID="AKIA2OULU2K4324HLYFNU"
# export AWS_SECRET_ACCESS_KEY="b8ma12345678901234567890toWCOjo"


## Step 2: Build an S3 bucket and DynamoDB for Terraform state and locking
module "bootstrap" {
source = "./modules/bootstrap"
s3_tfstate_bucket = "kyler-codebuild-demo-terraform-tfstate"
s3_logging_bucket_name = "kyler-codebuild-demo-logging-bucket"
dynamo_db_table_name = "codebuild-dynamodb-terraform-locking"
codebuild_iam_role_name = "CodeBuildIamRole"
codebuild_iam_role_policy_name = "CodeBuildIamRolePolicy"
terraform_codecommit_repo_arn = module.codecommit.terraform_codecommit_repo_arn
tf_codepipeline_artifact_bucket_arn = module.codepipeline.tf_codepipeline_artifact_bucket_arn
}

## Step 3: Build a CodeCommit git repo
module "codecommit" {
source = "./modules/codecommit"
repository_name = "CodeCommitTerraform"
}


## Step 4: Build CodeBuild projects for Terraform Plan and Terraform Apply
module "codebuild" {
source = "./modules/codebuild"
codebuild_project_terraform_plan_name = "TerraformPlan"
codebuild_project_terraform_apply_name = "TerraformApply"
s3_logging_bucket_id = module.bootstrap.s3_logging_bucket_id
codebuild_iam_role_arn = module.bootstrap.codebuild_iam_role_arn
s3_logging_bucket = module.bootstrap.s3_logging_bucket
}


## Step 5: Build a CodePipeline
module "codepipeline" {
source = "./modules/codepipeline"
tf_codepipeline_name = "TerraformCodePipeline"
tf_codepipeline_artifact_bucket_name = "kyler-codebuild-demo-artifact-bucket-name"
tf_codepipeline_role_name = "TerraformCodePipelineIamRole"
tf_codepipeline_role_policy_name = "TerraformCodePipelineIamRolePolicy"
terraform_codecommit_repo_name = module.codecommit.terraform_codecommit_repo_name
codebuild_terraform_plan_name = module.codebuild.codebuild_terraform_plan_name
codebuild_terraform_apply_name = module.codebuild.codebuild_terraform_apply_name
}
241 changes: 241 additions & 0 deletions modules/bootstrap/bootstrap.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
##
# Module to build the Azure DevOps "seed" configuration
##

# Build an S3 bucket to store TF state
resource "aws_s3_bucket" "state_bucket" {
bucket = var.s3_tfstate_bucket

# Tells AWS to encrypt the S3 bucket at rest by default
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

# Prevents Terraform from destroying or replacing this object - a great safety mechanism
lifecycle {
prevent_destroy = true
}

# Tells AWS to keep a version history of the state file
versioning {
enabled = true
}

tags = {
Terraform = "true"
}
}

# Build a DynamoDB to use for terraform state locking
resource "aws_dynamodb_table" "tf_lock_state" {
name = var.dynamo_db_table_name

# Pay per request is cheaper for low-i/o applications, like our TF lock state
billing_mode = "PAY_PER_REQUEST"

# Hash key is required, and must be an attribute
hash_key = "LockID"

# Attribute LockID is required for TF to use this table for lock state
attribute {
name = "LockID"
type = "S"
}

tags = {
Name = var.dynamo_db_table_name
Terraform = "true"
}
}


# Build an AWS S3 bucket for logging
resource "aws_s3_bucket" "s3_logging_bucket" {
bucket = var.s3_logging_bucket_name
acl = "private"

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

# Output name of S3 logging bucket back to main.tf
output "s3_logging_bucket_id" {
value = aws_s3_bucket.s3_logging_bucket.id
}
output "s3_logging_bucket" {
value = aws_s3_bucket.s3_logging_bucket.bucket
}

# Create an IAM role for CodeBuild to assume
resource "aws_iam_role" "codebuild_iam_role" {
name = var.codebuild_iam_role_name

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}

# Output the CodeBuild IAM role
output "codebuild_iam_role_arn" {
value = aws_iam_role.codebuild_iam_role.arn
}


# Create an IAM role policy for CodeBuild to use implicitly
resource "aws_iam_role_policy" "codebuild_iam_role_policy" {
name = var.codebuild_iam_role_policy_name
role = aws_iam_role.codebuild_iam_role.name

policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
"*"
],
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"${aws_s3_bucket.s3_logging_bucket.arn}",
"${aws_s3_bucket.s3_logging_bucket.arn}/*",
"${aws_s3_bucket.state_bucket.arn}",
"${aws_s3_bucket.state_bucket.arn}/*",
"arn:aws:s3:::codepipeline-us-east-1*",
"arn:aws:s3:::codepipeline-us-east-1*/*",
"${var.tf_codepipeline_artifact_bucket_arn}",
"${var.tf_codepipeline_artifact_bucket_arn}/*"
]
},
{
"Effect": "Allow",
"Action": [
"dynamodb:*"
],
"Resource": "${aws_dynamodb_table.tf_lock_state.arn}"
},
{
"Effect": "Allow",
"Action": [
"codecommit:BatchGet*",
"codecommit:BatchDescribe*",
"codecommit:Describe*",
"codecommit:EvaluatePullRequestApprovalRules",
"codecommit:Get*",
"codecommit:List*",
"codecommit:GitPull"
],
"Resource": "${var.terraform_codecommit_repo_arn}"
},
{
"Effect": "Allow",
"Action": [
"iam:Get*",
"iam:List*"
],
"Resource": "${aws_iam_role.codebuild_iam_role.arn}"
},
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "${aws_iam_role.codebuild_iam_role.arn}"
}
]
}
POLICY
}


# Create IAM role for Terraform builder to assume
resource "aws_iam_role" "tf_iam_assumed_role" {
name = "TerraformAssumedIamRole"

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "${aws_iam_role.codebuild_iam_role.arn}"
},
"Action": "sts:AssumeRole"
}
]
}
EOF

lifecycle {
prevent_destroy = true
}

tags = {
Terraform = "true"
}
}


# Create broad IAM policy Terraform to use to build, modify resources
resource "aws_iam_policy" "tf_iam_assumed_policy" {
name = "TerraformAssumedIamPolicy"

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAllPermissions",
"Effect": "Allow",
"Action": [
"*"
],
"Resource": "*"
}
]
}
EOF

lifecycle {
prevent_destroy = true
}
}

# Attach IAM assume role to policy
resource "aws_iam_role_policy_attachment" "tf_iam_attach_assumed_role_to_permissions_policy" {
role = aws_iam_role.tf_iam_assumed_role.name
policy_arn = aws_iam_policy.tf_iam_assumed_policy.arn

lifecycle {
prevent_destroy = true
}
}
25 changes: 25 additions & 0 deletions modules/bootstrap/bootstrap_variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
##
# Define variables for Azure DevOps Seed Module
##

variable "s3_tfstate_bucket" {
description = "Name of the S3 bucket used for Terraform state storage"
}
variable "s3_logging_bucket_name" {
description = "Name of S3 bucket to use for access logging"
}
variable "dynamo_db_table_name" {
description = "Name of DynamoDB table used for Terraform locking"
}
variable "codebuild_iam_role_name" {
description = "Name for IAM Role utilized by CodeBuild"
}
variable "codebuild_iam_role_policy_name" {
description = "Name for IAM policy used by CodeBuild"
}
variable "terraform_codecommit_repo_arn" {
description = "Terraform CodeCommit git repo ARN"
}
variable "tf_codepipeline_artifact_bucket_arn" {
description = "Codepipeline artifact bucket ARN"
}
Loading

0 comments on commit 90923b9

Please sign in to comment.