adding subaccount module

ctalarms-whitelist
lalanza808 4 years ago
parent ea7a2b2174
commit 1c37cbe254

@ -0,0 +1,51 @@
# aws-master - accounts
This module sets up a subordinate AWS account under a given organization. You need to use it in conjunction with the `aws-master/organizations` module to setup the Organizations backend on a master payer account.
Only use this module on the "Master Payer" AWS account.
*This has not been tested yet and will not work*.
## Usage
```
module "master_payer" {
source = "github.com/lalanza808/tf-modules.git/organizations/suborganizations"
prefix = module.labels.id
tags = module.labels.tags
enable_cur = true # cost and usage reporting to S3
enable_org = true # enables organizations service
}
module "aws_account_sandbox" "sandbox" {
source = "github.com/lalanza808/tf-modules.git/organizations/subaccounts"
account_name = "sandbox"
account_email = "aws-admin+sandbox@corp.com"
parent_ou_id = module.master_payer.prod_ou_id
}
output "sandbox_account_id" {
value = module.aws_account_sandbox.sandbox.account_id
}
```
## Inputs
You need to specify the following:
* `parent_ou_id`
* `account_name`
* `account_email`
See the full list of inputs here: [variables.tf](./variables.tf)
## Outputs
* `account_id`
* `account_arn`
[output.tf](./output.tf)

@ -0,0 +1,41 @@
#!/bin/bash
# This script initializes newly created AWS accounts with a Cloudformation init template.
# It is executed by a null_resource and should only trigger once per account.
# Don't echo commands and error on any issues with auth/assume role
set +x
set -e
# Wait a bit before proceeding - the script will invoke right after the account is created but sometimes takes a few seconds
sleep 30
# Assume a role into the Master AWS account
TEMPCREDS=$(aws sts assume-role --duration-seconds 900 \
--role-arn arn:aws:iam::${MASTER_ACCOUNT_ID}:role/${MASTER_ACCOUNT_ROLE} \
--role-session-name terraform-auto-account-provisioning)
export AWS_ACCESS_KEY_ID=$(echo $TEMPCREDS | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $TEMPCREDS | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $TEMPCREDS | jq -r '.Credentials.SessionToken')
# Assume another role through the Master into the newly provisioned account
TEMPCREDS=$(aws sts assume-role --duration-seconds 900 \
--role-arn arn:aws:iam::${ACCOUNT_ID}:role/${ROLE_NAME} \
--role-session-name terraform-auto-account-provisioning)
export AWS_ACCESS_KEY_ID=$(echo $TEMPCREDS | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $TEMPCREDS | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $TEMPCREDS | jq -r '.Credentials.SessionToken')
set -x
# Now echo commands and don't error because for some reason 0> codes can be expected with `aws cloudformation deploy`
set +e
# Deploy a Cloudformation stack to the new account to initialize the access roles
aws cloudformation deploy \
--stack-name "${STACK_NAME}" \
--template-file "${FILE_PATH}" \
--parameter-overrides "Account=${ACCOUNT_NAME}" \
--capabilities "CAPABILITY_NAMED_IAM" \
--region "${REGION}"
exit 0

@ -0,0 +1,82 @@
---
AWSTemplateFormatVersion: "2010-09-09"
Description: This stack creates the required resources for cross account management.
Parameters:
Prefix:
Type: String
Description: "The string to prefix in front of created resources"
Default: "organizations"
Account:
Type: String
Description: "The name of the account - dev, test, stage, prod, mgmt, etc"
Resources:
# IAM
ManagementRole:
Type: AWS::IAM::Role
Properties:
RoleName: ManagementRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- arn:aws:iam::${AWS::AccountId}:role/OrganizationAccountAccessRole
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
# Terraform Backend
TerraformStateBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub ${Prefix}-${Account}-terraform-state
VersioningConfiguration:
Status: Enabled
TerraformStateBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref TerraformStateBucket
PolicyDocument:
Statement:
- Action: s3:*
Effect: Allow
Principal:
AWS: arn:aws:iam::000000000000:role/RemoteAccess
Resource:
- !GetAtt TerraformStateBucket.Arn
- !Join
- '/'
- - !GetAtt TerraformStateBucket.Arn
- '*'
TerraformStateTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: LockID
AttributeType: S
KeySchema:
- AttributeName: LockID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
TableName: !Sub ${Prefix}-${Account}-terraform-locks
Outputs:
TerraformStateBucketOutput:
Description: Bucket used to store Terraform remote state file
Value: !Ref TerraformStateBucket
TerraformStateTableOutput:
Description: DynamoDB table used for Terraform state locking functionality
Value: !Ref TerraformStateTable
ManagementRoleArn:
Value: !GetAtt ManagementRole.Arn

@ -0,0 +1,43 @@
locals {
cft_file = "${path.module}/files/init.yaml"
cft_script = "${path.module}/files/account_init.sh"
}
data "local_file" "init_cft" {
filename = local.cft_file
}
resource "aws_organizations_account" "this" {
name = var.account_name
email = var.account_email
iam_user_access_to_billing = var.iam_billing_access
parent_id = var.parent_ou_id
role_name = var.access_role_name
tags = var.tags
# There is no AWS Organizations API for reading role_name
lifecycle {
ignore_changes = ["role_name"]
}
}
resource "null_resource" "initialize" {
triggers = {
file_content = data.local_file.init_cft.content_base64
}
provisioner "local-exec" {
command = local.cft_script
environment = {
STACK_NAME = var.init_stack_name
FILE_PATH = local.cft_file
REGION = var.init_stack_region
ACCOUNT_ID = aws_organizations_account.this.id
ROLE_NAME = var.access_role_name
ACCOUNT_NAME = var.account_name
MASTER_ACCOUNT_ID = var.master_account_id
MASTER_ACCOUNT_ROLE = var.master_account_role
}
}
}

@ -0,0 +1,7 @@
output "account_id" {
value = aws_organizations_account.this.id
}
output "account_arn" {
value = aws_organizations_account.this.arn
}

@ -0,0 +1,36 @@
variable "iam_billing_access" {
default = "ALLOW"
}
variable "access_role_name" {
default = "OrganizationAccountAccessRole"
}
variable "master_account_id" {
description = "Master AWS account ID where Organizations are provisioned"
default = "0000000000"
}
variable "master_account_role" {
description = "Role to assume into Master AWS account"
default = "ManagementAccess"
}
variable "tags" {
default = {}
type = "map"
}
variable "init_stack_name" {
default = "organizations-account-init"
description = "Name of the Cloudformation stack to use"
}
variable "init_stack_region" {
default = "us-east-1"
description = "Region to deploy the Cloudformation init stack into"
}
variable "parent_ou_id" {}
variable "account_name" {}
variable "account_email" {}
Loading…
Cancel
Save