Skip to content

Commit

Permalink
inital one
Browse files Browse the repository at this point in the history
Signed-off-by: Andrey Devyatkin <andrey.devyatkin@fivexl.io>
  • Loading branch information
Andrey9kin committed Feb 10, 2021
1 parent dec4b66 commit 2e81e94
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
# Crash log files
crash.log

# lock files
.terraform.lock.hcl

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[![FivexL](https://releases.fivexl.io/fivexlbannergit.jpg)](https://fivexl.io/)

# tf
Terraform wrapper for multi-environment setups
Terraform wrapper for multi-environment AWS setup
42 changes: 42 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
provider "aws" {
}

terraform {
backend "s3" {
}
}

data "aws_caller_identity" "current" {}

data "aws_region" "current" {}

locals {
state_bucket_name = format("terraform-state-%s", sha1("${data.aws_caller_identity.current.account_id}-${data.aws_region.current.name}"))
}

# This is state bucket used above
module "state_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "1.17.0"

bucket = local.state_bucket_name
acl = "private"

versioning = {
enabled = true
}

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

// S3 bucket-level Public Access Block configuration
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
97 changes: 97 additions & 0 deletions tf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/usr/env/bin bash

set -e


TF_PARALLELISM=${TF_PARALLELISM:-10}
TF_STATE_BUCKET=${TF_STATE_BUCKET:-}
TF_STATE_PATH=${TF_STATE_PATH:-}
TF_STATE_FILE_NAME=${TF_STATE_FILE_NAME:-main.tfstate}
TF_TERRAFORM_EXECUTABLE=${TF_TERRAFORM_EXECUTABLE:-terraform}
TF_ENVIRONMENT_ID=${TF_ENVIRONMENT_ID:-}

[ -e ./.terraform_executable ] && export TF_TERRAFORM_EXECUTABLE="$(cat .terraform_executable)"

if [ "$#" -eq 0 ] || [ "$*" == "-h" ] || [ "$*" == "-h" ]
then
echo "This is a Terraform wrapper to dynamically pick different state files for different environment"
echo "Wrapper will attempt to pick defaults and setup a correct bucket"
echo "All script argumetns will be passed to Terraform"
echo ""
echo "Example:"
echo "tf plan"
echo "tf destroy"
echo ""
echo "tf will indentify your env based on current AWS account id and region"
echo ""
exit 0
fi

if [ -z "${AWS_DEFAULT_REGION}" ]
then
echo "Define env variable AWS_DEFAULT_REGION (should be your region name, ex us-east-1) and try again"
exit 1
fi

if [ -z "${TF_ENVIRONMENT_ID}" ]; then
if [ -z $(which aws) ]; then
echo "aws cli is required to identify environment id. https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html"
exit 1
fi
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
if [ -z "${AWS_ACCOUNT_ID}" ]; then
echo "Can't determine aws account id by running 'aws sts get-caller-identity'. Please make sure that you have valid credentials and try again"
echo "Or provide your own TF_ENVIRONMENT_ID"
exit 1
fi
export TF_ENVIRONMENT_ID="${AWS_ACCOUNT_ID}-${AWS_DEFAULT_REGION}"
echo "Based on aws config assuming TF_ENVIRONMENT_ID=${TF_ENVIRONMENT_ID}"
else
echo "Using user provided TF_ENVIRONMENT_ID=${TF_ENVIRONMENT_ID}"
fi

if [ -z "${TF_STATE_BUCKET}" ]; then
# Use hashed environment id to avoid account id/region disclosure via S3 DNS name
# in this way it is hard to predict the bucket name and attacker won't be able to
# setup buckets in advance to capture your state file
HASHED_ENVIRONMENT_ID=$(echo -n ${TF_ENVIRONMENT_ID} | sha1sum | awk '{print $1}')
export TF_STATE_BUCKET="terraform-state-${HASHED_ENVIRONMENT_ID}"
fi

if [ -z "${TF_STATE_PATH}" ]; then
# Check if we are in git repo
GIT_REPO_TEST=$(git rev-parse --git-dir 2> /dev/null || true)
if [ -z "${GIT_REPO_TEST}" ]
then
echo "tf expects you to run inside git repo since it will be using git repo name as part of the state"
exit 1
fi

# Try to get remote repo name
# we can't use just local repo name because jenkins pipelines
# clone repos to directories with abracadabra names which are not the same
# as actual repo name
if [ ! -z "$(git config --get remote.origin.url)" ]
then
REPO_NAME=$(basename -s .git $(git config --get remote.origin.url))
echo "Using remote repo name \"${REPO_NAME}\" as a part of Terraform state path"
else
# If there are no remote repo then fall back to local repo directory name
REPO_NAME=$(basename $(git rev-parse --show-toplevel))
echo "Can not find remote repo name. Using local repo name \"${REPO_NAME}\" as a part of Terraform state path"
fi
export TF_STATE_PATH="terraform/${REPO_NAME}/${TF_STATE_FILE_NAME}"
fi

echo "Using remote state s3://${TF_STATE_BUCKET}/${TF_STATE_PATH}"

set -x

${TF_TERRAFORM_EXECUTABLE} init -backend-config "key=${TF_STATE_PATH}" -backend-config "bucket=${TF_STATE_BUCKET}" -backend-config "region=${AWS_DEFAULT_REGION}"

# If we are applying changes, do not ask for interactive approval
[ $1 == "apply" ] && export OPTIONS="-auto-approve"
# figure out which env file to use
[ -e ./${TF_ENVIRONMENT_ID}.tfvars ] && export VAR_FILE="-var-file=./${TF_ENVIRONMENT_ID}.tfvars"

${TF_TERRAFORM_EXECUTABLE} $* ${VAR_FILE} ${OPTIONS}

0 comments on commit 2e81e94

Please sign in to comment.