NTC Account Factory
Descriptionβ
NTC Account Factory simplifies the creation and management of AWS accounts, providing a robust foundation for scalable, secure, and compliant multi-account environments. This building block automates account provisioning, integrates with your organizational structure, and applies a consistent account baseline to ensure governance at scale. The account baseline enforces guardrails, security configurations, and can be completely customized, ensuring every account aligns with organizational standards.
With NTC Account Factory, you can rapidly deploy accounts tailored to specific workloads, environments, or business units, streamlining your AWS Landing Zone setup and accelerating cloud adoption.
Usageβ
Latest Release | 1.8.4 |
---|
- Account Factory
# --------------------------------------------------------------------------------------------------
# Β¦ NTC ACCOUNT FACTORY
# --------------------------------------------------------------------------------------------------
module "ntc_account_factory" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-account-factory?ref=X.X.X"
# this bucket stores required files for account factory
account_factory_baseline_bucket_name = "ntc-account-factory-baseline"
# this bucket stores required cloudtrail logs for account factory
account_factory_cloudtrail_bucket_name = "ntc-account-factory-cloudtrail"
# increase quotas for aws services used in account factory
increase_aws_service_quotas = {
codebuild_concurrent_runs_arm_small = 20
}
# account names and emails cannot be changed without manual intervention - set naming conventions to avoid mistakes
account_factory_naming_conventions = {
account_name_regex = "^aws-c2-[a-z0-9-]+$"
account_email_regex = "@nuvibit.com$"
}
# can be stored as HCL or alternatively as JSON for easy integration e.g. self service portal integration via git
account_factory_list = [
{
"account_name": "aws-c2-demo",
"account_email": "demo-account@nuvibit.com",
"ou_path": "/root/workloads/dev",
"close_on_deletion": true,
"account_tags": {
"AccountOwner": "demo-admin@nuvibit.com",
"AccountType": "workload",
"AccountDescription": "This is a demo account",
"AccountDecommission": false,
},
"alternate_contacts": [
{
"type": "SECURITY",
"name": "Security Contact",
"email_address": "demo-security@nuvibit.com"
}
],
"customer_values": {}
}
]
# notify on account lifecycle step functions or account baseline pipeline errors
account_factory_notification_settings = {
# identify for which AWS Organization notifications are sent
org_identifier = "c2"
# multiple subscriptions with different protocols is supported
subscriptions = [
{
protocol = "email"
endpoints = ["demo-ops@nuvibit.com"]
}
]
}
# (optional) credentials if you want to reference Terraform modules in your account baseline
# https://developer.hashicorp.com/terraform/language/modules/sources
#Β WARNING: do not store credentials in clear text in git - reference from a vault or from environment variable
#Β account_baseline_git_ssh_key = var.account_baseline_git_ssh_key
#Β account_baseline_github_access_token = var.account_baseline_github_access_token
#Β account_baseline_terraform_registry_token = var.account_baseline_terraform_registry_token
#Β account_baseline_terraform_registry_host = "spacelift.io"
# --------------------------------------------------------------------------------------------------
# Β¦ ACCOUNT LIFECYCLE CUSTOMIZATION
# --------------------------------------------------------------------------------------------------
# provide lambda packages for additional account lifecycle customization e.g. delete default vpc
# trigger for the lambda step functions are cloudtrail events with event source 'organizations.amazonaws.com'
account_lifecycle_customization_steps = [
{
# organizations event (e.g. when a new AWS account is created) that should trigger a lambda step_sequence
organizations_event_trigger = "CreateAccountResult"
# step sequence defines the order in which lambda steps are executed
step_sequence = [
# {
# step_name = "on_account_creation_enable_opt_in_regions"
# lambda_package_source_path = "INSERT_LAMBDA_SOURCE_PATH"
# lambda_handler = "main.lambda_handler"
# environment_variables = {
# "ORGANIZATIONS_MEMBER_ROLE" : "OrganizationAccountAccessRole"
# "OPT_IN_REGIONS" : jsonencode(["eu-central-2"])
# "DEFAULT_REGION" : "eu-central-1"
# }
# }
module.account_lifecycle_customization_templates.account_lifecycle_customization_steps["enable_opt_in_regions"],
module.account_lifecycle_customization_templates.account_lifecycle_customization_steps["delete_default_vpc"],
module.account_lifecycle_customization_templates.account_lifecycle_customization_steps["increase_service_quota"],
]
},
{
organizations_event_trigger = "CloseAccountResult"
step_sequence = [
module.account_lifecycle_customization_templates.account_lifecycle_customization_steps["move_to_suspended_ou"]
]
}
]
# (optional) list of user-defined organizational events to trigger account lifecycle customization step function
# this can be used to force account lifecycle actions for specified accounts
# https://docs.aws.amazon.com/organizations/latest/userguide/orgs_cloudtrail-integration.html
account_lifecycle_customization_on_demand_triggers = {
user_defined_events = [
jsonencode({
"source" : "aws.organizations",
"detail" : {
"eventSource" : "organizations.amazonaws.com",
"eventName" : "CreateAccountResult",
"serviceEventDetails" : {
"createAccountStatus" : {
"state": "SUCCEEDED",
"accountId" : "111111111111"
}
}
}
})
]
}
# list of baseline definitions for accounts in a specific scope
account_baseline_scopes = [
# --------------------------------------------------------------------------------------------------
# Β¦ ACCOUNT BASELINE - WORKLOAD ACCOUNTS
# --------------------------------------------------------------------------------------------------
{
scope_name = "workloads"
# you can use the terraform or opentofu binary for account baseline pipelines
terraform_binary = "opentofu"
# (optional) reduce parallelism to avoid api rate limits when deploying to multiple regions
terraform_parallelism = 10
# https://github.com/hashicorp/terraform/releases
# https://github.com/opentofu/opentofu/releases
terraform_version = "1.8.5"
aws_provider_version = "5.76.0"
# (optional) define provider default tags which will be applied to all baseline resources
provider_default_tags = {
ManagedBy = "ntc-account-factory",
BaselineScope = "workloads",
BaselineVersion = "1.3"
}
# (optional) schedule baseline pipelines to rerun every x hours
schedule_rerun_every_x_hours = 0
# (optional) IAM role which exists in member accounts and can be assumed by baseline pipeline
baseline_execution_role_name = "OrganizationAccountAccessRole"
# (optional) session name used by baseline pipeline in member accounts
baseline_execution_session_name = "ntc-account-factory"
# (optional) additional providers which assume a specific account role for cross account orchestration
# WARNING: removing an existing provider from 'baseline_assume_role_providers' can cause provider errors
baseline_assume_role_providers = [
{
configuration_alias = "connectivity"
role_arn = local.ntc_parameters["connectivity"]["baseline_assume_role_arn"]
session_name = "ntc-account-factory"
}
]
# add terraform code to baseline from static files or dynamic templates
baseline_terraform_files = [
module.account_baseline_templates.account_baseline_terraform_files["iam_monitoring_reader"],
module.account_baseline_templates.account_baseline_terraform_files["iam_instance_profile"],
module.account_baseline_templates.account_baseline_terraform_files["oidc_spacelift"],
module.account_baseline_templates.account_baseline_terraform_files["aws_config"],
]
# add delay to pipeline to avoid errors on first run
# in this case pipeline will wait for up to 10 minutes for dependencies to resolve
pipeline_delay_options = {
wait_for_seconds = 120
wait_retry_count = 5
wait_for_execution_role = true
wait_for_regions = false
wait_for_securityhub = false
wait_for_guardduty = false
}
# baseline terraform code will be provisioned in each specified region
baseline_regions = ["us-east-1", "eu-central-1"]
# baseline terraform code which can be provisioned in a single region (e.g. IAM)
baseline_main_region = "eu-central-1"
# accounts which should be included in baseline scope
include_accounts_all = false
include_accounts_by_ou_paths = [
"/root/workloads/prod",
"/root/workloads/dev",
"/root/workloads/test",
]
include_accounts_by_names = []
include_accounts_by_tags = [
# {
# key = "AccountType"
# value = "workload"
# }
]
# accounts which should be excluded in baseline scope
exclude_accounts_by_ou_paths = []
exclude_accounts_by_names = []
exclude_accounts_by_tags = []
# decomissioning of baseline terraform resources must be done before deleting the scope!
# decommission baseline terraform code for specific accounts in scope
decommission_accounts_all = false
decommission_accounts_by_ou_paths = []
decommission_accounts_by_names = []
decommission_accounts_by_tags = [
{
key = "AccountDecommission"
value = true
}
]
},
]
providers = {
aws = aws.euc1
aws.us_east_1 = aws.use1 # required for account lifecycle cloudtrail
}
}
Requirementsβ
The following requirements are needed by this module:
-
terraform (>= 1.3.1)
-
archive (>= 2.0.0)
-
aws (>= 5.11.0)
Providersβ
The following providers are used by this module:
-
archive (>= 2.0.0)
-
aws (>= 5.11.0)
Modulesβ
The following Modules are called:
account_factory_cloudtrailβ
Source: ./modules/cloudtrail
Version:
baseline_artifacts_bucketβ
Source: ./modules/bucket
Version:
baseline_bucketβ
Source: ./modules/bucket
Version:
lambda_pretty_notificationsβ
Source: ./modules/lambda
Version:
lambda_step_functionβ
Source: ./modules/lambda
Version:
lambda_user_defined_event_triggersβ
Source: ./modules/lambda
Version:
ou_pathβ
Source: ./modules/ou-path
Version:
Resourcesβ
The following resources are used by this module:
- aws_account_alternate_contact.ntc_factory_account (resource)
- aws_cloudwatch_event_rule.ntc_baseline_pipeline_schedule (resource)
- aws_cloudwatch_event_rule.ntc_baseline_pipeline_trigger (resource)
- aws_cloudwatch_event_rule.ntc_pipeline_notification (resource)
- aws_cloudwatch_event_rule.ntc_state_machine_notification (resource)
- aws_cloudwatch_event_rule.ntc_state_machine_trigger (resource)
- aws_cloudwatch_event_target.ntc_baseline_pipeline_schedule (resource)
- aws_cloudwatch_event_target.ntc_baseline_pipeline_trigger (resource)
- aws_cloudwatch_event_target.ntc_pipeline_notification (resource)
- aws_cloudwatch_event_target.ntc_state_machine_notification (resource)
- aws_cloudwatch_event_target.ntc_state_machine_trigger (resource)
- aws_codebuild_project.ntc_baseline_project (resource)
- aws_codepipeline.ntc_baseline_pipeline (resource)
- aws_dynamodb_table.ntc_account_baseline_delete_protection (resource)
- aws_iam_role.ntc_baseline_pipeline_event_rule_role (resource)
- aws_iam_role.ntc_baseline_pipeline_role (resource)
- aws_iam_role.ntc_lambda_execution_role (resource)
- aws_iam_role.ntc_org_member_role (resource)
- aws_iam_role.ntc_state_machine_event_rule_role (resource)
- aws_iam_role_policy.ntc_baseline_pipeline_event_rule_policy (resource)
- aws_iam_role_policy.ntc_baseline_pipeline_policy (resource)
- aws_iam_role_policy.ntc_lambda_policy (resource)
- aws_iam_role_policy.ntc_state_machine_event_rule_policy (resource)
- aws_iam_role_policy_attachment.ntc_org_member_role (resource)
- aws_kms_alias.ntc_account_factory_encryption (resource)
- aws_kms_key.ntc_account_factory_encryption (resource)
- aws_kms_key_policy.ntc_account_factory_encryption (resource)
- aws_lambda_invocation.ntc_user_defined_trigger_events (resource)
- aws_organizations_account.ntc_factory_account (resource)
- aws_s3_bucket_notification.ntc_baseline_pipeline_trigger (resource)
- aws_s3_object.ntc_account_baseline_zip (resource)
- aws_secretsmanager_secret.ntc_baseline_git_ssh_key (resource)
- aws_secretsmanager_secret.ntc_baseline_github_access_token (resource)
- aws_secretsmanager_secret.ntc_baseline_terraform_registry_token (resource)
- aws_secretsmanager_secret_version.ntc_baseline_git_ssh_key (resource)
- aws_secretsmanager_secret_version.ntc_baseline_github_access_token (resource)
- aws_secretsmanager_secret_version.ntc_baseline_terraform_registry_token (resource)
- aws_servicequotas_service_quota.ntc_servicequotas (resource)
- aws_sfn_state_machine.ntc_lifecycle_customization_state_machine (resource)
- aws_sns_topic.ntc_account_factory_notification (resource)
- aws_sns_topic_policy.ntc_account_factory_notification (resource)
- aws_sns_topic_subscription.ntc_account_factory_notification (resource)
- archive_file.ntc_account_baseline_zip (data source)
- aws_caller_identity.current (data source)
- aws_iam_policy_document.ntc_account_factory_encryption_policy (data source)
- aws_iam_policy_document.ntc_account_factory_notification (data source)
- aws_iam_policy_document.ntc_baseline_artifacts_bucket_policy (data source)
- aws_iam_policy_document.ntc_baseline_bucket_policy (data source)
- aws_iam_policy_document.ntc_baseline_pipeline_assume_role (data source)
- aws_iam_policy_document.ntc_baseline_pipeline_event_rule_assume_role (data source)
- aws_iam_policy_document.ntc_baseline_pipeline_event_rule_policy (data source)
- aws_iam_policy_document.ntc_baseline_pipeline_policy (data source)
- aws_iam_policy_document.ntc_baseline_secrets_manager (data source)
- aws_iam_policy_document.ntc_lambda_assume_role (data source)
- aws_iam_policy_document.ntc_lambda_policy (data source)
- aws_iam_policy_document.ntc_org_member_role (data source)
- aws_iam_policy_document.ntc_state_machine_event_rule_assume_role (data source)
- aws_iam_policy_document.ntc_state_machine_event_rule_policy (data source)
- aws_organizations_organization.org (data source)
- aws_partition.current (data source)
- aws_region.current (data source)
- aws_regions.available (data source)
- aws_servicequotas_service_quota.ntc_servicequotas (data source)
Required Inputsβ
The following input variables are required:
account_factory_baseline_bucket_nameβ
Description: The name for account factory S3 bucket which stores account baseline files.
Type: string
account_factory_cloudtrail_bucket_nameβ
Description: The name for NTC Account Factory cloudtrail logging bucket.
Type: string
Optional Inputsβ
The following input variables are optional (have default values):
account_baseline_git_ssh_keyβ
Description: SSH key for Git. Required if you want to reference Terraform modules in your account baseline which are hosted in Git (via SSH). Git must be reachable via Internet.
Type: string
Default: ""
account_baseline_git_ssh_key_secret_nameβ
Description: Name of the secrets manager secret where the 'account_baseline_git_ssh_key' will be stored so that the baseline pipeline can access it.
Type: string
Default: "git_ssh_key"
account_baseline_github_access_tokenβ
Description: Personal Access Token for Github. Required if you want to reference Terraform modules in your account baseline which are hosted in Github. Github must be reachable via Internet.
Type: string
Default: ""
account_baseline_github_access_token_secret_nameβ
Description: Name of the secrets manager secret where the 'account_baseline_github_access_token' will be stored so that the baseline pipeline can access it.
Type: string
Default: "github_access_token"
account_baseline_pipeline_event_rule_iam_role_nameβ
Description: The name of the IAM role that will be created for baseline pipeline triggers via cloudwatch event rules.
Type: string
Default: "ntc-af-pipeline-trigger-role"
account_baseline_pipeline_iam_role_nameβ
Description: The name of the IAM role that will be created for baseline pipelines.
Type: string
Default: "ntc-af-pipeline-role"
account_baseline_pipeline_logs_enabledβ
Description: Set to false to disable cloudwatch logs for account baseline pipelines.
Type: bool
Default: true
account_baseline_pipeline_name_prefixβ
Description: The prefix name for baseline pipelines.
Type: string
Default: "ntc-af"
account_baseline_pipeline_policy_nameβ
Description: The name for the baseline pipelines IAM policy.
Type: string
Default: "ntc-af-pipeline-policy"
account_baseline_scopesβ
Description: List of baseline scopes which define which member accounts will be baselined with a specific Terraform baseline configuration.
Type:
list(object({
scope_name = string
terraform_parallelism = optional(number, 10)
terraform_binary = optional(string, "terraform")
terraform_version = string
aws_provider_version = string
provider_default_tags = optional(map(string), { ManagedBy = "ntc-account-factory" })
pipeline_compute_type = optional(string, "BUILD_GENERAL1_SMALL")
pipeline_delay_options = optional(object({
wait_for_seconds = optional(number, 120)
wait_retry_count = optional(number, 5)
wait_for_execution_role = optional(bool, true)
wait_for_regions = optional(bool, true)
wait_for_securityhub = optional(bool, false)
wait_for_guardduty = optional(bool, false)
}), {})
schedule_rerun_every_x_hours = optional(number, 0)
baseline_execution_role_name = optional(string, "OrganizationAccountAccessRole")
baseline_execution_session_name = optional(string, "ntc-account-factory")
baseline_assume_role_providers = optional(list(object({
configuration_alias = string
role_arn = string
session_name = optional(string, "ntc-account-factory")
})), [])
baseline_terraform_files = list(object({
file_name = string
content = string
terraform_version_minimum = optional(string, "")
aws_provider_version_minimum = optional(string, "")
}))
baseline_regions = list(string)
baseline_main_region = string
include_accounts_all = optional(bool, false)
include_accounts_by_ou_paths = optional(list(string), [])
include_accounts_by_names = optional(list(string), [])
include_accounts_by_tags = optional(list(object({
key = string
value = string
})), [])
exclude_accounts_by_ou_paths = optional(list(string), [])
exclude_accounts_by_names = optional(list(string), [])
exclude_accounts_by_tags = optional(list(object({
key = string
value = string
})), [])
decommission_accounts_all = optional(bool, false)
decommission_accounts_by_ou_paths = optional(list(string), [])
decommission_accounts_by_names = optional(list(string), [])
decommission_accounts_by_tags = optional(list(object({
key = string
value = string
})), [])
}))
Default: []
account_baseline_terraform_registry_hostβ
Description: Name of Terraform Cloud or Enterprise host. Required if you want to reference Terraform modules in your account baseline from a Terraform Cloud or Enterprise private registry. Registry must be reachable via Internet.
Type: string
Default: "app.terraform.io"
account_baseline_terraform_registry_tokenβ
Description: Team- or User-Token for Terraform Cloud or Enterprise. Required if you want to reference Terraform modules in your account baseline from a Terraform Cloud or Enterprise private registry. Registry must be reachable via Internet.
Type: string
Default: ""
account_baseline_terraform_registry_token_secret_nameβ
Description: Name of the secrets manager secret where the 'account_baseline_terraform_registry_token' will be stored so that the baseline pipeline can access it.
Type: string
Default: "terraform_registry_token"
account_factory_baseline_artifacts_bucket_suffix_nameβ
Description: The name for account factory S3 bucket which stores codebuild artifacts.
Type: string
Default: "-artifacts"
account_factory_bucket_access_logging_target_bucket_nameβ
Description: Name of the bucket where S3 access logging should be stored. Requires "account_factory_bucket_enable_access_logging" to be true.
Type: string
Default: ""
account_factory_bucket_access_logging_target_prefixβ
Description: Prefix used for S3 access logging. Requires "account_factory_bucket_enable_access_logging" to be true.
Type: string
Default: "logs/"
account_factory_bucket_enable_access_loggingβ
Description: Set to true to log S3 access logging.
Type: bool
Default: false
account_factory_bucket_force_destroyβ
Description: Set to true if you want to allow the account factory s3 bucket to be force destroyed. WARNING: This is intended for automated testing and should otherwise stay false.
Type: bool
Default: false