diff --git a/README.md b/README.md index b994556..482337f 100644 --- a/README.md +++ b/README.md @@ -85,15 +85,15 @@ organization = { accounts = { dev = { account_name = "primeharbor-kickstart-dev" - account_email = ""aws+kickstart-dev@primeharbor.com" + account_email = "aws+kickstart-dev@primeharbor.com" } it = { account_name = "primeharbor-kickstart-it" - account_email = ""aws+kickstart-it@primeharbor.com" + account_email = "aws+kickstart-it@primeharbor.com" } sandbox = { account_name = "primeharbor-kickstart-sandbox" - account_email = ""aws+kickstart-sandbox@primeharbor.com" + account_email = "aws+kickstart-sandbox@primeharbor.com" parent_ou_id = "ou-yyyy-yyyyyyyy" } } @@ -112,8 +112,7 @@ organization = { phone_number = "+14041234567" } - organization_units = { - + organizational_units = { "bu1" = { name = "business_unit_1" is_child_of_root = true diff --git a/account_configurator.tf b/account_configurator.tf index 0d0242a..e541caa 100644 --- a/account_configurator.tf +++ b/account_configurator.tf @@ -37,4 +37,3 @@ resource "aws_s3_object" "account_factory_config" { key = var.account_configurator["account_factory_config_file"] source = "${path.root}/${var.account_configurator["account_factory_config_file"]}" } - diff --git a/accounts.tf b/accounts.tf index 6dc4672..c1b4d81 100644 --- a/accounts.tf +++ b/accounts.tf @@ -33,4 +33,3 @@ module "accounts" { primary_contact = var.global_primary_contact disable_sso_management = var.disable_sso_management } - diff --git a/audit-role.tf b/audit-role.tf index 7bd57d5..1647a81 100644 --- a/audit-role.tf +++ b/audit-role.tf @@ -19,7 +19,7 @@ resource "aws_cloudformation_stack_set" "audit_role" { permission_model = "SERVICE_MANAGED" call_as = "DELEGATED_ADMIN" description = "Deploy the Audit Role to all AWS Accounts" - template_url = "https://s3.amazonaws.com/pht-cloudformation/aws-account-automation/AuditRole-Template.yaml" + template_url = var.audit_role_template_url # Bug with provider https://github.com/hashicorp/terraform-provider-aws/issues/23464 # TF attempts to remove the administration_role_arn, even though it's added as part of a tf refresh @@ -77,7 +77,7 @@ resource "aws_cloudformation_stack_set_instance" "audit_role" { resource "aws_cloudformation_stack" "audit_role_payer" { count = var.deploy_audit_role == true ? 1 : 0 name = "audit-role" - template_url = "https://s3.amazonaws.com/pht-cloudformation/aws-account-automation/AuditRole-Template.yaml" + template_url = var.audit_role_template_url parameters = { TrustedAccountNumber = module.security_account.account_id @@ -86,4 +86,4 @@ resource "aws_cloudformation_stack" "audit_role_payer" { capabilities = [ "CAPABILITY_NAMED_IAM" ] -} \ No newline at end of file +} diff --git a/billing_alerts.tf b/billing_alerts.tf index 42a3025..480920c 100644 --- a/billing_alerts.tf +++ b/billing_alerts.tf @@ -1,16 +1,16 @@ -# # Copyright 2024 Chris Farris -# # -# # Licensed under the Apache License, Version 2.0 (the "License"); -# # you may not use this file except in compliance with the License. -# # You may obtain a copy of the License at -# # -# # http://www.apache.org/licenses/LICENSE-2.0 -# # -# # Unless required by applicable law or agreed to in writing, software -# # distributed under the License is distributed on an "AS IS" BASIS, -# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# # See the License for the specific language governing permissions and -# # limitations under the License. +# Copyright 2024 Chris Farris +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. resource "aws_sns_topic" "billing_alerts" { @@ -44,4 +44,4 @@ resource "aws_sns_topic_subscription" "billing_alerts" { topic_arn = aws_sns_topic.billing_alerts[0].arn protocol = "email" endpoint = each.key -} \ No newline at end of file +} diff --git a/examples/pipeline/README.md b/examples/pipeline/README.md index 792df60..f73537a 100644 --- a/examples/pipeline/README.md +++ b/examples/pipeline/README.md @@ -25,11 +25,11 @@ Overview ``` 2. You must import the organizational management account and the organization that was created via ClickOps ```bash - ./scripts/import-org.sh + ./scripts/import_org.sh cat import-org.tf ``` 3. Review the import-org.tf file for accuracy. -4. Run the teraform plan to create the security account (if one doesn't already exist) +4. Run the terraform plan to create the security account (if one doesn't already exist) ```bash terraform plan -out=${env}-terraform.tfplan -no-color -var-file="${env}.tfvars" -target module.organization.module.security_account ``` @@ -38,10 +38,12 @@ Overview make tf-apply ``` 6. Disable the creations of All AWS Accounts and Custom SCPs in your TF Vars file - 1. Comment out the `accounts = {}` block - 2. Comment out the `service_control_policies = {}` block - 3. We will re-enable them after the first apply. - 4. Delete the `security_services.tf` file on the first run. + 1. **IMPORTANT**: Ensure that your `payer_name` and `payer_email` variables align with what you manually used when creating the first AWS account, otherwise + it will force a recreation of the account. + 2. Comment out the `accounts = {}` block + 3. Comment out the `service_control_policies = {}` block + 4. We will re-enable them after the first apply. + 5. Delete the `security_services.tf` file on the first run. 7. Run the full terraform plan ```bash make tf-plan @@ -57,8 +59,6 @@ Overview make tf-plan ``` - - If you see the following error: ``` Error: listing Organizations Accounts for parent (r-117h) and descendants: AccessDeniedException: You don't have permissions to access this resource. @@ -85,7 +85,7 @@ git submodule add https://github.com/primeharbor/pht-account-configurator git submodule init git submodule update -EOF + diff --git a/examples/pipeline/main.tf b/examples/pipeline/main.tf index bf6256d..569267d 100644 --- a/examples/pipeline/main.tf +++ b/examples/pipeline/main.tf @@ -68,7 +68,7 @@ module "organization" { # Map Objects accounts = lookup(var.organization, "accounts", {}) service_control_policies = lookup(var.organization, "service_control_policies", {}) - organization_units = lookup(var.organization, "organization_units", {}) + organizational_units = lookup(var.organization, "organizational_units", {}) account_configurator = lookup(var.organization, "account_configurator", null) billing_alerts = lookup(var.organization, "billing_alerts", null) @@ -97,4 +97,4 @@ output "org_name" { output "security_account_id" { value = module.organization.security_account_id -} \ No newline at end of file +} diff --git a/examples/pipeline/sample.tfvars b/examples/pipeline/sample.tfvars index e229c4f..1686da0 100644 --- a/examples/pipeline/sample.tfvars +++ b/examples/pipeline/sample.tfvars @@ -28,11 +28,11 @@ organization = { disable_sso_management = false deploy_audit_role = true audit_role_name = "security-audit" + audit_role_template_url = "https://s3.amazonaws.com/pht-cloudformation/aws-account-automation/AuditRole-Template.yaml" vpc_flowlogs_bucket_name = "primeharbor-kickstart-flowlogs" macie_bucket_name = "primeharbor-kickstart-macie-findings" - organization_units = { - + organizational_units = { "MemeFactories" = { name = "MemeFactories" is_child_of_root = true @@ -41,7 +41,6 @@ organization = { name = "CoreIT" is_child_of_root = true } - } accounts = { @@ -56,7 +55,7 @@ organization = { sandbox = { account_name = "primeharbor-kickstart-sandbox" account_email = "aws+kickstart-sandbox@primeharbor.com" - parent_ou_id = "ou-yyyy-yyyyyyyy" + parent_ou_id = "Sandbox" } } @@ -84,7 +83,7 @@ organization = { policy_name = "SuspendedAccounts" policy_description = "Denies all activity in accounts in the SuspendedOU" policy_json_file = "policies/SuspendedAccountsPolicy.json.tftpl" - policy_targets = ["ou-xxxx-xxxxxxxx"] + policy_targets = ["Suspended"] policy_vars = { audit_role_name = "security-audit" } @@ -103,8 +102,8 @@ organization = { policy_description = "Deny access to unapproved default regions" policy_json_file = "policies/DisableRegionsPolicy.json.tftpl" policy_targets = [ - "ou-xxxx-xxxxxxxx", # Workloads - "ou-yyyy-yyyyyyyy" # Sandbox + "Workloads", + "Sandbox" ] policy_vars = { allowed_regions = ["us-east-1", "eu-west-1"] @@ -117,8 +116,8 @@ organization = { policy_description = "Deny access to unapproved Instance Types" policy_json_file = "policies/DenyUnapprovedInstanceTypes.json" policy_targets = [ - "ou-xxxx-xxxxxxxx", # Workloads - "ou-yyyy-yyyyyyyy" # Sandbox + "Workloads", + "Sandbox" ] } @@ -127,8 +126,8 @@ organization = { policy_description = "Deny access to unapproved Services" policy_json_file = "policies/DenyUnapprovedServices.json" policy_targets = [ - "ou-xxxx-xxxxxxxx", # Workloads - "ou-yyyy-yyyyyyyy" # Sandbox + "Workloads", + "Sandbox" ] } } @@ -170,4 +169,4 @@ organization = { ] } -} \ No newline at end of file +} diff --git a/examples/pipeline/scripts/generate_regions.sh b/examples/pipeline/scripts/generate_regions.sh index e7bd6c1..fdedb8a 100755 --- a/examples/pipeline/scripts/generate_regions.sh +++ b/examples/pipeline/scripts/generate_regions.sh @@ -21,8 +21,6 @@ else REPO=github.com/primeharbor/org-kickstart//modules/security_services?ref=$VERSION fi -REPO=/Users/chris/AWS/org-kickstart/modules/security_services - REGIONS=`aws ec2 describe-regions | jq -r '.Regions[].RegionName'` # Over write the existing files because we can't have duplicates @@ -73,4 +71,4 @@ EOF done -echo "You may need to re-run terraform init" \ No newline at end of file +echo "You may need to re-run terraform init" diff --git a/main.tf b/main.tf index beecea8..b3aa4cb 100644 --- a/main.tf +++ b/main.tf @@ -30,7 +30,7 @@ data "aws_regions" "current" {} # # Security Service flags variable "security_services" { - description = "explictly disable or not manage a security service" + description = "explicitly disable or not manage a security service" default = { disable_guardduty = "false" disable_macie = "false" @@ -74,4 +74,4 @@ provider "aws" { default_tags { tags = local.default_tags } -} \ No newline at end of file +} diff --git a/modules/security_services/guardduty.tf b/modules/security_services/guardduty.tf index ee0281f..939d678 100644 --- a/modules/security_services/guardduty.tf +++ b/modules/security_services/guardduty.tf @@ -13,7 +13,7 @@ # limitations under the License. -# Explictly create the detectors in the parent and security account +# Explicitly create the detectors in the parent and security account resource "aws_guardduty_detector" "payer_detector" { count = local.security_services["disable_guardduty"] ? 0 : 1 provider = aws.payer_account @@ -80,4 +80,4 @@ resource "aws_guardduty_member" "member" { ] } -} \ No newline at end of file +} diff --git a/modules/security_services/macie.tf b/modules/security_services/macie.tf index 5a835d8..c7cd120 100644 --- a/modules/security_services/macie.tf +++ b/modules/security_services/macie.tf @@ -13,7 +13,7 @@ # limitations under the License. -# Explictly enable Macie in the parent and security account +# Explicitly enable Macie in the parent and security account resource "aws_macie2_account" "payer_account" { count = local.security_services["disable_macie"] ? 0 : 1 provider = aws.payer_account @@ -77,4 +77,4 @@ resource "aws_macie2_member" "member" { ] } -} \ No newline at end of file +} diff --git a/modules/security_services/main.tf b/modules/security_services/main.tf index def2cc1..e584e8f 100644 --- a/modules/security_services/main.tf +++ b/modules/security_services/main.tf @@ -35,7 +35,7 @@ variable "macie_key_arn" { # # Security Service flags variable "security_services" { - description = "explictly disable or not manage a security service" + description = "explicitly disable or not manage a security service" default = { disable_guardduty = "false" disable_macie = "false" @@ -61,4 +61,4 @@ data "aws_organizations_organization" "org" {} data "aws_organizations_organizational_unit_descendant_accounts" "accounts" { provider = aws.security_account parent_id = data.aws_organizations_organization.org.roots[0].id -} \ No newline at end of file +} diff --git a/organization.tf b/organization.tf index 8e9659e..ff643a5 100644 --- a/organization.tf +++ b/organization.tf @@ -49,4 +49,3 @@ resource "aws_organizations_organization" "org" { feature_set = "ALL" } - diff --git a/ous.tf b/ous.tf index 92fff8b..fb8f04b 100644 --- a/ous.tf +++ b/ous.tf @@ -55,7 +55,7 @@ locals { # Accounts you're going to close or have closed go here. resource "aws_organizations_organizational_unit" "custom_ous" { - for_each = var.organization_units + for_each = var.organizational_units name = each.value["name"] parent_id = each.value["is_child_of_root"] ? aws_organizations_organization.org.roots[0].id : local.ou_name_to_id[each.value["parent_id"]] } diff --git a/outputs.tf b/outputs.tf index d13aff8..bbaecc6 100644 --- a/outputs.tf +++ b/outputs.tf @@ -28,5 +28,4 @@ output "macie_key_arn" { output "sso_instance_arn" { description = "AWS Identity Center Instance ARN managed by org-kickstart" value = tolist(data.aws_ssoadmin_instances.identity_store.arns)[0] - -} \ No newline at end of file +} diff --git a/scps.tf b/scps.tf index 71264ca..0d2c173 100644 --- a/scps.tf +++ b/scps.tf @@ -22,5 +22,3 @@ module "scp" { ou_name_to_id = local.ou_name_to_id # Pass the map to avoid regenerating it root_ou = aws_organizations_organization.org.roots[0].id } - - diff --git a/security_account.tf b/security_account.tf index a362e69..73d8f49 100644 --- a/security_account.tf +++ b/security_account.tf @@ -22,7 +22,7 @@ # https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/security-ou-and-accounts.html#security-tooling-accounts -# We explictly create a security account. +# We explicitly create a security account. module "security_account" { source = "./modules/account" @@ -66,4 +66,3 @@ resource "aws_organizations_delegated_administrator" "cloudformation" { account_id = module.security_account.account_id service_principal = "member.org.stacksets.cloudformation.amazonaws.com" } - diff --git a/variables.tf b/variables.tf index 50099df..c5d9662 100644 --- a/variables.tf +++ b/variables.tf @@ -165,7 +165,7 @@ variable "service_control_policies" { default = {} } -variable "organization_units" { +variable "organizational_units" { description = "Map of OUs to deploy" default = {} } @@ -183,4 +183,10 @@ variable "deploy_audit_role" { description = "Boolean to determine if org-kickstart should manage Audit Role" type = bool default = true -} \ No newline at end of file +} + +variable "audit_role_template_url" { + description = "The location of the audit role template URL" + type = string + default = "https://s3.amazonaws.com/pht-cloudformation/aws-account-automation/AuditRole-Template.yaml" +} diff --git a/vpc_flowlogs.tf b/vpc_flowlogs.tf index f3c715c..fdbe51d 100644 --- a/vpc_flowlogs.tf +++ b/vpc_flowlogs.tf @@ -80,5 +80,4 @@ data "aws_iam_policy_document" "vpc_flowlogs_bucket_policy" { actions = ["s3:PutObject"] resources = ["${aws_s3_bucket.vpc_flowlogs_bucket[0].arn}/*"] } - -} \ No newline at end of file +}