├── .ansible-lint
├── .ansible-lint-ignore
├── .docker
├── forge-github-app-register
│ ├── .dockerignore
│ ├── Dockerfile
│ ├── app.py
│ ├── deploy
│ │ └── github-app
│ │ │ ├── app-manifest.json
│ │ │ └── register.html
│ └── requirements.txt
└── pre-commit
│ └── Dockerfile
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE
│ └── default_pr.md
└── workflows
│ ├── build-forge-github-app-register.yml
│ ├── build-pre-commit.yml
│ └── pre-commit.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .terraform-docs.yml
├── .yamllint
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── docs
├── configurations
│ ├── build
│ │ └── gh_base_image.md
│ ├── dependency.md
│ ├── deployments
│ │ ├── forge_eks.md
│ │ ├── forge_extras.md
│ │ ├── forge_integrations.md
│ │ ├── forge_tenant.md
│ │ ├── index.md
│ │ ├── new_tenant.md
│ │ └── splunk_deployment.md
│ ├── index.md
│ └── secrets.md
├── img
│ └── forge_architecture.jpg
├── index.md
└── tenant-usage
│ ├── dependency-management.md
│ ├── index.md
│ └── renovatebot
│ ├── index.md
│ └── strategy.md
├── examples
├── build
│ ├── ansible
│ │ ├── build_gh_base_image.yaml
│ │ ├── group_vars
│ │ │ └── all
│ │ │ │ └── common.yaml
│ │ ├── requirements.yml
│ │ └── roles
│ │ │ ├── deps
│ │ │ └── tasks
│ │ │ │ ├── apt.yml
│ │ │ │ ├── clean.yml
│ │ │ │ ├── cli-tools.yml
│ │ │ │ ├── docker.yml
│ │ │ │ ├── gh.yml
│ │ │ │ └── main.yml
│ │ │ ├── splunk_otel_collector
│ │ │ └── tasks
│ │ │ │ └── main.yml
│ │ │ └── teleport
│ │ │ ├── files
│ │ │ ├── start-teleport.sh
│ │ │ └── teleport.service
│ │ │ ├── tasks
│ │ │ └── main.yml
│ │ │ └── templates
│ │ │ └── teleport.yaml.j2
│ └── packer
│ │ └── gha-runner.pkr.hcl
├── deployments
│ ├── forge-eks
│ │ ├── release_versions.yaml
│ │ └── terragrunt
│ │ │ ├── _global_settings
│ │ │ ├── _global.hcl
│ │ │ ├── _global.yaml
│ │ │ ├── eks.hcl
│ │ │ └── terragrunt.hcl
│ │ │ ├── environments
│ │ │ ├── prod
│ │ │ │ ├── _environment_wide_settings
│ │ │ │ │ ├── _environment.hcl
│ │ │ │ │ ├── _environment.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ └── regions
│ │ │ │ │ └── eu-west-1
│ │ │ │ │ ├── _region_wide_settings
│ │ │ │ │ ├── _region.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ └── eks
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ ├── config.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ ├── safety_hook.sh
│ │ │ └── terragrunt.hcl
│ │ │ ├── root.hcl
│ │ │ └── terragrunt.hcl
│ ├── forge-extras
│ │ ├── release_versions.yaml
│ │ └── terragrunt
│ │ │ ├── _global_settings
│ │ │ ├── _global.hcl
│ │ │ ├── _global.yaml
│ │ │ ├── cloud_custodian.hcl
│ │ │ ├── cloud_formation.hcl
│ │ │ ├── ecr.hcl
│ │ │ ├── forge_subscription.hcl
│ │ │ ├── storage.hcl
│ │ │ └── terragrunt.hcl
│ │ │ ├── environments
│ │ │ ├── prod
│ │ │ │ ├── _environment_wide_settings
│ │ │ │ │ ├── _environment.hcl
│ │ │ │ │ ├── _environment.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ ├── cloud_custodian
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ ├── config.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ ├── cloud_formation
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ ├── forge_subscription
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ ├── config.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ ├── regions
│ │ │ │ │ └── eu-west-1
│ │ │ │ │ │ ├── _region_wide_settings
│ │ │ │ │ │ ├── _region.hcl
│ │ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ │ └── ecr
│ │ │ │ │ │ ├── config.hcl
│ │ │ │ │ │ ├── config.yaml
│ │ │ │ │ │ └── terragrunt.hcl
│ │ │ │ └── storage
│ │ │ │ │ └── terragrunt.hcl
│ │ │ ├── safety_hook.sh
│ │ │ └── terragrunt.hcl
│ │ │ ├── root.hcl
│ │ │ └── terragrunt.hcl
│ ├── forge-integrations
│ │ ├── release_versions.yaml
│ │ └── terragrunt
│ │ │ ├── _global_settings
│ │ │ ├── _global.hcl
│ │ │ ├── splunk_cloud_conf.hcl
│ │ │ ├── splunk_cloud_forgecicd.hcl
│ │ │ └── terragrunt.hcl
│ │ │ ├── environments
│ │ │ ├── prod
│ │ │ │ ├── _environment_wide_settings
│ │ │ │ │ ├── _environment.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ ├── regions
│ │ │ │ │ └── eu-west-1
│ │ │ │ │ │ ├── _region_wide_settings
│ │ │ │ │ │ ├── _region.hcl
│ │ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ │ └── vpcs
│ │ │ │ │ │ └── sl
│ │ │ │ │ │ └── _vpc_wide_settings
│ │ │ │ │ │ ├── _vpc.hcl
│ │ │ │ │ │ └── terragrunt.hcl
│ │ │ │ ├── splunk_cloud_conf
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ └── splunk_cloud_forgecicd
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ └── safety_hook.sh
│ │ │ ├── root.hcl
│ │ │ └── terragrunt.hcl
│ ├── forge-tenant
│ │ ├── release_versions.yaml
│ │ └── terragrunt
│ │ │ ├── _global_settings
│ │ │ ├── _global.hcl
│ │ │ ├── _global.yaml
│ │ │ ├── tenants
│ │ │ │ ├── acme.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ └── terragrunt.hcl
│ │ │ ├── environments
│ │ │ ├── prod
│ │ │ │ ├── _environment_wide_settings
│ │ │ │ │ ├── _environment.hcl
│ │ │ │ │ ├── _environment.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ └── regions
│ │ │ │ │ └── eu-west-1
│ │ │ │ │ ├── _region_wide_settings
│ │ │ │ │ ├── _region.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ └── vpcs
│ │ │ │ │ └── sl
│ │ │ │ │ ├── _vpc_wide_settings
│ │ │ │ │ ├── _vpc.hcl
│ │ │ │ │ ├── _vpc.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ └── tenants
│ │ │ │ │ └── acme
│ │ │ │ │ ├── config.yaml
│ │ │ │ │ ├── runner_settings.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ ├── safety_hook.sh
│ │ │ └── terragrunt.hcl
│ │ │ ├── root.hcl
│ │ │ └── terragrunt.hcl
│ └── splunk-deployment
│ │ ├── release_versions.yaml
│ │ └── terragrunt
│ │ ├── _global_settings
│ │ ├── _global.hcl
│ │ ├── _global.yaml
│ │ ├── splunk_cloud_data_manager.hcl
│ │ ├── splunk_cloud_data_manager_common.hcl
│ │ ├── splunk_o11y_aws_integration.hcl
│ │ ├── splunk_o11y_aws_integration_common.hcl
│ │ ├── splunk_otel_eks.hcl
│ │ ├── splunk_secrets.hcl
│ │ └── terragrunt.hcl
│ │ ├── environments
│ │ ├── prod
│ │ │ ├── _environment_wide_settings
│ │ │ │ ├── _environment.hcl
│ │ │ │ ├── _environment.yaml
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── regions
│ │ │ │ └── eu-west-1
│ │ │ │ │ ├── _region_wide_settings
│ │ │ │ │ ├── _region.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ ├── splunk_o11y_aws_integration
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ ├── config.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ └── splunk_otel_eks
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ ├── config.yaml
│ │ │ │ │ └── terragrunt.hcl
│ │ │ ├── splunk_cloud_data_manager
│ │ │ │ ├── config.hcl
│ │ │ │ ├── config.yaml
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── splunk_cloud_data_manager_common
│ │ │ │ ├── config.hcl
│ │ │ │ ├── config.yaml
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── splunk_o11y_aws_integration_common
│ │ │ │ ├── config.hcl
│ │ │ │ ├── config.yaml
│ │ │ │ └── terragrunt.hcl
│ │ │ └── splunk_secrets
│ │ │ │ ├── config.hcl
│ │ │ │ ├── config.yaml
│ │ │ │ └── terragrunt.hcl
│ │ ├── safety_hook.sh
│ │ └── terragrunt.hcl
│ │ ├── root.hcl
│ │ └── terragrunt.hcl
├── infra-forge
│ ├── index.md
│ ├── release_versions.yaml
│ └── terragrunt
│ │ ├── _global_settings
│ │ ├── _global.hcl
│ │ ├── ami.hcl
│ │ ├── ami_sharing.hcl
│ │ ├── billing.hcl
│ │ ├── budget.hcl
│ │ ├── cloud_custodian.hcl
│ │ ├── cloudformation.hcl
│ │ ├── ecr.hcl
│ │ ├── eks.hcl
│ │ ├── forge_subscription.hcl
│ │ ├── opt_in_regions.hcl
│ │ ├── secrets.hcl
│ │ ├── service_linked_roles.hcl
│ │ ├── splunk_cloud_data_manager.hcl
│ │ ├── splunk_cloud_data_manager_deps.hcl
│ │ ├── splunk_o11y_integration.hcl
│ │ ├── splunk_o11y_regional_integration.hcl
│ │ ├── storage.hcl
│ │ └── terragrunt.hcl
│ │ ├── environments
│ │ ├── dev
│ │ │ ├── _environment_wide_settings
│ │ │ │ ├── _environment.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── ami
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── budget
│ │ │ │ ├── config.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── cloud_custodian
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── cloudformation
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── forge_subscription
│ │ │ │ ├── subscription_settings.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── opt_in_regions
│ │ │ │ ├── config.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── regions
│ │ │ │ └── eu-west-1
│ │ │ │ │ ├── _region_wide_settings
│ │ │ │ │ ├── _region.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ ├── ami_sharing
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ ├── billing
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ ├── ecr
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ ├── eks
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ ├── secrets
│ │ │ │ │ └── terragrunt.hcl
│ │ │ │ │ └── splunk_o11y_regional_integration
│ │ │ │ │ ├── config.hcl
│ │ │ │ │ └── terragrunt.hcl
│ │ │ ├── service_linked_roles
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── splunk_cloud_data_manager
│ │ │ │ ├── config.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── splunk_cloud_data_manager_deps
│ │ │ │ ├── config.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ ├── splunk_o11y_integration
│ │ │ │ ├── config.hcl
│ │ │ │ └── terragrunt.hcl
│ │ │ └── storage
│ │ │ │ └── terragrunt.hcl
│ │ ├── safety_hook.sh
│ │ └── terragrunt.hcl
│ │ ├── root.hcl
│ │ └── terragrunt.hcl
└── templates
│ ├── eks
│ ├── _environment_wide_settings
│ │ └── _environment.yaml
│ ├── _global_settings
│ │ └── _global.yaml
│ └── eks
│ │ └── config.yaml
│ ├── extras
│ ├── _environment_wide_settings
│ │ └── _environment.yaml
│ ├── _global_settings
│ │ └── _global.yaml
│ ├── cloud_custodian
│ │ └── config.yaml
│ ├── ecr
│ │ └── config.yaml
│ └── forge_subscription
│ │ └── config.yaml
│ ├── splunk
│ ├── _environment_wide_settings
│ │ └── _environment.yaml
│ ├── _global_settings
│ │ └── _global.yaml
│ ├── splunk_cloud_data_manager
│ │ └── config.yaml
│ ├── splunk_cloud_data_manager_common
│ │ └── config.yaml
│ ├── splunk_o11y_aws_integration
│ │ └── config.yaml
│ ├── splunk_o11y_aws_integration_common
│ │ └── config.yaml
│ ├── splunk_otel_eks
│ │ └── config.yaml
│ └── splunk_secrets
│ │ └── config.yaml
│ └── tenant
│ ├── _environment_wide_settings
│ └── _environment.yaml
│ ├── _global_settings
│ ├── _global.yaml
│ └── tenant.hcl
│ ├── _vpc_wide_settings
│ └── _vpc.yaml
│ └── tenant
│ ├── config.yaml
│ ├── runner_settings.hcl
│ └── terragrunt.hcl
├── modules
├── core
│ └── arc
│ │ ├── README.md
│ │ ├── data.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── scale_set
│ │ ├── README.md
│ │ ├── helm.tf
│ │ ├── locals.tf
│ │ ├── outputs.tf
│ │ ├── role.tf
│ │ ├── template_files
│ │ │ ├── dind.yml.tftpl
│ │ │ ├── hook_job_completed.tftpl
│ │ │ ├── hook_job_started.tftpl
│ │ │ └── k8s.yml.tftpl
│ │ ├── variables.tf
│ │ └── versions.tf
│ │ ├── scale_set_controller
│ │ ├── README.md
│ │ ├── helm.tf
│ │ ├── secret.tf
│ │ ├── template_files
│ │ │ └── values.yml.tftpl
│ │ ├── variables.tf
│ │ └── versions.tf
│ │ ├── variables.tf
│ │ └── versions.tf
├── infra
│ ├── ami_policy
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── global_policy.tf
│ │ ├── outputs.tf
│ │ ├── policies.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── ami_sharing
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── billing
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── budget
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── cloud_custodian
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── cloud_formation
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── ecr
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── eks
│ │ ├── README.md
│ │ ├── addons.tf
│ │ ├── backend.tf
│ │ ├── calico.tf
│ │ ├── data.tf
│ │ ├── eks.tf
│ │ ├── karpenter.tf
│ │ ├── nodes.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── templates
│ │ │ ├── ec2_node_class.yaml.tpl
│ │ │ └── node_pool.yaml.tpl
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── forge_subscription
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── ecr.tf
│ │ ├── outputs.tf
│ │ ├── policies.tf
│ │ ├── providers.tf
│ │ ├── roles.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── version.tf
│ ├── opt_in_regions
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── service_linked_roles
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ └── storage
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
├── integrations
│ ├── splunk_cloud_conf_shared
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── dashboard_jobs.tf
│ │ ├── dashboard_tenant.tf
│ │ ├── props_ec2.tf
│ │ ├── props_k8s.tf
│ │ ├── providers.tf
│ │ ├── secrets.tf
│ │ ├── template_files
│ │ │ ├── ci_jobs.json.tftpl
│ │ │ └── tenant.json.tftpl
│ │ ├── transforms_ec2.tf
│ │ ├── transforms_k8s.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── splunk_cloud_data_manager
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── cloudwatch.tf
│ │ ├── custom_cloudwatch.tf
│ │ ├── data_input
│ │ │ ├── README.md
│ │ │ ├── locals.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── s3_template.tf
│ │ │ ├── scripts
│ │ │ │ ├── create_splunk_integration.sh
│ │ │ │ ├── delete_splunk_integration.sh
│ │ │ │ └── get_splunk_integration.sh
│ │ │ ├── secrets.tf
│ │ │ ├── variables.tf
│ │ │ └── versions.tf
│ │ ├── locals.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── sec_meta.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── splunk_cloud_data_manager_common
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── providers.tf
│ │ ├── role.tf
│ │ ├── secrets.tf
│ │ ├── splunk.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── splunk_o11y_aws_integration
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── cf.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── secrets.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── splunk_o11y_aws_integration_common
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── role.tf
│ │ ├── secrets.tf
│ │ ├── signalfx.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── splunk_otel_eks
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── data.tf
│ │ ├── otel.tf
│ │ ├── providers.tf
│ │ ├── secrets.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── splunk_secrets
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── tags.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ └── teleport
│ │ ├── README.md
│ │ ├── backend.tf
│ │ ├── data.tf
│ │ ├── main.tf
│ │ ├── providers.tf
│ │ ├── tenant
│ │ ├── README.md
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ │ ├── variables.tf
│ │ └── versions.tf
└── platform
│ ├── arc_deployment
│ ├── README.md
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
│ ├── ec2_deployment
│ ├── README.md
│ ├── ami.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── scripts
│ │ └── download_lambdas.sh
│ ├── security_group.tf
│ ├── template_files
│ │ ├── hook_job_completed.tftpl
│ │ ├── hook_job_started.tftpl
│ │ ├── post_install.tftpl
│ │ └── user_data.tftpl
│ ├── variables.tf
│ └── versions.tf
│ └── forge_runners
│ ├── README.md
│ ├── arc_runners.tf
│ ├── backend.tf
│ ├── budget.tf
│ ├── ec2_runners.tf
│ ├── global_lock.tf
│ ├── lambda
│ ├── github_app_runner_group.py
│ ├── github_clean_global_lock.py
│ └── requirements.txt
│ ├── locals.tf
│ ├── outputs.tf
│ ├── providers.tf
│ ├── register_repo_runner_group.tf
│ ├── roles.tf
│ ├── scripts
│ ├── generate_and_patch_github_app.sh
│ ├── requirements_clean_global_lock.sh
│ └── requirements_runner_group.sh
│ ├── secrets.tf
│ ├── tags.tf
│ ├── update_gh_app.tf
│ ├── variables.tf
│ └── versions.tf
└── scripts
├── update-github-app-secrets.sh
└── update-terraform-docs.sh
/.ansible-lint:
--------------------------------------------------------------------------------
1 | ---
2 | exclude_paths:
3 | - .cache/
4 | - .github/
5 | - .terraform/
6 |
--------------------------------------------------------------------------------
/.ansible-lint-ignore:
--------------------------------------------------------------------------------
1 | examples/build/ansible/roles/deps/tasks/apt.yml no-changed-when
2 | examples/build/ansible/roles/deps/tasks/apt.yml ignore-errors
3 | examples/build/ansible/roles/deps/tasks/apt.yml risky-file-permissions
4 | examples/build/ansible/roles/deps/tasks/apt.yml package-latest
5 | examples/build/ansible/roles/deps/tasks/cli-tools.yml risky-shell-pipe
6 | examples/build/ansible/roles/deps/tasks/cli-tools.yml no-handler
7 | examples/build/ansible/roles/deps/tasks/docker.yml no-changed-when
8 | examples/build/ansible/roles/deps/tasks/docker.yml risky-shell-pipe
9 | examples/build/ansible/roles/deps/tasks/docker.yml command-instead-of-module
10 | examples/build/ansible/roles/teleport/tasks/main.yml command-instead-of-module
11 | examples/build/ansible/roles/teleport/tasks/main.yml no-changed-when
12 | examples/build/ansible/roles/teleport/tasks/main.yml risky-shell-pipe
13 | examples/build/ansible/roles/teleport/tasks/main.yml risky-file-permissions
14 | examples/build/ansible/roles/teleport/tasks/main.yml risky-file-permissions
15 |
--------------------------------------------------------------------------------
/.docker/forge-github-app-register/.dockerignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | *.pyc
3 | *.pyo
4 | *.pyd
5 | .env
6 | .git
7 |
--------------------------------------------------------------------------------
/.docker/forge-github-app-register/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.11-slim
2 |
3 | RUN useradd --create-home appuser
4 | WORKDIR /home/appuser
5 |
6 | COPY requirements.txt .
7 | RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | COPY --chown=appuser:appuser deploy deploy
10 | COPY --chown=appuser:appuser app.py .
11 |
12 | USER appuser
13 |
14 | ENV HOST=0.0.0.0
15 | ENV PORT=5000
16 | EXPOSE 5000
17 | CMD ["python", "app.py"]
18 |
--------------------------------------------------------------------------------
/.docker/forge-github-app-register/deploy/github-app/app-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ForgeRunnerFactory",
3 | "description": "Registers and manages ephemeral GitHub Actions runners for your Forge instance.",
4 | "url": "https://cisco-open.github.io/forge",
5 | "hook_attributes": {
6 | "url": "https://cisco-open.github.io/forge"
7 | },
8 | "redirect_url": "http://localhost:5000/oauth/callback",
9 | "callback_urls": [],
10 | "public": false,
11 | "default_permissions": {
12 | "actions": "read",
13 | "checks": "read",
14 | "metadata": "read",
15 | "organization_self_hosted_runners": "write",
16 | "organization_administration": "write"
17 | },
18 | "default_events": [
19 | "workflow_job"
20 | ],
21 | "request_oauth_on_install": false,
22 | "setup_on_update": false
23 | }
24 |
--------------------------------------------------------------------------------
/.docker/forge-github-app-register/deploy/github-app/register.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Register Forge Runner Factory App
6 |
7 |
8 | 🔧 Register the Forge Runner Factory App
9 |
13 |
14 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.docker/forge-github-app-register/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask>=2.0
2 | requests>=2.25
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 | ---
8 | **Describe the bug**
9 | A clear and concise description of what the bug is.
10 |
11 | **Version**
12 | The version of Forge, Terraform (or OpenTofu), terraform-aws-github-runner module, and any relevant Terraform Providers (e.g., AWS, Splunk, Kubernetes, Helm, SignalFx) in which the bug occurs.
13 |
14 |
15 | **To reproduce**
16 | Steps to reproduce the behavior.
17 |
18 | **Expected behavior**
19 | A clear and concise description of what you expected to happen.
20 |
21 | **Additional context**
22 | Add any other context about the problem here.
23 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 | ---
8 | **Is your feature request related to a problem? Please describe.**
9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
10 |
11 | **Describe the solution you'd like**
12 | A clear and concise description of what you want to happen.
13 |
14 | **Describe alternatives you've considered**
15 | A clear and concise description of any alternative solutions or features you've considered.
16 |
17 | **Additional context**
18 | Add any other context or screenshots about the feature request here.
19 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/default_pr.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Please provide a meaningful description of what this change will do, or is for. Bonus points for including links to
4 | related issues, other PRs, or technical references.
5 |
6 | Note that by _not_ including a description, you are asking reviewers to do extra work to understand the context of this
7 | change, which may lead to your PR taking much longer to review, or result in it not being reviewed at all.
8 |
9 | ## Type of Change
10 |
11 | - [ ] Bug Fix
12 | - [ ] New Feature
13 | - [ ] Breaking Change
14 | - [ ] Refactor
15 | - [ ] Documentation
16 | - [ ] Other
17 |
18 | ## Checklist
19 |
20 |
21 | - [ ] I have read the [contributing guidelines](/CONTRIBUTING.md)
22 | - [ ] Existing issues have been referenced (where applicable)
23 | - [ ] I have verified this change is not present in other open pull requests
24 | - [ ] Functionality is documented
25 | - [ ] All code style checks pass
26 | - [ ] New code contribution is covered by automated tests
27 | - [ ] All new and existing tests pass
28 |
--------------------------------------------------------------------------------
/.github/workflows/pre-commit.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:comments
3 | # yamllint disable rule:truthy
4 | name: Pre-commit Code Quality Checks
5 |
6 | on:
7 | pull_request:
8 | types:
9 | - opened
10 | - synchronize
11 | - reopened
12 | branches:
13 | - main
14 | push:
15 | branches:
16 | - main
17 |
18 | permissions:
19 | contents: read
20 |
21 | jobs:
22 | run-pre-commit:
23 | runs-on: ubuntu-latest
24 | timeout-minutes: 60
25 | container:
26 | image: ghcr.io/${{ github.repository }}-pre-commit:main
27 |
28 | steps:
29 | - name: Checkout Repository
30 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
31 |
32 | - name: Cache Pre-commit
33 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
34 | with:
35 | path: ~/.cache/pre-commit/
36 | key: pre-commit|${{ github.repository }}|${{ hashFiles('.pre-commit-config.yaml') }}
37 |
38 | - name: Mark repository as safe
39 | shell: bash
40 | run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
41 |
42 | - name: Run pre-commit in all files
43 | shell: bash
44 | run: pre-commit run --show-diff-on-failure --color=always --all-files | tee pre-commit.log
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .bash_history
3 |
4 | # Ignore Terraform state files
5 | *.tfstate
6 | *.tfstate.backup
7 | *.tfstate.backup.*
8 |
9 | # Ignore override files
10 | override.tf
11 | override.tf.json
12 | *_override.tf
13 | *_override.tf.json
14 |
15 | # Ignore Terraform plan files
16 | *.tfplan
17 |
18 | # Ignore .terraform directory
19 | .terraform/
20 |
21 | # Ignore Terraform state and lock files
22 | *.tflock
23 | .terraform.lock.hcl
24 | .terragrunt-cache
25 | providers
26 |
27 | # Auth files. Sensitive.
28 | .auth/
29 |
30 | artifacts
31 |
32 | package
33 |
--------------------------------------------------------------------------------
/.terraform-docs.yml:
--------------------------------------------------------------------------------
1 | ---
2 | formatter: markdown # this is required
3 |
4 | version: ''
5 |
6 | header-from: main.tf
7 | footer-from: ''
8 |
9 | recursive:
10 | enabled: false
11 |
12 | sections:
13 | hide: []
14 | show: []
15 |
16 | content: ''
17 |
18 | output:
19 | file: README.md
20 | mode: inject
21 | template: |-
22 |
23 | {{ .Content }}
24 |
25 |
26 | output-values:
27 | enabled: false
28 | from: ''
29 |
30 | sort:
31 | enabled: true
32 | by: name
33 |
34 | settings:
35 | anchor: true
36 | color: true
37 | default: true
38 | description: false
39 | escape: true
40 | hide-empty: false
41 | html: true
42 | indent: 2
43 | lockfile: true
44 | read-comments: true
45 | required: true
46 | sensitive: true
47 | type: true
48 |
--------------------------------------------------------------------------------
/.yamllint:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | # Specify the files to lint
4 | yaml-files:
5 | - '*.yaml'
6 | - '*.yml'
7 | - .yamllint
8 |
9 | # Define the linting rules
10 | rules:
11 | braces: enable
12 | brackets: enable
13 | colons: enable
14 | commas: enable
15 | comments:
16 | level: error
17 | comments-indentation:
18 | level: error
19 | document-end: disable
20 | document-start:
21 | present: true # Ensure that documents start with '---'
22 | level: error # Set the level to error
23 | empty-lines: enable
24 | empty-values: disable
25 | hyphens: enable
26 | indentation:
27 | spaces: 2 # Use 2 spaces for indentation
28 | level: error # Set the level to error
29 | indent-sequences: true
30 | check-multi-line-strings: false
31 | key-duplicates: enable
32 | key-ordering: disable
33 | # Unavoidable due to long queries.
34 | line-length: disable
35 | new-line-at-end-of-file: enable
36 | new-lines: enable
37 | octal-values: disable
38 | quoted-strings: disable
39 | trailing-spaces:
40 | level: error # Warn about trailing spaces
41 | truthy:
42 | level: error
43 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policies and Procedures
2 |
3 | This document outlines security procedures and general policies for the
4 | `Forge` project.
5 |
6 | - [Security Policies and Procedures](#security-policies-and-procedures)
7 | - [Reporting a Bug](#reporting-a-bug)
8 | - [Disclosure Policy](#disclosure-policy)
9 | - [Comments on this Policy](#comments-on-this-policy)
10 |
11 | ## Reporting a Bug
12 |
13 | The `Forge` team and community take all security bugs in
14 | `Forge` seriously. Thank you for improving the security of
15 | `Forge`. We appreciate your efforts and responsible disclosure and
16 | will make every effort to acknowledge your contributions.
17 |
18 | Report security bugs by emailing `oss-security@cisco.com`.
19 |
20 | The lead maintainer will acknowledge your email within 48 hours, and will send a
21 | more detailed response within 48 hours indicating the next steps in handling
22 | your report. After the initial reply to your report, the security team will
23 | endeavor to keep you informed of the progress towards a fix and full
24 | announcement, and may ask for additional information or guidance.
25 |
26 | ## Disclosure Policy
27 |
28 | When the security team receives a security bug report, they will assign it to a
29 | primary handler. This person will coordinate the fix and release process,
30 | involving the following steps:
31 |
32 | - Confirm the problem and determine the affected versions.
33 | - Audit code to find any potential similar problems.
34 | - Prepare fixes for all releases still under maintenance. These fixes will be
35 | released as quickly as possible.
36 |
37 | ## Comments on this Policy
38 |
39 | If you have suggestions on how this process could be improved please submit a
40 | pull request.
41 |
--------------------------------------------------------------------------------
/docs/configurations/deployments/index.md:
--------------------------------------------------------------------------------
1 | # Forge Deployment Scenarios
2 |
3 | - [**First Tenant**](./forge_tenant.md)
4 | *Minimal multi-tenant Forge deployment example. Shows how to provision Forge runners and onboard your first tenant.*
5 |
6 | - [**New Tenant Guide**](./new_tenant.md)
7 | *Step-by-step checklist for adding a new tenant to an existing Forge deployment, including config files, secrets, and GitHub App setup.*
8 |
9 | - [**Forge EKS**](./forge_eks.md)
10 | *Deploys an EKS cluster with Calico and Karpenter, suitable for running Forge ARC runners and other workloads.*
11 |
12 | - [**Forge Integrations**](./forge_integrations.md)
13 | *Example for deploying Forge with Splunk, Observability, and other integrations. Includes required modules and configuration tips.*
14 |
15 | - [**Splunk Deployment**](./splunk_deployment.md)
16 | *Complete example for deploying Splunk integrations, including secrets, data manager, and observability modules.*
17 |
18 | - [**Extras Deployments**](./forge_extras.md)
19 | *Deploys supporting infrastructure such as Cloud Custodian, CloudFormation permissions, ECR repositories, Forge subscription, and S3 storage.*
20 |
--------------------------------------------------------------------------------
/docs/img/forge_architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/docs/img/forge_architecture.jpg
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Welcome to Forge Documentation
2 |
3 | Forge is a platform for secure, ephemeral GitHub Actions runners on AWS with multi-tenant isolation.
4 |
5 | ## 🚀 Quick Start
6 | - [Deploy Your First Tenant](./configurations/deployments/forge_tenant.md)
7 | - [Add a New Tenant](./configurations/deployments/new_tenant.md)
8 | - [All Deployment Scenarios](./configurations/deployments/index.md)
9 |
10 | ## 📚 Documentation Index
11 | - [Configuration Reference](./configurations/index.md)
12 | - [Tenant Usage Guide](tenant-usage/index.md)
13 | - [Secrets Reference](./configurations/secrets.md)
14 | - [Module Dependency Guide](./configurations/dependency.md)
15 |
--------------------------------------------------------------------------------
/examples/build/ansible/build_gh_base_image.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Build GH Runner
3 | hosts: all
4 | gather_facts: true
5 | become: true
6 | pre_tasks:
7 |
8 | - name: Wait for cloud-init to complete.
9 | ansible.builtin.command: /usr/bin/cloud-init status --wait
10 | changed_when: false
11 |
12 | - name: Wait for any ongoing apt installations to conclude.
13 | ansible.builtin.command: systemd-run --property="After=apt-daily.service apt-daily-upgrade.service" --wait /bin/true
14 | changed_when: false
15 |
16 | roles:
17 | - role: deps
18 | # - role: teleport # Uncomment if you want to install Teleport
19 | # - role: splunk_otel_collector # Uncomment if you want to install Splunk OpenTelemetry Collector
20 |
--------------------------------------------------------------------------------
/examples/build/ansible/group_vars/all/common.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | username: ubuntu
3 | # renovate: datasource=github-releases depName=actions/runner registryUrl=https://github.com/
4 | github_runner_version: 2.323.0
5 | runner_tarball: "https://github.com/actions/runner/releases/download/v{{ github_runner_version }}/actions-runner-linux-x64-{{ github_runner_version }}.tar.gz"
6 |
7 | # renovate: datasource=github-tags depName=aws/aws-cli registryUrl=https://github.com/
8 | aws_cli_version: 2.26.7
9 | aws_cli_checksum: bb1fcbbdaffc006dce62827083605b9953d23a1b42b3a7375733d9a6d7c94b8d
10 |
11 | # renovate: datasource=github-tags depName=github-aws-runners/terraform-aws-github-runner registryUrl=https://github.com/
12 | tf_aws_github_runner_version: 6.5.5
13 | install_runner_shell: https://raw.githubusercontent.com/github-aws-runners/terraform-aws-github-runner/v{{ tf_aws_github_runner_version }}/modules/runners/templates/install-runner.sh
14 |
15 | teleport_comm_ca_pin: # e.g. sha256:3c2f8b1d4e5f7c6a9b0c8d9e1f2a3b4c5d6e7f8g9h0i1j2k3l4m5n6o7p8q9r0
16 | teleport_comm_auth_server: # e.g. teleport.example.com:443
17 |
--------------------------------------------------------------------------------
/examples/build/ansible/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: amazon.aws
4 | version: 9.4.0
5 | - name: signalfx.splunk_otel_collector
6 | version: 0.31.0
7 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/deps/tasks/clean.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Remove useless packages from the cache
3 | ansible.builtin.apt:
4 | autoclean: true
5 |
6 | - name: Remove dependencies that are no longer required
7 | ansible.builtin.apt:
8 | autoremove: true
9 |
10 | - name: Clean the local package cache (apt clean)
11 | ansible.builtin.shell: apt clean -y
12 | args:
13 | executable: /bin/bash
14 | changed_when: false
15 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/deps/tasks/docker.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install key and repo support for Docker CE and Build-X plugin.
3 | args:
4 | executable: /bin/bash
5 | ansible.builtin.shell: |
6 | sudo install -m 0755 -d /etc/apt/keyrings
7 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
8 | sudo chmod a+r /etc/apt/keyrings/docker.gpg
9 | echo \
10 | "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
11 | "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
12 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
13 |
14 | - name: Install Docker Build-X, CE, and other components.
15 | ansible.builtin.apt:
16 | update_cache: true
17 | pkg:
18 | - containerd.io
19 | - docker-ce
20 | - docker-ce-cli
21 | - docker-buildx-plugin
22 | - docker-compose-plugin
23 |
24 | - name: Disable global Docker services. We'll create a non-root equivalent in userdata.
25 | args:
26 | executable: /bin/bash
27 | ansible.builtin.shell: |
28 | systemctl is-enabled docker.service && systemctl disable --now docker.service docker.socket || echo "already disabled"
29 | register: docker_disable
30 | changed_when: "'disabled' in docker_disable.stdout or docker_disable.rc == 0"
31 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/deps/tasks/gh.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Create /opt.
3 | ansible.builtin.file:
4 | path: /opt
5 | state: directory
6 | mode: '0755'
7 | recurse: true
8 |
9 | - name: Create /opt/scripts.
10 | ansible.builtin.file:
11 | path: /opt/scripts
12 | state: directory
13 | mode: '0755'
14 | recurse: true
15 |
16 | - name: Download install_gha_runner.sh from GitHub
17 | ansible.builtin.get_url:
18 | url: "{{ install_runner_shell }}"
19 | dest: /opt/scripts/install_gha_runner.sh
20 | mode: '0755'
21 | force: true
22 |
23 | - name: Install GitHub Actions runner package (via scripts we just deployed).
24 | args:
25 | executable: /bin/bash
26 | ansible.builtin.shell: |
27 | USERNAME={{ username }} RUNNER_TARBALL_URL={{ runner_tarball }} /opt/scripts/install_gha_runner.sh
28 | register: gha_install
29 | changed_when: "'installed successfully' in gha_install.stdout or 'already installed' not in gha_install.stdout"
30 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/deps/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Update and install APT packages
3 | ansible.builtin.import_tasks: ./apt.yml
4 |
5 | - name: Install Docker
6 | ansible.builtin.import_tasks: ./docker.yml
7 |
8 | - name: Install GitHub CLI
9 | ansible.builtin.import_tasks: ./gh.yml
10 |
11 | - name: Install CLI tools
12 | ansible.builtin.import_tasks: ./cli-tools.yml
13 |
14 | - name: Clean up
15 | ansible.builtin.import_tasks: ./clean.yml
16 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/splunk_otel_collector/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Set splunk_skip_repo
4 | ansible.builtin.set_fact:
5 | splunk_skip_repo: true
6 |
7 | - name: Download Splunk GPG key
8 | ansible.builtin.get_url:
9 | url: https://splunk.jfrog.io/splunk/otel-collector-deb/splunk-B3CD4420.gpg
10 | dest: /etc/apt/keyrings/splunk.gpg
11 | mode: '0644'
12 |
13 | - name: Add Splunk OpenTelemetry Collector repo to apt source list
14 | ansible.builtin.apt_repository:
15 | repo: "deb [signed-by=/etc/apt/keyrings/splunk.gpg] https://splunk.jfrog.io/splunk/otel-collector-deb release main"
16 | filename: splunk-otel-collector.list
17 | state: present
18 | validate_certs: false
19 |
20 | - name: "Include splunk_otel_collector"
21 | ansible.builtin.include_role:
22 | name: "signalfx.splunk_otel_collector.collector"
23 | vars:
24 | splunk_access_token: "{{ lookup('env', 'SPLUNK_ACCESS_TOKEN') }}"
25 | splunk_realm: "{{ lookup('env', 'SPLUNK_REALM') }}"
26 | splunk_otel_collector_config: /etc/otel/collector/agent_config.yaml
27 | install_splunk_otel_auto_instrumentation: true
28 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/teleport/files/start-teleport.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /etc/userdata
4 |
5 | cmd="/usr/local/bin/teleport start --diag-addr=0.0.0.0:3000 --pid-file=/run/teleport.pid"
6 |
7 | INSTANCE_ID=$(wget -q -O - http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.instanceId')
8 | TENANT=$(wget -q -O - http://169.254.169.254/latest/meta-data/tags/instance/TeleportTenantName)
9 |
10 | sed -e "s|\$TENANT|$TENANT|g" \
11 | -e "s|\$INSTANCE_ID|$INSTANCE_ID|g" \
12 | /etc/teleport.yaml.tpl >/etc/teleport.yaml
13 |
14 | exec $cmd
15 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/teleport/files/teleport.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Teleport SSH Service FIPS
3 | After=network.target
4 |
5 | [Service]
6 | Type=simple
7 | Restart=always
8 | EnvironmentFile=-/etc/default/teleport
9 | ExecStartPre=/bin/rm -rf /var/lib/teleport-app
10 | ExecStart=/etc/start-teleport.sh
11 | ExecReload=/bin/kill -HUP $MAINPID
12 | PIDFile=/run/teleport.pid
13 |
14 | [Install]
15 | WantedBy=multi-user.target
16 |
--------------------------------------------------------------------------------
/examples/build/ansible/roles/teleport/templates/teleport.yaml.j2:
--------------------------------------------------------------------------------
1 | teleport:
2 | data_dir: /var/lib/teleport-app
3 | nodename: forge-cicd-$INSTANCE_ID
4 | ca_pin: {{ teleport_ca_pin }}
5 | join_params:
6 | method: token
7 | token_name: headless-token
8 | auth_servers: [{{ teleport_auth_server }}]
9 | log:
10 | output: stderr
11 | severity: INFO
12 | auth_service:
13 | enabled: no
14 | ssh_service:
15 | enabled: yes
16 | labels:
17 | Tenant: $TENANT
18 | InstanceId: $INSTANCE_ID
19 | commands:
20 | - name: hostname
21 | command: ["hostname"]
22 | period: 1m0s
23 | - name: IP-addresses
24 | command: ["hostname", "-I"]
25 | period: 1h0m0s
26 | - name: timestamp
27 | command: ["uptime", "-s"]
28 | period: 1h0m0s
29 | proxy_service:
30 | enabled: no
31 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/release_versions.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | api_version: v1
3 | product: Forge
4 | version: v1.0.0
5 | metadata:
6 | use_local_repos: true
7 | spec:
8 | # Versions of our IaC/Terraform modules.
9 | iac:
10 | modules:
11 | eks:
12 | local_path: ../forge
13 | repo: git@github.com:cisco-open/forge.git
14 | module_path: modules/infra/eks
15 | ref: main
16 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/_global_settings/_global.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | global = yamldecode(file("_global.yaml"))
3 |
4 | team_name = local.global.team_name
5 | product_name = local.global.product_name
6 | project_name = local.global.project_name
7 | aws_account_prefix = local.global.aws_account_prefix
8 | git_org = local.global.git_org
9 | group_email = local.global.group_email
10 | }
11 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: forgeMT
3 | product_name: forgeMT
4 | project_name: forgemt
5 | aws_account_prefix: forge
6 | git_org: forgemt
7 | group_email: forgemt@cisco.com
8 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/_global_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-eks/terragrunt/_global_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/prod/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: prod
3 | default_aws_region: eu-west-1
4 | aws_account_id: '123456789012'
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-eks/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/_region.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | region_aws = "eu-west-1"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-eks/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/prod/regions/eu-west-1/eks/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 |
3 | config = yamldecode(file("config.yaml"))
4 |
5 | cluster_name = local.config.cluster_name
6 | cluster_version = local.config.cluster_version
7 | cluster_size = local.config.cluster_size
8 | subnet_ids = local.config.subnet_ids
9 | vpc_id = local.config.vpc_id
10 | cluster_ami_filter = local.config.cluster_ami_filter
11 | cluster_ami_owners = local.config.cluster_ami_owners
12 | }
13 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/prod/regions/eu-west-1/eks/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | cluster_name: forge-euw1-dev
3 | cluster_version: '1.31'
4 | cluster_size:
5 | instance_type: m5.large
6 | min_size: 3
7 | max_size: 10
8 | desired_size: 3
9 | subnet_ids:
10 | - subnet-0abc1234def567890
11 | - subnet-0123456789abcdef0
12 | vpc_id: vpc-0abc1234def567890
13 | cluster_ami_filter:
14 | - EKS1.31Ubuntu22-amd64-hvm-*
15 | cluster_ami_owners:
16 | - '123456789012'
17 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/environments/terragrunt.hcl:
--------------------------------------------------------------------------------
1 | # We use for enabling safety hooks. They're in place to prevent an accident "tf
2 | # run-all apply" for a non-dev environment.
3 | terraform {
4 | # Make it difficult to change or destroy resources in non-dev environments.
5 | before_hook "before_hook" {
6 | commands = ["apply", "plan", "destroy"]
7 | execute = [
8 | "/bin/bash", "-c",
9 | "${get_parent_terragrunt_dir()}/safety_hook.sh \"${get_parent_terragrunt_dir()}\" \"${get_terragrunt_dir()}\""
10 | ]
11 | }
12 |
13 | # Placeholder (no-op); might use this in the future.
14 | after_hook "after_hook" {
15 | commands = ["apply", "plan"]
16 | execute = ["/bin/bash", "-c", ":"]
17 | run_on_error = true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/root.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-eks/terragrunt/root.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-eks/terragrunt/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-eks/terragrunt/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/release_versions.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | api_version: v1
3 | product: Forge
4 | version: v1.0.0
5 | metadata:
6 | use_local_repos: true
7 | spec:
8 | # Versions of our IaC/Terraform modules.
9 | iac:
10 | modules:
11 | cloud_custodian:
12 | local_path: ../forge
13 | repo: git@github.com:cisco-open/forge.git
14 | module_path: modules/infra/cloud_custodian
15 | ref: main
16 | cloud_formation:
17 | local_path: ../forge
18 | repo: git@github.com:cisco-open/forge.git
19 | module_path: modules/infra/cloud_formation
20 | ref: main
21 | ecr:
22 | local_path: ../forge
23 | repo: git@github.com:cisco-open/forge.git
24 | module_path: modules/infra/ecr
25 | ref: main
26 | storage:
27 | local_path: ../forge
28 | repo: git@github.com:cisco-open/forge.git
29 | module_path: modules/infra/storage
30 | ref: main
31 | forge_subscription:
32 | local_path: ../forge
33 | repo: git@github.com:cisco-open/forge.git
34 | module_path: modules/infra/forge_subscription
35 | ref: main
36 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/_global_settings/_global.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | global = yamldecode(file("_global.yaml"))
3 |
4 | team_name = local.global.team_name
5 | product_name = local.global.product_name
6 | project_name = local.global.project_name
7 | aws_account_prefix = local.global.aws_account_prefix
8 | git_org = local.global.git_org
9 | group_email = local.global.group_email
10 | }
11 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: forgeMT
3 | product_name: forgeMT
4 | project_name: forgemt
5 | aws_account_prefix: forge
6 | git_org: forgemt
7 | group_email: forgemt@cisco.com
8 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/_global_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-extras/terragrunt/_global_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: prod
3 | default_aws_region: eu-west-1
4 | aws_account_id: '123456789012'
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-extras/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/cloud_custodian/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | forge_role_arn = local.config.forge_role_arn
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/cloud_custodian/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | forge_role_arn: arn:aws:iam::123456789012:role/role_for_forge_runners
3 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/forge_subscription/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | forge = local.config.forge
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/forge_subscription/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | forge:
3 | runner_roles:
4 | - arn:aws:iam::123456789012:role/srea-euw1-sl-small/srea-euw1-sl-small-runner-role
5 | - arn:aws:iam::123456789012:role/srea-euw1-sl-standard/srea-euw1-sl-standard-runner-role
6 | - arn:aws:iam::123456789012:role/srea-euw1-sl-large/srea-euw1-sl-large-runner-role
7 | - arn:aws:iam::123456789012:role/srea-euw1-sl-dependabot-arc-runner-role
8 | - arn:aws:iam::123456789012:role/srea-euw1-sl-k8s-arc-runner-role
9 |
10 | ecr_repositories:
11 | names:
12 | - pre-commit
13 | - ops-builder
14 | - actions-runner
15 | - actions-runner-base-image
16 | ecr_access_account_ids:
17 | - '123456789013'
18 | regions:
19 | - eu-west-1
20 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/_region.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | region_aws = "eu-west-1"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-extras/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/regions/eu-west-1/ecr/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | repositories = local.config.repositories
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/prod/regions/eu-west-1/ecr/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | repositories:
3 | - repo: pre-commit
4 | mutability: MUTABLE
5 | scan_on_push: true
6 | - repo: ops-builder
7 | mutability: MUTABLE
8 | scan_on_push: true
9 | - repo: actions-runner
10 | mutability: MUTABLE
11 | scan_on_push: true
12 | - repo: actions-runner-base-image
13 | mutability: MUTABLE
14 | scan_on_push: true
15 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/environments/terragrunt.hcl:
--------------------------------------------------------------------------------
1 | # We use for enabling safety hooks. They're in place to prevent an accident "tf
2 | # run-all apply" for a non-dev environment.
3 | terraform {
4 | # Make it difficult to change or destroy resources in non-dev environments.
5 | before_hook "before_hook" {
6 | commands = ["apply", "plan", "destroy"]
7 | execute = [
8 | "/bin/bash", "-c",
9 | "${get_parent_terragrunt_dir()}/safety_hook.sh \"${get_parent_terragrunt_dir()}\" \"${get_terragrunt_dir()}\""
10 | ]
11 | }
12 |
13 | # Placeholder (no-op); might use this in the future.
14 | after_hook "after_hook" {
15 | commands = ["apply", "plan"]
16 | execute = ["/bin/bash", "-c", ":"]
17 | run_on_error = true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/root.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-extras/terragrunt/root.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-extras/terragrunt/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-extras/terragrunt/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/release_versions.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | api_version: v1
3 | product: Forge
4 | version: v1.0.0
5 | metadata:
6 | use_local_repos: true
7 | spec:
8 | # Versions of our IaC/Terraform modules.
9 | iac:
10 | modules:
11 | splunk_cloud_forgecicd:
12 | local_path: ../forge
13 | repo: git@github.com:cisco-open/forge.git
14 | module_path: modules/platform/splunk_cloud_data_manager
15 | ref: main
16 | splunk_cloud_conf:
17 | local_path: ../forge
18 | repo: git@github.com:cisco-open/forge.git
19 | module_path: modules/platform/splunk_cloud_conf_shared
20 | ref: main
21 |
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/_global_settings/_global.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | team_name = "forgeMT" # # e.g., "DevOps Team"
3 | product_name = "forgeMT" # # e.g., "Internal Platform"
4 | project_name = "forgemt" # # e.g., "intplat"
5 | aws_account_prefix = "forge" # # e.g., "intplat-ops"
6 |
7 | # GitHub organization for GitOps repo.
8 | git_org = "forgemt" # e.g., "my-org"
9 |
10 | # Team information.
11 | group_email = "forgemt@cisco.com" # e.g., "devops@example.com"
12 | }
13 |
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/_global_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-integrations/terragrunt/_global_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-integrations/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/_region.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | region_aws = "eu-west-1"
3 | region_alias = "euw1"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-integrations/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/_vpc.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | vpc_alias = "sl" #
3 |
4 | # Subnet IDs for Lambda functions
5 | lambda_subnet_ids = ["subnet-0abc1234def567890"] #
6 |
7 | vpc_id = "vpc-0abc1234def567890" #
8 | subnet_ids = [
9 | "subnet-0abc1234def567890", #
10 | "subnet-0123456789abcdef0", #
11 | ]
12 | cluster_name = "forge-euw1-prod" #
13 | }
14 |
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-integrations/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/environments/prod/splunk_cloud_forgecicd/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | regions = [
3 | "eu-west-1",
4 | ]
5 |
6 | env = "prod"
7 | }
8 |
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/root.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-integrations/terragrunt/root.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-integrations/terragrunt/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-integrations/terragrunt/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/release_versions.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | api_version: v1
3 | product: Forge
4 | version: v1.0.0
5 | metadata:
6 | use_local_repos: true
7 | spec:
8 | # Versions of our IaC/Terraform modules.
9 | iac:
10 | modules:
11 | forge_runners:
12 | local_path: ../forge
13 | repo: git@github.com:cisco-open/forge.git
14 | module_path: modules/platform/forge_runners
15 | ref: main
16 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/_global_settings/_global.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | global = yamldecode(file("_global.yaml"))
3 |
4 | team_name = local.global.team_name
5 | product_name = local.global.product_name
6 | project_name = local.global.project_name
7 | aws_account_prefix = local.global.aws_account_prefix
8 | git_org = local.global.git_org
9 | group_email = local.global.group_email
10 | }
11 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: forgeMT
3 | product_name: forgeMT
4 | project_name: forgemt
5 | aws_account_prefix: forge
6 | git_org: forgemt
7 | group_email: forgemt@cisco.com
8 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/_global_settings/tenants/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/_global_settings/tenants/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/_global_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/_global_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: prod
3 | default_aws_region: eu-west-1
4 | aws_account_id: '123456789012'
5 | runner_group_name_suffix: cicd-forge
6 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/_region.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | region_aws = "eu-west-1"
3 | region_alias = "euw1"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/_vpc.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | vpc = yamldecode(file("_vpc.yaml"))
3 |
4 | vpc_alias = local.vpc.vpc_alias
5 | lambda_subnet_ids = local.vpc.lambda_subnet_ids
6 | vpc_id = local.vpc.vpc_id
7 | subnet_ids = local.vpc.subnet_ids
8 | cluster_name = local.vpc.cluster_name
9 | }
10 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/_vpc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | vpc_alias: sl
3 | lambda_subnet_ids:
4 | - subnet-0abc1234def567890
5 | vpc_id:
6 | - vpc-0abc1234def567890
7 | subnet_ids:
8 | - subnet-0abc1234def567890
9 | - subnet-0123456789abcdef0
10 | cluster_name: forge-euw1-prod
11 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/_vpc_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/tenants/acme/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | gh_config:
3 | ghes_url: ''
4 | ghes_org: cisco-open
5 | tenant:
6 | iam_roles_to_assume:
7 | - arn:aws:iam::123456789012:role/role_for_forge_runners
8 | ecr_registries:
9 | - 123456789012.dkr.ecr.eu-west-1.amazonaws.com
10 | ec2_runner_specs:
11 | small:
12 | ami_name: forge-gh-runner-v*
13 | ami_owner: '123456789012'
14 | ami_kms_key_arn: ''
15 | max_instances: 1
16 | instance_types:
17 | - t2.small
18 | - t2.medium
19 | - t2.large
20 | - t3.small
21 | - t3.medium
22 | - t3.large
23 | pool_config: []
24 | arc_runner_specs:
25 | dependabot:
26 | runner_size:
27 | max_runners: 100
28 | min_runners: 1
29 | scale_set_name: dependabot
30 | scale_set_type: dind
31 | container_actions_runner: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/actions-runner:latest
32 | container_requests_cpu: 500m
33 | container_requests_memory: 1Gi
34 | container_limits_cpu: '1'
35 | container_limits_memory: 2Gi
36 | k8s:
37 | runner_size:
38 | max_runners: 100
39 | min_runners: 1
40 | scale_set_name: k8s
41 | scale_set_type: k8s
42 | container_actions_runner: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/actions-runner:latest
43 | container_requests_cpu: 500m
44 | container_requests_memory: 1Gi
45 | container_limits_cpu: '1'
46 | container_limits_memory: 2Gi
47 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/environments/terragrunt.hcl:
--------------------------------------------------------------------------------
1 | # We use for enabling safety hooks. They're in place to prevent an accident "tf
2 | # run-all apply" for a non-dev environment.
3 | terraform {
4 | # Make it difficult to change or destroy resources in non-dev environments.
5 | before_hook "before_hook" {
6 | commands = ["apply", "plan", "destroy"]
7 | execute = [
8 | "/bin/bash", "-c",
9 | "${get_parent_terragrunt_dir()}/safety_hook.sh \"${get_parent_terragrunt_dir()}\" \"${get_terragrunt_dir()}\""
10 | ]
11 | }
12 |
13 | # Placeholder (no-op); might use this in the future.
14 | after_hook "after_hook" {
15 | commands = ["apply", "plan"]
16 | execute = ["/bin/bash", "-c", ":"]
17 | run_on_error = true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/root.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/root.hcl
--------------------------------------------------------------------------------
/examples/deployments/forge-tenant/terragrunt/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/forge-tenant/terragrunt/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/release_versions.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | api_version: v1
3 | product: Forge
4 | version: v1.0.0
5 | metadata:
6 | use_local_repos: true
7 | spec:
8 | # Versions of our IaC/Terraform modules.
9 | iac:
10 | modules:
11 | splunk_cloud_data_manager_common:
12 | local_path: ../forge
13 | repo: git@github.com:cisco-open/forge.git
14 | module_path: modules/integrations/splunk_cloud_data_manager_common
15 | ref: main
16 | splunk_cloud_data_manager:
17 | local_path: ../forge
18 | repo: git@github.com:cisco-open/forge.git
19 | module_path: modules/integrations/splunk_cloud_data_manager
20 | ref: main
21 | splunk_o11y_aws_integration_common:
22 | local_path: ../forge
23 | repo: git@github.com:cisco-open/forge.git
24 | module_path: modules/integrations/splunk_o11y_aws_integration_common
25 | ref: main
26 | splunk_o11y_aws_integration:
27 | local_path: ../forge
28 | repo: git@github.com:cisco-open/forge.git
29 | module_path: modules/integrations/splunk_o11y_aws_integration
30 | ref: main
31 | splunk_otel_eks:
32 | local_path: ../forge
33 | repo: git@github.com:cisco-open/forge.git
34 | module_path: modules/integrations/splunk_otel_eks
35 | ref: main
36 | splunk_secrets:
37 | local_path: ../forge
38 | repo: git@github.com:cisco-open/forge.git
39 | module_path: modules/integrations/splunk_secrets
40 | ref: main
41 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/_global_settings/_global.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | global = yamldecode(file("_global.yaml"))
3 |
4 | team_name = local.global.team_name
5 | product_name = local.global.product_name
6 | project_name = local.global.project_name
7 | aws_account_prefix = local.global.aws_account_prefix
8 | git_org = local.global.git_org
9 | group_email = local.global.group_email
10 | }
11 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: forgeMT
3 | product_name: forgeMT
4 | project_name: forgemt
5 | aws_account_prefix: forge
6 | git_org: forgemt
7 | group_email: forgemt@cisco.com
8 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/_global_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/splunk-deployment/terragrunt/_global_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: prod
3 | default_aws_region: eu-west-1
4 | aws_account_id: '123456789012'
5 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/splunk-deployment/terragrunt/environments/prod/_environment_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/_region.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | region_aws = "eu-west-1"
3 | region_alias = "euw1"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/_region_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/splunk_o11y_aws_integration/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | splunk_ingest_url = local.config.splunk_ingest_url
4 | template_url = local.config.template_url
5 | }
6 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/splunk_o11y_aws_integration/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | splunk_ingest_url: https://ingest.us0.signalfx.com
3 | template_url: https://o11y-public.s3.amazonaws.com/aws-cloudformation-templates/release/template_all_features_regional.yaml
4 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/splunk_otel_eks/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | cluster_name = local.config.cluster_name
4 | splunk_otel_collector = local.config.splunk_otel_collector
5 | }
6 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/regions/eu-west-1/splunk_otel_eks/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | cluster_name: forge-euw1-prod
3 |
4 | splunk_otel_collector:
5 | splunk_observability_realm: us0
6 | splunk_platform_endpoint: https://http-inputs-mycompany.splunkcloud.com:443/services/collector
7 | splunk_platform_index: forge-prod-index
8 | gateway: false
9 | splunk_observability_profiling: true
10 | environment: prod
11 | discovery: true
12 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_cloud_data_manager/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | cloudformation_s3_config = local.config.cloudformation_s3_config
4 | cloudwatch_log_groups_config = local.config.cloudwatch_log_groups_config
5 | security_metadata_config = local.config.security_metadata_config
6 | splunk_cloud = local.config.splunk_cloud
7 | }
8 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_cloud_data_manager/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | splunk_cloud: https://mycompany.splunkcloud.com
3 |
4 | cloudformation_s3_config:
5 | bucket: 123456789012-short-term-storage
6 | key: cicd_artifacts/cf-templates/
7 | region: eu-west-1
8 |
9 | cloudwatch_log_groups_config:
10 | enabled: true
11 | name: forge-cwl-prod
12 | datasource:
13 | cwl-eks:
14 | enabled: true
15 | index: forge-prod-index
16 | cwl-lambda:
17 | enabled: true
18 | index: forge-prod-index
19 | regions:
20 | - eu-west-1
21 |
22 | security_metadata_config:
23 | enabled: true
24 | name: forge-secmeta-prod
25 | datasource:
26 | metadata:
27 | enabled: true
28 | index: forge-prod-index
29 | regions:
30 | - eu-west-1
31 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_cloud_data_manager_common/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | splunk_cloud = local.config.splunk_cloud
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_cloud_data_manager_common/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | splunk_cloud: https://mycompany.splunkcloud.com
3 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_o11y_aws_integration_common/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | integration_name = local.config.integration_name
4 | integration_regions = local.config.integration_regions
5 | splunk_api_url = local.config.splunk_api_url
6 | splunk_organization_id = local.config.splunk_organization_id
7 | }
8 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_o11y_aws_integration_common/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | integration_name: forge-prod
3 | integration_regions:
4 | - eu-west-1
5 | splunk_api_url: https://api.us0.signalfx.com
6 | splunk_organization_id: ORG1234567890
7 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_secrets/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | config = yamldecode(file("config.yaml"))
3 | replica_regions = local.config.replica_regions
4 | }
5 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/prod/splunk_secrets/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | replica_regions: []
3 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/environments/terragrunt.hcl:
--------------------------------------------------------------------------------
1 | # We use for enabling safety hooks. They're in place to prevent an accident "tf
2 | # run-all apply" for a non-dev environment.
3 | terraform {
4 | # Make it difficult to change or destroy resources in non-dev environments.
5 | before_hook "before_hook" {
6 | commands = ["apply", "plan", "destroy"]
7 | execute = [
8 | "/bin/bash", "-c",
9 | "${get_parent_terragrunt_dir()}/safety_hook.sh \"${get_parent_terragrunt_dir()}\" \"${get_terragrunt_dir()}\""
10 | ]
11 | }
12 |
13 | # Placeholder (no-op); might use this in the future.
14 | after_hook "after_hook" {
15 | commands = ["apply", "plan"]
16 | execute = ["/bin/bash", "-c", ":"]
17 | run_on_error = true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/root.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/splunk-deployment/terragrunt/root.hcl
--------------------------------------------------------------------------------
/examples/deployments/splunk-deployment/terragrunt/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/deployments/splunk-deployment/terragrunt/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/infra-forge/index.md:
--------------------------------------------------------------------------------
1 | # 🧩 Infra Forge Deployment Example
2 |
3 | This folder provides a complete, multi-tenant **Forge** deployment using **Terragrunt** for layered configuration.
4 |
5 | > **⚠️ Important:** Replace all `` placeholders with actual values (e.g., tokens, ARNs, config IDs) before deploying.
6 |
7 | ---
8 |
9 | ## ⚠️ Prerequisites
10 |
11 | Before deploying, ensure:
12 |
13 | * All `` placeholders are replaced
14 | * Secrets are created in **AWS Secrets Manager**
15 | → See [`docs/configurations/secrets.md`](../../docs/configurations/secrets.md)
16 | * Infra dependencies (e.g., IAM, S3) are in place
17 | → See [`docs/configurations/dependency.md`](../../docs/configurations/dependency.md)
18 |
19 | ---
20 |
21 | ## 🚀 Deployment
22 |
23 | ### Apply a Single Module
24 |
25 | ```bash
26 | terragrunt apply terragrunt/environments/prod/regions/eu-west-1/vpcs/sl/tenants/forge/runner_settings.hcl
27 | ```
28 |
29 | ### Apply All Modules Recursively
30 |
31 | ```bash
32 | terragrunt run-all apply terragrunt/environments/prod/
33 | ```
34 |
35 | > **Tip:** Always run `terragrunt run-all plan` first to validate changes before applying.
36 |
--------------------------------------------------------------------------------
/examples/infra-forge/release_versions.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | api_version: v1
3 | product: Forge
4 | cloud_provider: aws
5 | version: v0.0.0
6 | revision:
7 | use_local_repos: false
8 | actor:
9 | job_id:
10 | spec:
11 | # Versions of our IaC/Terraform modules.
12 | iac:
13 | modules:
14 | forge_runners:
15 | local_path: modules/forge-modules
16 | repo: git@github.com:cisco-open/forge.git
17 | ref: main
18 | teleport:
19 | local_path: modules/forge-modules
20 | repo: git@github.com:cisco-open/forge.git
21 | ref: main
22 | splunk_cloud_data_manager:
23 | local_path: modules/infra-modules
24 | repo: git@github.com:cisco-open/forge.git
25 | ref: main
26 | splunk_conf:
27 | local_path: modules/forge-modules
28 | repo: git@github.com:cisco-open/forge.git
29 | ref: main
30 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/_global.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Default region for the AWS accounts associated with the account (i.e. where
3 | # we store the TF state files, etc.).
4 | team_name = "ForgeTeam"
5 | product_name = "Forge"
6 | project_name = "forge"
7 | cloud_provider = "aws"
8 | sl_aws_account_prefix = "forge-ops" # Prefix for the AWS profile. Eg: forge-ops- | forge-ops-.
9 |
10 | # Team information.
11 | group_email = ""
12 |
13 | splunk_api_url = "https://api..signalfx.com"
14 | splunk_organization_id = ""
15 | }
16 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/ami.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | # Default AWS profile and region. Typically used when deciding on
11 | # master/replica setups, such as auto-replication of secrets, databases, etc.
12 | default_aws_region = local.env_data.locals.default_aws_region
13 | default_aws_profile = local.env_data.locals.default_aws_profile
14 | aws_account_id = local.env_data.locals.aws_account_id
15 | }
16 |
17 | input = {
18 |
19 | aws_profile = local.default_aws_profile
20 |
21 | # Let's centralize this into a common region.
22 | aws_region = local.env_data.locals.default_aws_region
23 | }
24 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/ami_sharing.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 |
12 | # Region-wide settings.
13 | region_data = read_terragrunt_config(find_in_parent_folders("_region_wide_settings/_region.hcl"))
14 | region = local.region_data.locals.region_aws
15 |
16 | ami_sharing_data = read_terragrunt_config(find_in_parent_folders("ami_sharing/config.hcl"))
17 | }
18 |
19 | inputs = {
20 |
21 | aws_profile = local.default_aws_profile
22 |
23 | aws_region = local.region
24 | account_ids = local.ami_sharing_data.locals.account_ids
25 | ami_name_filter = local.ami_sharing_data.locals.ami_name_filter
26 | }
27 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/billing.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 | aws_account_id = local.env_data.locals.aws_account_id
12 |
13 | # Region-wide settings.
14 | region_data = read_terragrunt_config(find_in_parent_folders("_region_wide_settings/_region.hcl"))
15 | region = local.region_data.locals.region_aws
16 | }
17 |
18 | inputs = {
19 | # Common values re-used throughout sub-modules. These are also used in things
20 | # like logs, determining whqqich S3 buckets and/or paths to use for storing
21 | # build artifacts, etc.
22 |
23 | aws_profile = local.default_aws_profile # Email address used for critical alerts.
24 | group_email = local.group_email
25 |
26 | # Let's centralize this into a common region.
27 | aws_region = local.region
28 | }
29 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/budget.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Default AWS profile and region. Typically used when deciding on
9 | # master/replica setups, such as auto-replication of secrets, databases, etc.
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 | aws_account_id = local.env_data.locals.aws_account_id
12 |
13 | budget_data = read_terragrunt_config(find_in_parent_folders("budget/config.hcl"))
14 | }
15 |
16 | inputs = {
17 | # Common values re-used throughout sub-modules. These are also used in things
18 | # like logs, determining which S3 buckets and/or paths to use for storing
19 | # build artifacts, etc.
20 | project_name = local.project_name
21 | aws_profile = local.default_aws_profile
22 | aws_account_id = local.aws_account_id
23 |
24 | sl_aws_account_name = local.env_data.locals.sl_aws_account_name
25 |
26 | # Let's centralize this into a common region.
27 | aws_region = local.env_data.locals.default_aws_region
28 | # Configuration for Forge runners.
29 | aws_budget = local.budget_data.locals.aws_budget
30 | }
31 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/cloud_custodian.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 | aws_account_id = local.env_data.locals.aws_account_id
12 | }
13 |
14 | inputs = {
15 | # Common values re-used throughout sub-modules. These are also used in things
16 | # like logs, determining which S3 buckets and/or paths to use for storing
17 | # build artifacts, etc.
18 | project_name = local.project_name
19 | aws_profile = local.default_aws_profile
20 | aws_account_id = local.aws_account_id
21 |
22 | aws_region = local.default_aws_region
23 | forge_role_arn = "arn:aws:iam::123456789012:role/role_for_forge_runners"
24 | }
25 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/cloudformation.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 | aws_account_id = local.env_data.locals.aws_account_id
12 | }
13 |
14 | inputs = {
15 | # Common values re-used throughout sub-modules. These are also used in things
16 | # like logs, determining which S3 buckets and/or paths to use for storing
17 | # build artifacts, etc.
18 | project_name = local.project_name
19 | aws_profile = local.default_aws_profile
20 | aws_account_id = local.aws_account_id
21 |
22 | aws_region = local.default_aws_region
23 | }
24 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/ecr.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 |
12 | # Region-wide settings.
13 | region_data = read_terragrunt_config(find_in_parent_folders("_region_wide_settings/_region.hcl"))
14 | region = local.region_data.locals.region_aws
15 | }
16 |
17 | inputs = {
18 | # Common values re-used throughout sub-modules. These are also used in things
19 | # like logs, determining which S3 buckets and/or paths to use for storing
20 | # build artifacts, etc.
21 |
22 | aws_profile = local.default_aws_profile
23 |
24 | aws_region = local.region
25 | }
26 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/forge_subscription.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | # Default AWS profile and region. Typically used when deciding on
11 | # master/replica setups, such as auto-replication of secrets, databases, etc.
12 | default_aws_profile = local.env_data.locals.default_aws_profile
13 |
14 | subscription_settings_data = read_terragrunt_config(find_in_parent_folders("forge_subscription/subscription_settings.hcl"))
15 | }
16 |
17 | inputs = {
18 | # Common values re-used throughout sub-modules. These are also used in things
19 | # like logs, determining which S3 buckets and/or paths to use for storing
20 | # build artifacts, etc.
21 |
22 | aws_profile = local.default_aws_profile
23 |
24 | # Let's centralize this into a common region.
25 | aws_region = local.env_data.locals.default_aws_region
26 |
27 | # Configuration for Forge runners.
28 | forge = local.subscription_settings_data.locals.forge
29 | }
30 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/opt_in_regions.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | # Default AWS profile and region. Typically used when deciding on
11 | # master/replica setups, such as auto-replication of secrets, databases, etc.
12 | default_aws_region = local.env_data.locals.default_aws_region
13 | default_aws_profile = local.env_data.locals.default_aws_profile
14 |
15 | opt_in_regions_data = read_terragrunt_config(find_in_parent_folders("opt_in_regions/config.hcl"))
16 | }
17 |
18 | inputs = {
19 | # Common values re-used throughout sub-modules. These are also used in things
20 | # like logs, determining which S3 buckets and/or paths to use for storing
21 | # build artifacts, etc.
22 |
23 | aws_profile = local.default_aws_profile
24 |
25 | # Let's centralize this into a common region.
26 | aws_region = local.env_data.locals.default_aws_region
27 | # Configuration for Forge runners.
28 | opt_in_regions = local.opt_in_regions_data.locals.opt_in_regions
29 | }
30 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/secrets.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 | aws_account_id = local.env_data.locals.aws_account_id
12 |
13 | # Region-wide settings.
14 | region_data = read_terragrunt_config(find_in_parent_folders("_region_wide_settings/_region.hcl"))
15 | region = local.region_data.locals.region_aws
16 | }
17 |
18 | inputs = {
19 | # Common values re-used throughout sub-modules. These are also used in things
20 | # like logs, determining which S3 buckets and/or paths to use for storing
21 | # build artifacts, etc.
22 | project_name = local.project_name
23 | aws_profile = local.default_aws_profile
24 | aws_account_id = local.aws_account_id
25 |
26 | aws_region = local.region
27 | }
28 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/service_linked_roles.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | # Default AWS profile and region. Typically used when deciding on
11 | # master/replica setups, such as auto-replication of secrets, databases, etc.
12 | default_aws_region = local.env_data.locals.default_aws_region
13 | default_aws_profile = local.env_data.locals.default_aws_profile
14 |
15 | }
16 |
17 | inputs = {
18 | # Common values re-used throughout sub-modules. These are also used in things
19 | # like logs, determining which S3 buckets and/or paths to use for storing
20 | # build artifacts, etc.
21 |
22 | aws_profile = local.default_aws_profile
23 |
24 | # Let's centralize this into a common region.
25 | aws_region = local.env_data.locals.default_aws_region
26 | }
27 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/splunk_cloud_data_manager.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Environment-wide settings.
3 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
4 | extra_tags = local.env_data.locals.extra_tags
5 | default_tags = local.env_data.locals.default_tags
6 |
7 | # Default AWS profile and region. Typically used when deciding on
8 | # master/replica setups, such as auto-replication of secrets, databases, etc.
9 | default_aws_region = local.env_data.locals.default_aws_region
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 | aws_account_id = local.env_data.locals.aws_account_id
12 |
13 | splunk_cloud = read_terragrunt_config(find_in_parent_folders("splunk_cloud_data_manager/config.hcl"))
14 | }
15 |
16 | inputs = {
17 | # Common values re-used throughout sub-modules. These are also used in things
18 | # like logs, determining which S3 buckets and/or paths to use for storing
19 | # build artifacts, etc.
20 | aws_profile = local.default_aws_profile
21 | aws_account_id = local.aws_account_id
22 | aws_region = local.default_aws_region
23 |
24 | tags = local.default_tags
25 | all_tags = merge(local.extra_tags, local.default_tags)
26 |
27 | splunk_cloud = local.splunk_cloud.locals.splunk_cloud
28 | cloudformation_s3_config = local.splunk_cloud.locals.cloudformation_s3_config
29 |
30 | cloudwatch_log_groups_config = local.splunk_cloud.locals.cloudwatch_log_groups_config
31 | security_metadata_config = local.splunk_cloud.locals.security_metadata_config
32 | }
33 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/splunk_cloud_data_manager_deps.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | # Default AWS profile and region. Typically used when deciding on
11 | # master/replica setups, such as auto-replication of secrets, databases, etc.
12 | default_aws_region = local.env_data.locals.default_aws_region
13 | default_aws_profile = local.env_data.locals.default_aws_profile
14 | aws_account_id = local.env_data.locals.aws_account_id
15 |
16 | splunk_cloud = read_terragrunt_config(find_in_parent_folders("splunk_cloud_data_manager_deps/config.hcl"))
17 | }
18 |
19 | inputs = {
20 |
21 | aws_profile = local.default_aws_profile
22 | aws_account_id = local.aws_account_id
23 |
24 | aws_region = local.default_aws_region
25 | splunk_cloud = local.splunk_cloud.locals.splunk_cloud
26 | }
27 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/splunk_o11y_integration.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 | splunk_api_url = local.global_data.locals.splunk_api_url
8 | splunk_organization_id = local.global_data.locals.splunk_organization_id
9 |
10 | # Environment-wide settings.
11 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
12 | default_aws_region = local.env_data.locals.default_aws_region
13 | default_aws_profile = local.env_data.locals.default_aws_profile
14 |
15 | splunk_integration = read_terragrunt_config(find_in_parent_folders("splunk_o11y_integration/config.hcl"))
16 | }
17 |
18 | inputs = {
19 | # Common values re-used throughout sub-modules. These are also used in things
20 | # like logs, determining which S3 buckets and/or paths to use for storing
21 | # build artifacts, etc.
22 | project_name = local.project_name
23 | aws_profile = local.default_aws_profile
24 | aws_region = local.default_aws_region
25 | integration_name = local.splunk_integration.locals.integration_name
26 | integration_regions = local.splunk_integration.locals.integration_regions
27 | splunk_api_url = local.splunk_api_url
28 | splunk_organization_id = local.splunk_organization_id
29 | }
30 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/splunk_o11y_regional_integration.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Project-wide settings (i.e. global across the various AWS accounts used in
3 | # the overall repo/project).
4 | global_data = read_terragrunt_config(find_in_parent_folders("_global_settings/_global.hcl"))
5 | group_email = local.global_data.locals.group_email
6 | project_name = local.global_data.locals.project_name
7 |
8 | # Environment-wide settings.
9 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
10 | default_aws_profile = local.env_data.locals.default_aws_profile
11 |
12 | # Region-wide settings.
13 | region_data = read_terragrunt_config(find_in_parent_folders("_region_wide_settings/_region.hcl"))
14 | region = local.region_data.locals.region_aws
15 |
16 | splunk_integration = read_terragrunt_config(find_in_parent_folders("splunk_o11y_regional_integration/config.hcl"))
17 | }
18 |
19 | inputs = {
20 | # Common values re-used throughout sub-modules. These are also used in things
21 | # like logs, determining which S3 buckets and/or paths to use for storing
22 | # build artifacts, etc.
23 | project_name = local.project_name
24 | aws_profile = local.default_aws_profile
25 | aws_region = local.region
26 | splunk_ingest_url = local.splunk_integration.locals.splunk_ingest_url
27 | template_url = local.splunk_integration.locals.template_url
28 | }
29 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/_global_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/infra-forge/terragrunt/_global_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/_environment_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/infra-forge/terragrunt/environments/dev/_environment_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/budget/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | # Budget/billing constraints.
3 | aws_budget = {
4 | # AWS uses strings, not numbers, in this API.
5 | per_account = "500.00"
6 | services = {
7 | EC2 = {
8 | budget_limit = "200.00"
9 | },
10 | S3 = {
11 | budget_limit = "200.00"
12 | },
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/forge_subscription/subscription_settings.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | forge = {
3 | runner_roles = [
4 | "arn:aws:iam::123456789012:role/tenant_example-euw1-sl-small/tenant_example-euw1-sl-small-runner-role",
5 | "arn:aws:iam::123456789012:role/tenant_example-euw1-sl-standard/tenant_example-euw1-sl-standard-runner-role",
6 | "arn:aws:iam::123456789012:role/tenant_example-euw1-sl-large/tenant_example-euw1-sl-large-runner-role",
7 | "arn:aws:iam::123456789012:role/tenant_example-euw1-sl-dependabot-arc-runner-role",
8 | "arn:aws:iam::123456789012:role/tenant_example-euw1-sl-k8s-arc-runner-role",
9 | ]
10 | ecr_repositories = {
11 | names = [
12 | "pre-commit",
13 | "ops-builder",
14 | "actions-runner",
15 | ]
16 | ecr_access_account_ids = [
17 | "123456789012", # Accounts that can pull from the ECR repositories
18 | ]
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/opt_in_regions/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 |
3 | opt_in_regions = [
4 | "af-south-1",
5 | "ap-east-1",
6 | "ap-south-2",
7 | "ap-southeast-3",
8 | "ap-southeast-5",
9 | "ap-southeast-4",
10 | "ca-west-1",
11 | "eu-south-1",
12 | "eu-south-2",
13 | "eu-central-2",
14 | "il-central-1",
15 | "me-south-1",
16 | "me-central-1",
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/regions/eu-west-1/_region_wide_settings/_region.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | region_aws = "eu-west-1"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/regions/eu-west-1/_region_wide_settings/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/infra-forge/terragrunt/environments/dev/regions/eu-west-1/_region_wide_settings/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/regions/eu-west-1/ami_sharing/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | account_ids = [
3 | "123456789012", # your tenant account id
4 | ]
5 | ami_name_filter = "forge-gh-runner-base-image-v*"
6 | }
7 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/regions/eu-west-1/eks/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | cluster_name = "forge-euw1-dev"
3 | cluster_version = "1.31"
4 | cluster_size = {
5 | instance_type = "m5.large"
6 | min_size = 3
7 | max_size = 10
8 | desired_size = 3
9 | }
10 | subnet_ids = [
11 | "subnet-aaaaaaaaaaaaaaaaa",
12 | "subnet-bbbbbbbbbbbbbbbbb",
13 | ]
14 | vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
15 |
16 | splunk_otel_collector = {
17 | splunk_observability_realm = "us0"
18 | splunk_platform_endpoint = "https://http-inputs-.splunkcloud.com:443/services/collector"
19 | splunk_platform_index = "forge-prod-index"
20 | gateway = false
21 | splunk_observability_profiling = true
22 | environment = "prod"
23 | discovery = true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/regions/eu-west-1/splunk_o11y_regional_integration/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | splunk_ingest_url = "https://ingest..signalfx.com"
3 | template_url = "https://o11y-public.s3.amazonaws.com/aws-cloudformation-templates/release/template_all_features_regional.yaml"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/splunk_cloud_data_manager/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | env_data = read_terragrunt_config(find_in_parent_folders("_environment_wide_settings/_environment.hcl"))
3 |
4 | splunk_cloud = "https://.splunkcloud.com"
5 | cloudformation_s3_config = {
6 | bucket = "${local.env_data.locals.aws_account_id}-short-term-storage"
7 | key = "cicd_artifacts/cf-templates/"
8 | region = "eu-west-1"
9 | }
10 |
11 | cloudwatch_log_groups_config = {
12 | enabled = true
13 | name = "forge-cwl-prod"
14 | datasource = {
15 | cwl-eks = {
16 | enabled = true
17 | index = "forge-prod-index"
18 | }
19 | cwl-lambda = {
20 | enabled = true
21 | index = "forge-prod-index"
22 | }
23 | }
24 | regions = ["eu-west-1"]
25 | }
26 |
27 | security_metadata_config = {
28 | enabled = true
29 | name = "forge-secmeta-prod"
30 | datasource = {
31 | metadata = {
32 | enabled = true
33 | index = "forge-prod-index"
34 | }
35 | }
36 | regions = ["eu-west-1"]
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/splunk_cloud_data_manager_deps/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | splunk_cloud = "https://your-instance.splunkcloud.com"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/dev/splunk_o11y_integration/config.hcl:
--------------------------------------------------------------------------------
1 | locals {
2 | integration_name = "forge-prod"
3 | integration_regions = [
4 | "eu-west-1",
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/environments/terragrunt.hcl:
--------------------------------------------------------------------------------
1 | # We use for enabling safety hooks. They're in place to prevent an accident "tf
2 | # run-all apply" for a non-dev environment.
3 | terraform {
4 | # Make it difficult to change or destroy resources in non-dev environments.
5 | before_hook "before_hook" {
6 | commands = ["apply", "plan", "destroy"]
7 | execute = [
8 | "/bin/bash", "-c",
9 | "${get_parent_terragrunt_dir()}/safety_hook.sh \"${get_parent_terragrunt_dir()}\" \"${get_terragrunt_dir()}\""
10 | ]
11 | }
12 |
13 | # Placeholder (no-op); might use this in the future.
14 | after_hook "after_hook" {
15 | commands = ["apply", "plan"]
16 | execute = ["/bin/bash", "-c", ":"]
17 | run_on_error = true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/root.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/infra-forge/terragrunt/root.hcl
--------------------------------------------------------------------------------
/examples/infra-forge/terragrunt/terragrunt.hcl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/examples/infra-forge/terragrunt/terragrunt.hcl
--------------------------------------------------------------------------------
/examples/templates/eks/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: # e.g., "prod"
3 | default_aws_region: # e.g., "eu-west-1"
4 | aws_account_id: # e.g., "123456789012"
5 |
--------------------------------------------------------------------------------
/examples/templates/eks/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: # e.g., "DevOps Team"
3 | product_name: # e.g., "Internal Platform"
4 | project_name: # e.g., "intplat"
5 | aws_account_prefix: # e.g., "intplat-ops"
6 | git_org: # e.g., "my-org"
7 | group_email: # e.g., "devops@example.com"
8 |
--------------------------------------------------------------------------------
/examples/templates/eks/eks/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | cluster_name: # e.g., "forge-euw1-dev"
3 | cluster_version: # e.g., "1.31"
4 | cluster_size:
5 | instance_type: # e.g., "m5.large"
6 | min_size: # e.g., 3
7 | max_size: # e.g., 10
8 | desired_size: # e.g., 3
9 | subnet_ids:
10 | - # e.g., "subnet-0abc1234def567890"
11 | - # e.g., "subnet-0123456789abcdef0"
12 | vpc_id: # e.g., "vpc-0abc1234def567890"
13 | cluster_ami_filter:
14 | - # e.g., "EKS1.31Ubuntu22-amd64-hvm-*"
15 | cluster_ami_owners:
16 | - # e.g., "123456789012"
17 |
--------------------------------------------------------------------------------
/examples/templates/extras/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: # e.g., "prod"
3 | default_aws_region: # e.g., "eu-west-1"
4 | aws_account_id: # e.g., "123456789012"
5 |
--------------------------------------------------------------------------------
/examples/templates/extras/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: # e.g., "DevOps Team"
3 | product_name: # e.g., "Internal Platform"
4 | project_name: # e.g., "intplat"
5 | aws_account_prefix: # e.g., "intplat-ops"
6 | git_org: # e.g., "my-org"
7 | group_email: # e.g., "devops@example.com"
8 |
--------------------------------------------------------------------------------
/examples/templates/extras/cloud_custodian/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | forge_role_arn: # e.g., arn:aws:iam::123456789012:role/role_for_forge_runners
3 |
--------------------------------------------------------------------------------
/examples/templates/extras/ecr/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | repositories:
3 | - repo: # e.g., pre-commit
4 | mutability: # e.g., MUTABLE or IMMUTABLE
5 | scan_on_push: # true or false
6 |
--------------------------------------------------------------------------------
/examples/templates/extras/forge_subscription/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | forge:
3 | runner_roles:
4 | - # e.g., arn:aws:iam::123456789012:role/my-runner-role-1
5 | - # e.g., arn:aws:iam::123456789012:role/my-runner-role-2
6 |
7 | ecr_repositories:
8 | names:
9 | - # e.g., pre-commit
10 | ecr_access_account_ids:
11 | - # e.g., "123456789013"
12 | regions:
13 | - # e.g., eu-west-1
14 |
--------------------------------------------------------------------------------
/examples/templates/splunk/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: # e.g., "prod"
3 | default_aws_region: # e.g., "eu-west-1"
4 | aws_account_id: # e.g., "123456789012"
5 | splunk:
6 | splunk_api_url: # e.g., "https://api.us0.signalfx.com"
7 | splunk_ingest_url: # e.g., "https://ingest.us0.signalfx.com"
8 | splunk_organization_id: # e.g., "ORG1234567890"
9 | data_manager_template_url: # e.g., "https://o11y-public.s3.amazonaws.com/aws-cloudformation-templates/release/template_all_features_regional.yaml"
10 | splunk_cloud: # e.g., "https://mycompany.splunkcloud.com"
11 |
--------------------------------------------------------------------------------
/examples/templates/splunk/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: # e.g., "DevOps Team"
3 | product_name: # e.g., "Internal Platform"
4 | project_name: # e.g., "intplat"
5 | aws_account_prefix: # e.g., "intplat-ops"
6 | git_org: # e.g., "my-org"
7 | group_email: # e.g., "devops@example.com"
8 |
--------------------------------------------------------------------------------
/examples/templates/splunk/splunk_cloud_data_manager_common/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | splunk_cloud: # e.g., https://mycompany.splunkcloud.com
3 |
--------------------------------------------------------------------------------
/examples/templates/splunk/splunk_o11y_aws_integration/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | splunk_ingest_url: # e.g., https://ingest.us0.signalfx.com
3 | template_url: # e.g., https://o11y-public.s3.amazonaws.com/aws-cloudformation-templates/release/template_all_features_regional.yaml
4 |
--------------------------------------------------------------------------------
/examples/templates/splunk/splunk_o11y_aws_integration_common/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | integration_name: # e.g., forge-prod
3 | integration_regions:
4 | - # e.g., eu-west-1
5 | splunk_api_url: # e.g., https://api.us0.signalfx.com
6 | splunk_organization_id: # e.g., ORG1234567890
7 |
--------------------------------------------------------------------------------
/examples/templates/splunk/splunk_otel_eks/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | cluster_name: # e.g., forge-euw1-prod
3 |
4 | splunk_otel_collector:
5 | splunk_observability_realm: # e.g., us0
6 | splunk_platform_endpoint: # e.g., https://http-inputs-mycompany.splunkcloud.com:443/services/collector
7 | splunk_platform_index: # e.g., forge-prod-index
8 | gateway: # true or false
9 | splunk_observability_profiling: # true or false
10 | environment: # e.g., prod
11 | discovery: # true or false
12 |
--------------------------------------------------------------------------------
/examples/templates/splunk/splunk_secrets/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | replica_regions:
3 | - # e.g., eu-west-1
4 | - # e.g., us-east-1
5 |
--------------------------------------------------------------------------------
/examples/templates/tenant/_environment_wide_settings/_environment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | env: # e.g., "prod"
3 | default_aws_region: # e.g., "eu-west-1"
4 | runner_group_name_suffix: # e.g., "cicd-forge"
5 | aws_account_id: # e.g., "123456789012"
6 |
--------------------------------------------------------------------------------
/examples/templates/tenant/_global_settings/_global.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | team_name: # e.g., "DevOps Team"
3 | product_name: # e.g., "Internal Platform"
4 | project_name: # e.g., "intplat"
5 | aws_account_prefix: # e.g., "intplat-ops"
6 | git_org: # e.g., "my-org"
7 | group_email: # e.g., "devops@example.com"
8 |
--------------------------------------------------------------------------------
/examples/templates/tenant/_vpc_wide_settings/_vpc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | vpc_alias: # e.g., "sl"
3 | lambda_subnet_ids:
4 | - # e.g., "subnet-0abc1234def567890"
5 | -
6 | vpc_id: # e.g., "vpc-0abc1234def567890"
7 | subnet_ids:
8 | - # e.g., "subnet-0abc1234def567890"
9 | - # e.g., "subnet-0123456789abcdef0"
10 | cluster_name: # e.g., "forge-euw1-prod"
11 |
--------------------------------------------------------------------------------
/examples/templates/tenant/tenant/config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | gh_config:
3 | ghes_url:
4 | ghes_org:
5 | tenant:
6 | iam_roles_to_assume:
7 | - arn:aws:iam:::role/
8 | ecr_registries:
9 | - .dkr.ecr..amazonaws.com
10 | ec2_runner_specs:
11 | :
12 | ami_name:
13 | ami_owner:
14 | ami_kms_key_arn:
15 | max_instances:
16 | instance_types:
17 | -
18 | pool_config:
19 | - size:
20 | schedule_expression:
21 | schedule_expression_timezone:
22 | arc_runner_specs:
23 | :
24 | runner_size:
25 | max_runners:
26 | min_runners:
27 | scale_set_name:
28 | scale_set_type:
29 | container_actions_runner:
30 | container_requests_cpu:
31 | container_requests_memory:
32 | container_limits_cpu:
33 | container_limits_memory:
34 |
--------------------------------------------------------------------------------
/modules/core/arc/data.tf:
--------------------------------------------------------------------------------
1 | data "aws_eks_cluster" "cluster" {
2 | name = var.eks_cluster_name
3 | }
4 |
5 | data "aws_eks_cluster_auth" "cluster" {
6 | name = var.eks_cluster_name
7 | }
8 |
9 | data "aws_subnet" "eks_subnets" {
10 | for_each = toset(data.aws_eks_cluster.cluster.vpc_config[0].subnet_ids)
11 | id = each.value
12 | }
13 |
--------------------------------------------------------------------------------
/modules/core/arc/outputs.tf:
--------------------------------------------------------------------------------
1 | output "runners_map" {
2 | value = { for key, value in module.scale_sets : key => value }
3 | }
4 |
5 | output "subnet_cidr_blocks" {
6 | value = { for id, subnet in data.aws_subnet.eks_subnets : id => subnet.cidr_block }
7 | }
8 |
--------------------------------------------------------------------------------
/modules/core/arc/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.tags
9 | }
10 | }
11 |
12 | provider "kubernetes" {
13 | host = data.aws_eks_cluster.cluster.endpoint
14 | cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
15 | token = data.aws_eks_cluster_auth.cluster.token
16 | }
17 |
18 | provider "helm" {
19 | kubernetes {
20 | host = data.aws_eks_cluster.cluster.endpoint
21 | cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
22 | token = data.aws_eks_cluster_auth.cluster.token
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set/locals.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | github_config_url = var.ghes_url != "" ? "${var.ghes_url}/${var.ghes_org}" : "https://github.com/${var.ghes_org}"
3 | }
4 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set/outputs.tf:
--------------------------------------------------------------------------------
1 | output "runner_role_arn" {
2 | value = aws_iam_role.runner_role.arn
3 | }
4 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set/role.tf:
--------------------------------------------------------------------------------
1 | data "aws_iam_policy_document" "assume_role" {
2 | statement {
3 | effect = "Allow"
4 |
5 | principals {
6 | type = "Service"
7 | identifiers = ["pods.eks.amazonaws.com"]
8 | }
9 |
10 | actions = [
11 | "sts:AssumeRole",
12 | "sts:TagSession"
13 | ]
14 | }
15 | }
16 |
17 | resource "aws_iam_role" "runner_role" {
18 | name = var.iam_role_name
19 | assume_role_policy = data.aws_iam_policy_document.assume_role.json
20 |
21 | tags = var.tags
22 | tags_all = var.tags
23 | }
24 |
25 | resource "aws_iam_role_policy_attachment" "runner_role_policy_attachment" {
26 | count = length(var.runner_iam_role_managed_policy_arns)
27 | role = aws_iam_role.runner_role.name
28 | policy_arn = element(var.runner_iam_role_managed_policy_arns, count.index)
29 | }
30 |
31 | resource "kubernetes_service_account" "runner_sa" {
32 | metadata {
33 | name = var.service_account
34 | namespace = var.namespace
35 | }
36 | }
37 |
38 | resource "aws_eks_pod_identity_association" "eks_pod_identity" {
39 | cluster_name = var.cluster_name
40 | namespace = var.namespace
41 | service_account = var.service_account
42 | role_arn = aws_iam_role.runner_role.arn
43 |
44 | tags = var.tags
45 | }
46 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | aws = {
4 | source = "hashicorp/aws"
5 | version = ">= 5.90"
6 | }
7 | helm = {
8 | source = "hashicorp/helm"
9 | version = ">= 2.17.0"
10 | }
11 | kubernetes = {
12 | source = "hashicorp/kubernetes"
13 | version = ">= 2.36.0"
14 | }
15 | }
16 |
17 | # OpenTofu version.
18 | required_version = ">= 1.9.1"
19 | }
20 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set_controller/helm.tf:
--------------------------------------------------------------------------------
1 | resource "helm_release" "gha_runner_scale_set_controller" {
2 | name = var.release_name
3 | namespace = var.namespace
4 | chart = var.chart_name
5 | version = var.chart_version
6 |
7 | create_namespace = true
8 |
9 | values = [
10 | templatefile(
11 | "${path.module}/template_files/values.yml.tftpl",
12 | {
13 | name = var.controller_config.name
14 | namespace = var.namespace
15 | }
16 | )
17 | ]
18 |
19 | upgrade_install = true
20 | cleanup_on_fail = true
21 | timeout = 1200
22 |
23 | depends_on = [kubernetes_secret.github_app]
24 | }
25 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set_controller/secret.tf:
--------------------------------------------------------------------------------
1 | resource "kubernetes_namespace" "controller_namespace" {
2 | metadata {
3 | name = var.namespace
4 | }
5 | }
6 |
7 | resource "kubernetes_secret" "github_app" {
8 |
9 | metadata {
10 | name = var.release_name
11 | namespace = var.namespace
12 | }
13 |
14 | type = "generic"
15 |
16 | data = {
17 | github_app_id = var.github_app.id
18 | github_app_installation_id = var.github_app.installation_id
19 | github_app_private_key = base64decode(var.github_app.key_base64)
20 | }
21 | lifecycle {
22 | create_before_destroy = true
23 | }
24 | depends_on = [kubernetes_namespace.controller_namespace]
25 | }
26 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set_controller/variables.tf:
--------------------------------------------------------------------------------
1 | variable "chart_name" {
2 | description = "Chart URL for the Helm chart"
3 | type = string
4 | }
5 |
6 | variable "chart_version" {
7 | description = "Chart version for the Helm chart"
8 | type = string
9 | }
10 |
11 | variable "namespace" {
12 | description = "Namespace for chart installation"
13 | type = string
14 | }
15 |
16 | variable "release_name" {
17 | description = "Name of the Helm release"
18 | type = string
19 | }
20 |
21 | variable "controller_config" {
22 | type = object({
23 | name = string
24 | })
25 | }
26 |
27 | variable "github_app" {
28 | description = "GitHub App configuration"
29 | type = object({
30 | key_base64 = string
31 | id = string
32 | installation_id = string
33 | })
34 | }
35 |
--------------------------------------------------------------------------------
/modules/core/arc/scale_set_controller/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | aws = {
4 | source = "hashicorp/aws"
5 | version = ">= 5.90"
6 | }
7 | helm = {
8 | source = "hashicorp/helm"
9 | version = ">= 2.17.0"
10 | }
11 | kubernetes = {
12 | source = "hashicorp/kubernetes"
13 | version = ">= 2.36.0"
14 | }
15 | }
16 |
17 | # OpenTofu version.
18 | required_version = ">= 1.9.1"
19 | }
20 |
--------------------------------------------------------------------------------
/modules/core/arc/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | aws = {
4 | source = "hashicorp/aws"
5 | version = ">= 5.90"
6 | }
7 | helm = {
8 | source = "hashicorp/helm"
9 | version = ">= 2.17.0"
10 | }
11 | kubernetes = {
12 | source = "hashicorp/kubernetes"
13 | version = ">= 2.36.0"
14 | }
15 | }
16 |
17 | # OpenTofu version.
18 | required_version = ">= 1.9.1"
19 | }
20 |
--------------------------------------------------------------------------------
/modules/infra/ami_policy/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Re-use what's provided by the root module.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/ami_policy/global_policy.tf:
--------------------------------------------------------------------------------
1 | # Always encrypt new EBS volumes (e.g. AMI images) by default. Packer is not
2 | # able to override/disable this setting.
3 | resource "aws_ebs_encryption_by_default" "gpol_encrypt_ebs" {
4 | # We'll re-enable this when we have a custom KMS key prepared.
5 | enabled = false
6 | }
7 |
--------------------------------------------------------------------------------
/modules/infra/ami_policy/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/modules/infra/ami_policy/outputs.tf
--------------------------------------------------------------------------------
/modules/infra/ami_policy/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/ami_policy/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/ami_policy/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS profile to use."
3 | type = string
4 | }
5 |
6 | variable "aws_region" {
7 | description = "Assuming single region for now."
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | type = map(string)
13 | description = "A map of tags to apply to resources."
14 | }
15 |
16 | variable "default_tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 |
--------------------------------------------------------------------------------
/modules/infra/ami_policy/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/ami_sharing/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/ami_sharing/main.tf:
--------------------------------------------------------------------------------
1 | # Fetch all matching AMIs
2 | data "aws_ami_ids" "ami_filter" {
3 | owners = ["self"]
4 |
5 | filter {
6 | name = "name"
7 | values = [var.ami_name_filter]
8 | }
9 | }
10 |
11 | # Create all AMI-account pairs
12 | locals {
13 | ami_account_pairs = flatten([
14 | for ami in data.aws_ami_ids.ami_filter.ids : [
15 | for account in var.account_ids : {
16 | ami_id = ami
17 | account = account
18 | }
19 | ]
20 | ])
21 | }
22 |
23 | # Share AMIs with accounts
24 | resource "aws_ami_launch_permission" "share_amis" {
25 | for_each = { for pair in local.ami_account_pairs : "${pair.ami_id}-${pair.account}" => pair }
26 |
27 | image_id = each.value.ami_id
28 | account_id = each.value.account
29 | }
30 |
--------------------------------------------------------------------------------
/modules/infra/ami_sharing/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/ami_sharing/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS profile to use."
3 | type = string
4 | }
5 |
6 | variable "aws_region" {
7 | description = "Assuming single region for now."
8 | type = string
9 | }
10 |
11 | variable "default_tags" {
12 | type = map(string)
13 | description = "A map of tags to apply to resources."
14 | }
15 |
16 | variable "account_ids" {
17 | description = "List of AWS accounts to share AMIs with"
18 | type = list(string)
19 | }
20 |
21 | variable "ami_name_filter" {
22 | description = "AMI name filter to use to find AMIs to share"
23 | type = string
24 | }
25 |
--------------------------------------------------------------------------------
/modules/infra/ami_sharing/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/billing/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/billing/main.tf:
--------------------------------------------------------------------------------
1 | # SNS topic and associated policy-related functionality. This allows the budget
2 | # resource to make use of this topic (i.e. publish alerts).
3 | resource "aws_sns_topic" "account_billing_alarm_topic" {
4 | name = "account-billing-alarm-topic"
5 | }
6 |
7 | # Ensure topic subscribers are emailed on notifications.
8 | resource "aws_sns_topic_subscription" "email-target" {
9 | topic_arn = aws_sns_topic.account_billing_alarm_topic.arn
10 | protocol = "email"
11 | endpoint = var.group_email
12 | }
13 |
14 | # Map the policy to the topic.
15 | resource "aws_sns_topic_policy" "account_billing_alarm_policy" {
16 | arn = aws_sns_topic.account_billing_alarm_topic.arn
17 | policy = data.aws_iam_policy_document.sns_topic_policy.json
18 | }
19 |
20 | # Security policy for the topic.
21 | data "aws_iam_policy_document" "sns_topic_policy" {
22 | statement {
23 | sid = "AWSBudgetsSNSPublishingPermissions"
24 | effect = "Allow"
25 |
26 | actions = [
27 | "SNS:Receive",
28 | "SNS:Publish"
29 | ]
30 |
31 | principals {
32 | type = "Service"
33 | identifiers = ["budgets.amazonaws.com"]
34 | }
35 |
36 | resources = [
37 | aws_sns_topic.account_billing_alarm_topic.arn
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/modules/infra/billing/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/billing/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS profile to use."
3 | type = string
4 | }
5 |
6 | variable "aws_region" {
7 | description = "Assuming single region for now."
8 | type = string
9 | }
10 |
11 | variable "group_email" {
12 | type = string
13 | description = "Group email (for contacting owners in case of security/compliance issues)."
14 | }
15 |
16 | variable "default_tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 |
--------------------------------------------------------------------------------
/modules/infra/billing/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/budget/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/budget/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/budget/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_budget" {
2 | description = "Defines the budget and billing limits for AWS accounts and services."
3 | type = object(
4 | {
5 | per_account = string
6 | services = map(
7 | object(
8 | {
9 | budget_limit = string
10 | }
11 | )
12 | )
13 | }
14 | )
15 | }
16 |
17 | variable "aws_account_id" {
18 | description = "AWS account ID associated with the infra/backend."
19 | type = string
20 | }
21 |
22 | variable "aws_profile" {
23 | description = "AWS profile to use."
24 | type = string
25 | }
26 |
27 | variable "aws_region" {
28 | description = "Assuming single region for now."
29 | type = string
30 | }
31 |
32 | variable "default_tags" {
33 | type = map(string)
34 | description = "A map of tags to apply to resources."
35 | }
36 |
--------------------------------------------------------------------------------
/modules/infra/budget/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/cloud_custodian/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/cloud_custodian/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/cloud_custodian/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/cloud_custodian/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS profile to use."
3 | type = string
4 | }
5 |
6 | variable "aws_region" {
7 | description = "Assuming single region for now."
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | type = map(string)
13 | description = "A map of tags to apply to resources."
14 | }
15 |
16 | variable "default_tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 | variable "forge_role_arn" {
21 | type = string
22 | description = "ARN of the role to assume for Cloud Custodian."
23 | }
24 |
--------------------------------------------------------------------------------
/modules/infra/cloud_custodian/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/cloud_formation/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/cloud_formation/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/modules/infra/cloud_formation/outputs.tf
--------------------------------------------------------------------------------
/modules/infra/cloud_formation/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/cloud_formation/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/cloud_formation/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_account_id" {
2 | description = "AWS account ID associated with the infra/backend."
3 | type = string
4 | }
5 |
6 | variable "aws_profile" {
7 | type = string
8 | description = "AWS profile to use."
9 | }
10 |
11 | variable "aws_region" {
12 | type = string
13 | description = "Default AWS region."
14 | }
15 |
16 | variable "tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 |
21 | variable "default_tags" {
22 | type = map(string)
23 | description = "A map of tags to apply to resources."
24 | }
25 |
--------------------------------------------------------------------------------
/modules/infra/cloud_formation/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/ecr/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/ecr/outputs.tf:
--------------------------------------------------------------------------------
1 | output "ops_container_repository_names" {
2 | value = [for registry in aws_ecr_repository.ops_container_repository : registry.name]
3 | }
4 |
--------------------------------------------------------------------------------
/modules/infra/ecr/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/ecr/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/ecr/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | type = string
3 | description = "AWS profile to use."
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Default AWS region."
9 | }
10 |
11 | variable "tags" {
12 | type = map(string)
13 | description = "A map of tags to apply to resources."
14 | }
15 |
16 | variable "default_tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 |
21 | variable "repositories" {
22 | type = list(object({
23 | repo = string
24 | mutability = string
25 | scan_on_push = bool
26 | }))
27 | description = "A list of ECR repositories to create. Mutability must be 'MUTABLE' or 'IMMUTABLE'."
28 |
29 | validation {
30 | condition = alltrue([
31 | for r in var.repositories : contains(["MUTABLE", "IMMUTABLE"], r.mutability)
32 | ])
33 | error_message = "Each repository 'mutability' must be either 'MUTABLE' or 'IMMUTABLE'."
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/modules/infra/ecr/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/eks/addons.tf:
--------------------------------------------------------------------------------
1 | # Fetch the most recent version of the aws-ebs-csi-driver
2 | data "aws_eks_addon_version" "aws_ebs_csi_driver" {
3 | addon_name = "aws-ebs-csi-driver"
4 | kubernetes_version = var.cluster_version
5 | }
6 |
7 | # Fetch the most recent version of the eks-pod-identity-agent
8 | data "aws_eks_addon_version" "eks_pod_identity_agent" {
9 | addon_name = "eks-pod-identity-agent"
10 | kubernetes_version = var.cluster_version
11 | }
12 |
13 | resource "aws_eks_addon" "aws_ebs_csi_driver" {
14 | cluster_name = var.cluster_name
15 | addon_name = "aws-ebs-csi-driver"
16 | addon_version = data.aws_eks_addon_version.aws_ebs_csi_driver.version
17 | service_account_role_arn = module.ebs_csi_irsa_role.iam_role_arn
18 | timeouts {
19 | create = "60m"
20 | update = "60m"
21 | delete = "60m"
22 | }
23 |
24 | depends_on = [module.self_managed_node_group]
25 | }
26 |
27 | resource "aws_eks_addon" "eks_pod_identity_agent" {
28 | cluster_name = var.cluster_name
29 | addon_name = "eks-pod-identity-agent"
30 | addon_version = data.aws_eks_addon_version.eks_pod_identity_agent.version
31 | timeouts {
32 | create = "60m"
33 | update = "60m"
34 | delete = "60m"
35 | }
36 |
37 | configuration_values = jsonencode({
38 | agent = {
39 | additionalArgs = {
40 | "-b" : "169.254.170.23"
41 | }
42 | }
43 | })
44 |
45 | depends_on = [module.self_managed_node_group]
46 | }
47 |
--------------------------------------------------------------------------------
/modules/infra/eks/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/eks/calico.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "apply_tigera_operator" {
2 | provisioner "local-exec" {
3 | command = "kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/tigera-operator.yaml"
4 | }
5 |
6 | depends_on = [
7 | null_resource.update_kubeconfig,
8 | ]
9 | }
10 |
11 | resource "null_resource" "create_calico_installation" {
12 | provisioner "local-exec" {
13 | command = < pair
35 | }
36 | provider = aws.by_region[each.value.region]
37 |
38 | repository = each.value.name
39 | policy = data.aws_iam_policy_document.ecr_repository_policy.json
40 | }
41 |
--------------------------------------------------------------------------------
/modules/infra/forge_subscription/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/modules/infra/forge_subscription/outputs.tf
--------------------------------------------------------------------------------
/modules/infra/forge_subscription/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
12 | provider "aws" {
13 | alias = "by_region"
14 | # supported by opentofu >= 1.9.0
15 | for_each = toset(var.forge.ecr_repositories.regions)
16 | profile = var.aws_profile
17 | region = each.key
18 |
19 | # Required, as per security guidelines.
20 | default_tags {
21 | tags = var.default_tags
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/modules/infra/forge_subscription/roles.tf:
--------------------------------------------------------------------------------
1 | # Role assumed by Forge Runners
2 | data "aws_iam_policy_document" "assume_role_for_forge_runners" {
3 | # Allows us to access S3, SecretsManager immediately when we SSH into a runner VM.
4 | statement {
5 | actions = [
6 | "sts:AssumeRole",
7 | ]
8 | principals {
9 | type = "Service"
10 | identifiers = [
11 | "ec2.amazonaws.com",
12 | "s3.amazonaws.com",
13 | ]
14 | }
15 | }
16 |
17 | # Allow GH runners to assume dedicated role.
18 | statement {
19 | effect = "Allow"
20 | actions = [
21 | "sts:AssumeRole",
22 | "sts:TagSession",
23 | ]
24 | principals {
25 | type = "AWS"
26 | identifiers = var.forge.runner_roles
27 | }
28 | }
29 | }
30 |
31 | # Dedicated role. Allow it to be assumed.
32 | resource "aws_iam_role" "role_for_forge_runners" {
33 | name = "role_for_forge_runners"
34 | assume_role_policy = data.aws_iam_policy_document.assume_role_for_forge_runners.json
35 | max_session_duration = 21600 # Allow role to last for up to 6 hours.
36 | tags_all = local.all_security_tags
37 | }
38 |
--------------------------------------------------------------------------------
/modules/infra/forge_subscription/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/forge_subscription/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | type = string
3 | description = "AWS profile to use."
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Default AWS region."
9 | }
10 |
11 | variable "forge" {
12 | type = object({
13 | runner_roles = list(string)
14 | ecr_repositories = object({
15 | names = list(string)
16 | ecr_access_account_ids = list(string)
17 | regions = list(string)
18 | })
19 | })
20 | description = "Configuration for Forge runners."
21 | default = {
22 | runner_roles = []
23 | ecr_repositories = {
24 | names = []
25 | ecr_access_account_ids = []
26 | regions = []
27 | }
28 | }
29 | }
30 |
31 | variable "tags" {
32 | type = map(string)
33 | description = "A map of tags to apply to resources."
34 | }
35 |
36 | variable "default_tags" {
37 | type = map(string)
38 | description = "A map of tags to apply to resources."
39 | }
40 |
--------------------------------------------------------------------------------
/modules/infra/forge_subscription/version.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## Requirements
3 |
4 | | Name | Version |
5 | |------|---------|
6 | | [terraform](#requirement\_terraform) | >= 1.9.1 |
7 | | [aws](#requirement\_aws) | ~> 5.90 |
8 |
9 | ## Providers
10 |
11 | | Name | Version |
12 | |------|---------|
13 | | [aws](#provider\_aws) | 5.99.1 |
14 |
15 | ## Modules
16 |
17 | No modules.
18 |
19 | ## Resources
20 |
21 | | Name | Type |
22 | |------|------|
23 | | [aws_account_region.enabled_regions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/account_region) | resource |
24 |
25 | ## Inputs
26 |
27 | | Name | Description | Type | Default | Required |
28 | |------|-------------|------|---------|:--------:|
29 | | [aws\_profile](#input\_aws\_profile) | AWS profile to use. | `string` | n/a | yes |
30 | | [aws\_region](#input\_aws\_region) | Default AWS region. | `string` | n/a | yes |
31 | | [default\_tags](#input\_default\_tags) | A map of tags to apply to resources. | `map(string)` | n/a | yes |
32 | | [opt\_in\_regions](#input\_opt\_in\_regions) | List of opt-in AWS regions to enable | `list(string)` | `[]` | no |
33 |
34 | ## Outputs
35 |
36 | No outputs.
37 |
38 |
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/main.tf:
--------------------------------------------------------------------------------
1 | resource "aws_account_region" "enabled_regions" {
2 | for_each = { for region in var.opt_in_regions : region => region }
3 | region_name = each.key
4 | enabled = true
5 | }
6 |
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/modules/infra/opt_in_regions/outputs.tf
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opt_in_regions" {
2 | description = "List of opt-in AWS regions to enable"
3 | type = list(string)
4 | default = []
5 | }
6 | variable "aws_profile" {
7 | type = string
8 | description = "AWS profile to use."
9 | }
10 |
11 | variable "aws_region" {
12 | type = string
13 | description = "Default AWS region."
14 | }
15 |
16 |
17 | variable "default_tags" {
18 | type = map(string)
19 | description = "A map of tags to apply to resources."
20 | }
21 |
--------------------------------------------------------------------------------
/modules/infra/opt_in_regions/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## Requirements
3 |
4 | | Name | Version |
5 | |------|---------|
6 | | [terraform](#requirement\_terraform) | >= 1.9.1 |
7 | | [aws](#requirement\_aws) | ~> 5.90 |
8 |
9 | ## Providers
10 |
11 | | Name | Version |
12 | |------|---------|
13 | | [aws](#provider\_aws) | 5.99.1 |
14 |
15 | ## Modules
16 |
17 | No modules.
18 |
19 | ## Resources
20 |
21 | | Name | Type |
22 | |------|------|
23 | | [aws_iam_service_linked_role.spot](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_service_linked_role) | resource |
24 |
25 | ## Inputs
26 |
27 | | Name | Description | Type | Default | Required |
28 | |------|-------------|------|---------|:--------:|
29 | | [aws\_profile](#input\_aws\_profile) | AWS profile to use. | `string` | n/a | yes |
30 | | [aws\_region](#input\_aws\_region) | Default AWS region. | `string` | n/a | yes |
31 | | [default\_tags](#input\_default\_tags) | A map of tags to apply to resources. | `map(string)` | n/a | yes |
32 | | [tags](#input\_tags) | A map of tags to apply to resources. | `map(string)` | n/a | yes |
33 |
34 | ## Outputs
35 |
36 | No outputs.
37 |
38 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/main.tf:
--------------------------------------------------------------------------------
1 | resource "aws_iam_service_linked_role" "spot" {
2 | aws_service_name = "spot.amazonaws.com"
3 | tags_all = local.all_security_tags
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS profile to use."
3 | type = string
4 | }
5 |
6 | variable "aws_region" {
7 | description = "Default AWS region."
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | type = map(string)
13 | description = "A map of tags to apply to resources."
14 | }
15 |
16 | variable "default_tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 |
--------------------------------------------------------------------------------
/modules/infra/service_linked_roles/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/infra/storage/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/storage/outputs.tf:
--------------------------------------------------------------------------------
1 | output "s3_short_term_settings" {
2 | value = {
3 | "path" = "${aws_s3_bucket.s3_short_term.id}/cicd_artifacts"
4 | "arn" = aws_s3_bucket.s3_short_term.arn
5 | "suffix" = "/cicd_artifacts"
6 | }
7 | description = "Path to use for short-term storage of artifacts in S3."
8 | }
9 |
10 | output "s3_long_term_settings" {
11 | value = {
12 | "path" = "${aws_s3_bucket.s3_long_term.id}/cicd_artifacts"
13 | "arn" = aws_s3_bucket.s3_long_term.arn
14 | "suffix" = "/cicd_artifacts"
15 | }
16 | description = "Path to use for long-term storage of artifacts in S3."
17 | }
18 |
--------------------------------------------------------------------------------
/modules/infra/storage/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/infra/storage/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/infra/storage/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_account_id" {
2 | type = string
3 | description = "AWS account ID (not SL AWS account ID) associated with the infra/backend."
4 | }
5 |
6 | variable "aws_profile" {
7 | description = "AWS profile to use."
8 | type = string
9 | }
10 |
11 | variable "aws_region" {
12 | description = "Default AWS region."
13 | type = string
14 | }
15 |
16 | variable "tags" {
17 | type = map(string)
18 | description = "A map of tags to apply to resources."
19 | }
20 |
21 | variable "default_tags" {
22 | type = map(string)
23 | description = "A map of tags to apply to resources."
24 | }
25 |
--------------------------------------------------------------------------------
/modules/infra/storage/versions.tf:
--------------------------------------------------------------------------------
1 | # Needed to interact with in-house/on-prem SLVM resources.
2 | terraform {
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.80"
7 | }
8 | }
9 | # OpenTofu version.
10 | required_version = ">= 1.9.0"
11 | }
12 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Re-use what's provided by the root module.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/dashboard_jobs.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | job_definition = templatefile(
3 | "${path.module}/template_files/ci_jobs.json.tftpl",
4 | {
5 | splunk_index = var.splunk_conf.index
6 | }
7 | )
8 | job_eai_data = <
10 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 | EOF
26 | }
27 |
28 | resource "splunk_data_ui_views" "ci_jobs" {
29 | name = "ci_jobs"
30 | eai_data = local.job_eai_data
31 |
32 | acl {
33 | app = var.splunk_conf.acl.app
34 | owner = var.splunk_conf.acl.owner
35 | sharing = var.splunk_conf.acl.sharing
36 | read = var.splunk_conf.acl.read
37 | write = var.splunk_conf.acl.write
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/dashboard_tenant.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | tenant_definition = templatefile(
3 | "${path.module}/template_files/tenant.json.tftpl",
4 | {
5 | splunk_index = var.splunk_conf.index
6 | }
7 | )
8 | tenant_eai_data = <
10 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 | EOF
26 | }
27 |
28 | resource "splunk_data_ui_views" "tenant" {
29 | name = "tenant"
30 | eai_data = local.tenant_eai_data
31 |
32 | acl {
33 | app = var.splunk_conf.acl.app
34 | owner = var.splunk_conf.acl.owner
35 | sharing = var.splunk_conf.acl.sharing
36 | read = var.splunk_conf.acl.read
37 | write = var.splunk_conf.acl.write
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
12 | provider "splunk" {
13 | url = "${var.splunk_conf.splunk_cloud}:8089"
14 | auth_token = data.aws_secretsmanager_secret_version.secrets["splunk_cloud_api_token"].secret_string
15 | insecure_skip_verify = true
16 | }
17 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/secrets.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | ro_secrets = {
3 | splunk_cloud_api_token = {
4 | name = "/cicd/common/splunk_cloud_api_token"
5 | }
6 | }
7 | }
8 |
9 | data "aws_secretsmanager_secret" "secrets" {
10 | for_each = local.ro_secrets
11 | name = each.value.name
12 | }
13 |
14 | data "aws_secretsmanager_secret_version" "secrets" {
15 | for_each = data.aws_secretsmanager_secret.secrets
16 | secret_id = each.value.id
17 | }
18 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | type = string
3 | description = "AWS profile (i.e. generated via 'sl aws session generate') to use."
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Assuming single region for now."
9 | }
10 |
11 | variable "default_tags" {
12 | type = map(string)
13 | description = "A map of tags to apply to resources."
14 | }
15 |
16 | variable "splunk_conf" {
17 | type = object({
18 | splunk_cloud = string
19 | acl = object({
20 | app = string
21 | owner = string
22 | sharing = string
23 | read = list(string)
24 | write = list(string)
25 | })
26 | index = string
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_conf_shared/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | aws = {
4 | source = "hashicorp/aws"
5 | version = ">= 5.90"
6 | }
7 | splunk = {
8 | source = "splunk/splunk"
9 | version = ">= 1.4.30"
10 | }
11 | }
12 |
13 | # OpenTofu version.
14 | required_version = ">= 1.9.1"
15 | }
16 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/data_input/locals.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | name = "SplunkDMDataIngest-${random_uuid.splunk_input_uuid.result}"
3 |
4 | template_url = "https://${var.cloudformation_s3_config.bucket}.s3.amazonaws.com/${var.cloudformation_s3_config.key}${random_uuid.splunk_input_uuid.result}/template.json"
5 |
6 | tags = merge(
7 | var.tags_all,
8 | {
9 | SplunkDMVersion = data.external.splunk_dm_version.result["version"]
10 | }
11 | )
12 | tags_all = merge(
13 | var.tags_all,
14 | {
15 | SplunkDMVersion = data.external.splunk_dm_version.result["version"]
16 | }
17 | )
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/data_input/output.tf:
--------------------------------------------------------------------------------
1 |
2 | output "splunk_integration_name" {
3 | description = "The name of the Splunk integration CloudFormation stack."
4 | value = local.name
5 | }
6 |
7 | output "splunk_integration_template_url" {
8 | description = "The URL of the CloudFormation template for the Splunk integration."
9 | value = local.template_url
10 | }
11 |
12 | output "splunk_integration_tags" {
13 | description = "The tags applied to the Splunk integration CloudFormation stack."
14 | value = local.tags
15 | }
16 |
17 | output "splunk_integration_tags_all" {
18 | description = "All tags applied to the Splunk integration CloudFormation stack, including inherited tags."
19 | value = local.tags_all
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/data_input/s3_template.tf:
--------------------------------------------------------------------------------
1 | data "external" "ensure_template_file" {
2 | program = ["bash", "-c", <<-EOT
3 | FILE="/tmp/${random_uuid.splunk_input_uuid.result}_template.json"
4 | [ -f "$FILE" ] || echo '{}' > "$FILE"
5 | echo "{ \"md5\": \"$(md5sum $FILE | awk '{print $1}')\" }"
6 | EOT
7 | ]
8 | }
9 |
10 | resource "aws_s3_object" "cloudformation_template" {
11 | bucket = var.cloudformation_s3_config.bucket
12 | key = "${var.cloudformation_s3_config.key}${random_uuid.splunk_input_uuid.result}/template.json"
13 | source = "/tmp/${random_uuid.splunk_input_uuid.result}_template.json"
14 | etag = data.external.ensure_template_file.result["md5"]
15 |
16 | depends_on = [
17 | data.external.ensure_template_file,
18 | null_resource.create_integration,
19 | random_uuid.splunk_input_uuid,
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/data_input/secrets.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | secrets = {
3 | splunk_cloud_username = {
4 | name = "/cicd/common/splunk_cloud_username"
5 | }
6 | splunk_cloud_password = {
7 | name = "/cicd/common/splunk_cloud_password"
8 | }
9 | }
10 | }
11 |
12 | data "aws_secretsmanager_secret" "secrets" {
13 | for_each = local.secrets
14 | name = each.value.name
15 | }
16 |
17 | data "aws_secretsmanager_secret_version" "secrets" {
18 | for_each = data.aws_secretsmanager_secret.secrets
19 | secret_id = each.value.id
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/data_input/variables.tf:
--------------------------------------------------------------------------------
1 | variable "splunk_cloud" {
2 | type = string
3 | description = "Splunk Cloud endpoint."
4 | }
5 |
6 | variable "splunk_cloud_input_json" {
7 | type = string
8 | description = "Splunk Cloud input JSON."
9 | }
10 |
11 | variable "tags" {
12 | type = map(string)
13 | description = "Tags to apply to resources."
14 | }
15 |
16 | variable "tags_all" {
17 | type = map(string)
18 | description = "All Tags to apply to resources."
19 | }
20 |
21 | variable "cloudformation_s3_config" {
22 | type = object({
23 | bucket = string
24 | key = string
25 | })
26 | description = "S3 bucket for CloudFormation templates."
27 | }
28 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/data_input/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | random = {
9 | source = "hashicorp/random"
10 | version = "3.7.1"
11 | }
12 | external = {
13 | source = "hashicorp/external"
14 | version = "~> 2.3"
15 | }
16 | null = {
17 | source = "hashicorp/null"
18 | version = "~> 3.2"
19 | }
20 | local = {
21 | source = "hashicorp/local"
22 | version = "2.5.2"
23 | }
24 | time = {
25 | source = "hashicorp/time"
26 | version = "~> 0.13"
27 | }
28 | }
29 |
30 | # OpenTofu version.
31 | required_version = ">= 1.9.1"
32 | }
33 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/locals.tf:
--------------------------------------------------------------------------------
1 | locals {
2 |
3 | resource_tags = [
4 | for k, v in local.all_security_tags : {
5 | Key = k
6 | Value = v
7 | }
8 | ]
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/outputs.tf:
--------------------------------------------------------------------------------
1 | output "splunk_cloud_input_cloudwatch_logs_json" {
2 | description = "The Splunk Cloud input map."
3 | value = var.cloudwatch_log_groups_config.enabled ? local.splunk_cloud_input_cloudwatch_json : ""
4 | }
5 |
6 | output "splunk_cloud_input_security_metadata_json" {
7 | description = "The Splunk Cloud input map for security metadata."
8 | value = var.security_metadata_config.enabled ? local.splunk_cloud_input_security_metadata_json : ""
9 | }
10 |
11 | output "splunk_cloud_input_custom_logs_json" {
12 | description = "The Splunk Cloud input map for custom logs."
13 | value = var.custom_cloudwatch_log_groups_config.enabled ? local.splunk_cloud_input_custom_logs_json : ""
14 | }
15 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/providers.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = var.aws_region
3 | profile = var.aws_profile
4 |
5 | # Required, as per security guidelines.
6 | default_tags {
7 | tags = var.tags
8 | }
9 | }
10 |
11 | provider "aws" {
12 | alias = "cloudformation_s3_config"
13 | region = var.cloudformation_s3_config.region
14 | profile = var.aws_profile
15 |
16 | # Required, as per security guidelines.
17 | default_tags {
18 | tags = var.tags
19 | }
20 | }
21 |
22 | provider "aws" {
23 | alias = "by_region"
24 | # supported by opentofu >= 1.9.0
25 | for_each = toset(
26 | distinct(merge(
27 | var.security_metadata_config.enabled ? { security_metadata = var.security_metadata_config.regions } : {},
28 | var.cloudwatch_log_groups_config.enabled ? { cloudwatch_logs = var.cloudwatch_log_groups_config.regions } : {},
29 | var.custom_cloudwatch_log_groups_config.enabled ? { custom_cloudwatch_logs = [for v in var.custom_cloudwatch_log_groups_config.log_group_name_prefixes : v.region] } : {}
30 | ) != {} ? flatten(values(merge(
31 | var.security_metadata_config.enabled ? { security_metadata = var.security_metadata_config.regions } : {},
32 | var.cloudwatch_log_groups_config.enabled ? { cloudwatch_logs = var.cloudwatch_log_groups_config.regions } : {},
33 | var.custom_cloudwatch_log_groups_config.enabled ? { custom_cloudwatch_logs = [for v in var.custom_cloudwatch_log_groups_config.log_group_name_prefixes : v.region] } : {}
34 | ))) : [var.aws_region])
35 | )
36 | profile = var.aws_profile
37 | region = each.key
38 |
39 | default_tags {
40 | tags = var.tags
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | random = {
9 | source = "hashicorp/random"
10 | version = "3.7.1"
11 | }
12 | external = {
13 | source = "hashicorp/external"
14 | version = "~> 2.3"
15 | }
16 | null = {
17 | source = "hashicorp/null"
18 | version = "~> 3.2"
19 | }
20 | local = {
21 | source = "hashicorp/local"
22 | version = "2.5.2"
23 | }
24 | time = {
25 | source = "hashicorp/time"
26 | version = "~> 0.13"
27 | }
28 | }
29 |
30 | # OpenTofu version.
31 | required_version = ">= 1.9.1"
32 | }
33 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager_common/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager_common/providers.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = var.aws_region
3 | profile = var.aws_profile
4 |
5 | # Required, as per security guidelines.
6 | default_tags {
7 | tags = merge(var.default_tags, )
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager_common/secrets.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | secrets = {
3 | splunk_cloud_username = {
4 | name = "/cicd/common/splunk_cloud_username"
5 | }
6 | splunk_cloud_password = {
7 | name = "/cicd/common/splunk_cloud_password"
8 | }
9 | }
10 | }
11 |
12 | data "aws_secretsmanager_secret" "secrets" {
13 | for_each = local.secrets
14 | name = each.value.name
15 | }
16 |
17 | data "aws_secretsmanager_secret_version" "secrets" {
18 | for_each = data.aws_secretsmanager_secret.secrets
19 | secret_id = each.value.id
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager_common/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager_common/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_account_id" {
2 | description = "AWS account ID (not SL AWS account ID) associated with the infra/backend."
3 | type = string
4 | }
5 |
6 | variable "aws_profile" {
7 | type = string
8 | description = "AWS profile (i.e., generated via 'sl aws session generate') to use."
9 | }
10 |
11 | variable "aws_region" {
12 | type = string
13 | description = "Default AWS region."
14 | }
15 | variable "splunk_cloud" {
16 | type = string
17 | description = "Splunk Cloud endpoint."
18 | }
19 |
20 | variable "tags" {
21 | type = map(string)
22 | description = "A map of tags to apply to resources."
23 | }
24 |
25 | variable "default_tags" {
26 | type = map(string)
27 | description = "A map of tags to apply to resources."
28 | }
29 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_cloud_data_manager_common/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | external = {
9 | source = "hashicorp/external"
10 | version = "~> 2.3"
11 | }
12 | }
13 |
14 | # OpenTofu version.
15 | required_version = ">= 1.9.1"
16 | }
17 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/cf.tf:
--------------------------------------------------------------------------------
1 | resource "aws_cloudformation_stack" "splunk_integration" {
2 | name = "splunk-integration"
3 |
4 | parameters = {
5 | SplunkAccessToken = data.aws_secretsmanager_secret_version.secrets["splunk_access_ingest_token"].secret_string
6 | SplunkIngestUrl = var.splunk_ingest_url
7 | }
8 |
9 | template_url = var.template_url
10 |
11 | capabilities = [
12 | "CAPABILITY_AUTO_EXPAND",
13 | "CAPABILITY_NAMED_IAM"
14 | ]
15 |
16 | tags = local.all_security_tags
17 | tags_all = local.all_security_tags
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cisco-open/forge/88370ff639002b3353d78bb15f147481bd9a1dcb/modules/integrations/splunk_o11y_aws_integration/outputs.tf
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/providers.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = var.aws_region
3 | profile = var.aws_profile
4 |
5 | # Required, as per security guidelines.
6 | default_tags {
7 | tags = merge(var.default_tags, )
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/secrets.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | secrets = {
3 | splunk_access_ingest_token = {
4 | name = "/cicd/common/splunk_access_ingest_token"
5 | }
6 | }
7 | }
8 |
9 | data "aws_secretsmanager_secret" "secrets" {
10 | for_each = local.secrets
11 | name = each.value.name
12 | }
13 |
14 | data "aws_secretsmanager_secret_version" "secrets" {
15 | for_each = data.aws_secretsmanager_secret.secrets
16 | secret_id = each.value.id
17 | }
18 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | type = string
3 | description = "AWS profile (i.e., generated via 'sl aws session generate') to use."
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Default AWS region."
9 | }
10 |
11 | variable "splunk_ingest_url" {
12 | description = "URL for Splunk Ingest."
13 | type = string
14 | }
15 |
16 | variable "template_url" {
17 | description = "URL for the CloudFormation template."
18 | type = string
19 | }
20 |
21 |
22 | variable "tags" {
23 | type = map(string)
24 | description = "A map of tags to apply to resources."
25 | }
26 |
27 | variable "default_tags" {
28 | type = map(string)
29 | description = "A map of tags to apply to resources."
30 | }
31 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | }
9 |
10 | # OpenTofu version.
11 | required_version = ">= 1.9.1"
12 | }
13 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/outputs.tf:
--------------------------------------------------------------------------------
1 | output "iam_role_splunk_integration" {
2 | value = aws_iam_role.splunk_integration.arn
3 | }
4 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/providers.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = var.aws_region
3 | profile = var.aws_profile
4 |
5 | # Required, as per security guidelines.
6 | default_tags {
7 | tags = merge(var.default_tags, )
8 | }
9 | }
10 |
11 | provider "signalfx" {
12 | api_url = var.splunk_api_url
13 |
14 | email = data.aws_secretsmanager_secret_version.secrets["splunk_o11y_username"].secret_string
15 | password = data.aws_secretsmanager_secret_version.secrets["splunk_o11y_password"].secret_string
16 | organization_id = var.splunk_organization_id
17 | }
18 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/secrets.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | secrets = {
3 | splunk_o11y_username = {
4 | name = "/cicd/common/splunk_o11y_username"
5 | }
6 | splunk_o11y_password = {
7 | name = "/cicd/common/splunk_o11y_password"
8 | }
9 | }
10 | }
11 |
12 | data "aws_secretsmanager_secret" "secrets" {
13 | for_each = local.secrets
14 | name = each.value.name
15 | }
16 |
17 | data "aws_secretsmanager_secret_version" "secrets" {
18 | for_each = data.aws_secretsmanager_secret.secrets
19 | secret_id = each.value.id
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/signalfx.tf:
--------------------------------------------------------------------------------
1 | resource "signalfx_aws_external_integration" "integration" {
2 | name = var.integration_name
3 | }
4 |
5 | resource "signalfx_aws_integration" "integration" {
6 | enabled = true
7 |
8 | integration_id = signalfx_aws_external_integration.integration.id
9 | external_id = signalfx_aws_external_integration.integration.external_id
10 | role_arn = aws_iam_role.splunk_integration.arn
11 | regions = var.integration_regions
12 | import_cloud_watch = true
13 | enable_aws_usage = true
14 | use_metric_streams_sync = true
15 | enable_check_large_volume = true
16 |
17 | depends_on = [time_sleep.wait_30_seconds]
18 | }
19 |
20 | # Force a delay between secret creation and seeding. We only need a few
21 | # seconds, but if we don't do this, we get into a bad state requiring manual
22 | # intervention and/or manual forced-deletion of secrets.
23 | resource "time_sleep" "wait_30_seconds" {
24 | depends_on = [
25 | aws_iam_role.splunk_integration,
26 | ]
27 | create_duration = "30s"
28 | }
29 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_account_id" {
2 | description = "AWS account ID (not SL AWS account ID) associated with the infra/backend."
3 | type = string
4 | }
5 |
6 | variable "aws_profile" {
7 | type = string
8 | description = "AWS profile (i.e., generated via 'sl aws session generate') to use."
9 | }
10 |
11 | variable "aws_region" {
12 | type = string
13 | description = "Default AWS region."
14 | }
15 |
16 | variable "integration_name" {
17 | type = string
18 | description = "Name of the integration."
19 | }
20 |
21 | variable "integration_regions" {
22 | type = list(string)
23 | description = "List of regions for the integration."
24 | }
25 |
26 | variable "splunk_api_url" {
27 | description = "URL for plunk Observability Cloud API."
28 | type = string
29 | }
30 |
31 | variable "splunk_organization_id" {
32 | description = "organization ID for Splunk Observability Cloud."
33 | type = string
34 | }
35 |
36 | variable "tags" {
37 | type = map(string)
38 | description = "A map of tags to apply to resources."
39 | }
40 |
41 | variable "default_tags" {
42 | type = map(string)
43 | description = "A map of tags to apply to resources."
44 | }
45 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_o11y_aws_integration_common/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | signalfx = {
9 | source = "splunk-terraform/signalfx"
10 | version = "9.9.0"
11 | }
12 | time = {
13 | source = "hashicorp/time"
14 | version = "~> 0.13"
15 | }
16 | }
17 |
18 | # OpenTofu version.
19 | required_version = ">= 1.9.1"
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_otel_eks/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Will be filled by Terragrunt.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_otel_eks/data.tf:
--------------------------------------------------------------------------------
1 | data "aws_eks_cluster" "cluster" {
2 | name = var.cluster_name
3 | }
4 |
5 | data "aws_eks_cluster_auth" "cluster" {
6 | name = var.cluster_name
7 | }
8 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_otel_eks/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
12 | provider "kubernetes" {
13 | host = data.aws_eks_cluster.cluster.endpoint
14 | cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
15 | token = data.aws_eks_cluster_auth.cluster.token
16 | }
17 |
18 | provider "helm" {
19 | kubernetes {
20 | host = data.aws_eks_cluster.cluster.endpoint
21 | cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
22 | token = data.aws_eks_cluster_auth.cluster.token
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_otel_eks/secrets.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | secrets = {
3 | splunk_access_ingest_token = {
4 | name = "/cicd/common/splunk_access_ingest_token"
5 | }
6 | splunk_cloud_hec_token_eks = {
7 | name = "/cicd/common/splunk_cloud_hec_token_eks"
8 | }
9 | }
10 | }
11 |
12 | data "aws_secretsmanager_secret" "secrets" {
13 | for_each = local.secrets
14 | name = each.value.name
15 | }
16 |
17 | data "aws_secretsmanager_secret_version" "secrets" {
18 | for_each = data.aws_secretsmanager_secret.secrets
19 | secret_id = each.value.id
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_otel_eks/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | type = string
3 | description = "AWS profile to use."
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Default AWS region."
9 | }
10 |
11 | variable "cluster_name" {
12 | description = "The name of the EKS cluster"
13 | type = string
14 | }
15 |
16 | variable "splunk_otel_collector" {
17 | description = "Configuration for the Splunk OpenTelemetry Collector"
18 | type = object({
19 | splunk_observability_realm = string
20 | splunk_platform_endpoint = string
21 | splunk_platform_index = string
22 | gateway = bool
23 | splunk_observability_profiling = bool
24 | environment = string
25 | discovery = bool
26 | })
27 | }
28 |
29 | variable "default_tags" {
30 | type = map(string)
31 | description = "A map of tags to apply to resources."
32 | }
33 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_otel_eks/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | helm = {
9 | source = "hashicorp/helm"
10 | version = "2.17.0"
11 | }
12 | kubernetes = {
13 | source = "hashicorp/kubernetes"
14 | version = "2.36.0"
15 | }
16 | }
17 |
18 | # OpenTofu version.
19 | required_version = ">= 1.9.1"
20 | }
21 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_secrets/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Re-use what's provided by the root module.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_secrets/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
12 |
13 | provider "aws" {
14 | alias = "by_region"
15 | # supported by opentofu >= 1.9.0
16 | for_each = toset(local.all_regions)
17 | profile = var.aws_profile
18 | region = each.key
19 |
20 | # Required, as per security guidelines.
21 | default_tags {
22 | tags = var.default_tags
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_secrets/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_secrets/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS profile to use."
3 | type = string
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Default AWS region."
9 | default = "us-east-1"
10 | }
11 |
12 | variable "replica_regions" {
13 | description = "List of regions to replicate the secret"
14 | type = list(string)
15 | default = []
16 | }
17 |
18 | variable "tags" {
19 | type = map(string)
20 | description = "A map of tags to apply to resources."
21 | }
22 |
23 | variable "default_tags" {
24 | type = map(string)
25 | description = "A map of tags to apply to resources."
26 | }
27 |
--------------------------------------------------------------------------------
/modules/integrations/splunk_secrets/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Provider versions.
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 5.90"
7 | }
8 | time = {
9 | source = "hashicorp/time"
10 | version = "~> 0.13"
11 | }
12 | }
13 |
14 | # OpenTofu version.
15 | required_version = ">= 1.9.1"
16 | }
17 |
--------------------------------------------------------------------------------
/modules/integrations/teleport/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Re-use what's provided by the root module.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integrations/teleport/data.tf:
--------------------------------------------------------------------------------
1 | data "aws_eks_cluster" "cluster" {
2 | name = var.teleport_config.cluster_name
3 | }
4 |
5 | data "aws_eks_cluster_auth" "cluster" {
6 | name = var.teleport_config.cluster_name
7 | }
8 |
--------------------------------------------------------------------------------
/modules/integrations/teleport/main.tf:
--------------------------------------------------------------------------------
1 | module "tenant" {
2 | for_each = { for tenant in var.tenants : tenant => tenant }
3 | source = "./tenant"
4 |
5 | namespace = each.value
6 | release_name = "${each.value}-${var.tenant_prefix}"
7 | teleport_config = var.teleport_config
8 |
9 | tags = var.tags
10 | }
11 |
12 | resource "kubernetes_config_map" "aws_auth_teleport" {
13 | count = length(var.tenants) > 0 ? 1 : 0
14 | metadata {
15 | name = "aws-auth"
16 | namespace = "kube-system"
17 | }
18 |
19 | data = {
20 | mapRoles = join("\n", [
21 | for tenant in var.tenants : < runner.runner_role_arn
4 | }
5 | }
6 |
7 | output "subnet_cidr_blocks" {
8 | value = module.arc.subnet_cidr_blocks
9 | }
10 |
--------------------------------------------------------------------------------
/modules/platform/arc_deployment/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | type = string
3 | description = "AWS profile (i.e. generated via 'sl aws session generate') to use."
4 | }
5 |
6 | variable "aws_region" {
7 | type = string
8 | description = "Assuming single region for now."
9 | }
10 |
11 | variable "runner_configs" {
12 | type = object({
13 | prefix = string
14 | arc_cluster_name = string
15 | ghes_url = string
16 | ghes_org = string
17 | github_app = object({
18 | key_base64 = string
19 | id = string
20 | installation_id = string
21 | })
22 | runner_iam_role_managed_policy_arns = list(string)
23 | runner_group_name = string
24 | runner_specs = map(object({
25 | runner_size = object({
26 | max_runners = number
27 | min_runners = number
28 | })
29 | scale_set_name = string
30 | scale_set_type = string
31 | container_actions_runner = string
32 | container_limits_cpu = string
33 | container_limits_memory = string
34 | container_requests_cpu = string
35 | container_requests_memory = string
36 | }))
37 | })
38 | }
39 |
40 | variable "tenant_configs" {
41 | type = object({
42 | ecr_registries = list(string)
43 | tags = map(string)
44 | name = string
45 | })
46 | }
47 |
--------------------------------------------------------------------------------
/modules/platform/arc_deployment/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # OpenTofu version.
3 | required_version = ">= 1.9.1"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/platform/ec2_deployment/ami.tf:
--------------------------------------------------------------------------------
1 | data "aws_ssm_parameter" "ami_id" {
2 | for_each = {
3 | for runner_key, runner in module.runners.runners_map :
4 | runner_key => split("parameter", runner.launch_template_ami_id)[1]
5 | }
6 |
7 | name = each.value
8 | with_decryption = true
9 | }
10 |
11 | data "aws_ami" "runner_ami" {
12 | for_each = { for runner_key, runner in module.runners.runners_map : runner_key => runner.launch_template_ami_id }
13 | most_recent = false
14 | filter {
15 | name = "image-id"
16 | values = [data.aws_ssm_parameter.ami_id[each.key].value]
17 | }
18 | depends_on = [module.runners]
19 | }
20 |
--------------------------------------------------------------------------------
/modules/platform/ec2_deployment/outputs.tf:
--------------------------------------------------------------------------------
1 | output "webhook_endpoint" {
2 | value = module.runners.webhook.endpoint
3 | }
4 |
5 | output "ec2_runners_arn_map" {
6 | value = {
7 | for runner_key, runner in module.runners.runners_map : runner_key => runner.role_runner.arn
8 | }
9 | }
10 |
11 | output "ec2_runners_ami_name_map" {
12 | value = {
13 | for runner_key, runner in module.runners.runners_map : runner_key => data.aws_ami.runner_ami[runner_key].name
14 | }
15 | }
16 |
17 | output "subnet_cidr_blocks" {
18 | value = { for id, subnet in data.aws_subnet.runner_subnet : id => subnet.cidr_block }
19 | }
20 |
--------------------------------------------------------------------------------
/modules/platform/ec2_deployment/scripts/download_lambdas.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -x
3 |
4 | if [ -z "$1" ]; then
5 | echo "Usage: $0 "
6 | exit 1
7 | fi
8 |
9 | DOWNLOAD_PATH="$1"
10 | # renovate: datasource=github-tags depName=github-aws-runners/terraform-aws-github-runner registryUrl=https://github.com/
11 | VERSION="6.5.5"
12 |
13 | rm -rf "$DOWNLOAD_PATH"
14 | mkdir -p "$DOWNLOAD_PATH"
15 |
16 | # Download files to the specified directory
17 | wget --no-verbose -P "$DOWNLOAD_PATH" "https://github.com/github-aws-runners/terraform-aws-github-runner/releases/download/v${VERSION}/runner-binaries-syncer.zip"
18 | wget --no-verbose -P "$DOWNLOAD_PATH" "https://github.com/github-aws-runners/terraform-aws-github-runner/releases/download/v${VERSION}/runners.zip"
19 | wget --no-verbose -P "$DOWNLOAD_PATH" "https://github.com/github-aws-runners/terraform-aws-github-runner/releases/download/v${VERSION}/webhook.zip"
20 |
21 | echo -n "{\"version\":\"${VERSION}\"}"
22 |
--------------------------------------------------------------------------------
/modules/platform/ec2_deployment/security_group.tf:
--------------------------------------------------------------------------------
1 | # Allow the lambda to egress to any destination via any protocol.
2 | resource "aws_security_group" "gh_runner_lambda_egress" {
3 | name = "${var.runner_configs.prefix}-gh-runner-lambda-egress-all"
4 | vpc_id = var.network_configs.vpc_id
5 |
6 | egress {
7 | from_port = 0
8 | to_port = 0
9 | protocol = "-1"
10 | cidr_blocks = ["0.0.0.0/0"]
11 | }
12 |
13 | tags = merge(
14 | var.tenant_configs.tags,
15 | {
16 | Name = "${var.runner_configs.prefix}-gh-runner-lambda-egress-all"
17 | }
18 | )
19 |
20 | tags_all = var.tenant_configs.tags
21 | }
22 |
23 | # Policy for the runners (not the lambdas).
24 | resource "aws_security_group" "gh_runner_egress" {
25 | name = "${var.runner_configs.prefix}-gh-runner-lambda-egress"
26 | vpc_id = var.network_configs.vpc_id
27 |
28 | egress {
29 | from_port = 0
30 | to_port = 0
31 | protocol = "-1"
32 | cidr_blocks = ["0.0.0.0/0"]
33 | }
34 |
35 | tags = merge(
36 | var.tenant_configs.tags,
37 | {
38 | Name = "${var.runner_configs.prefix}-gh-runner-lambda-egress"
39 | }
40 | )
41 |
42 | tags_all = var.tenant_configs.tags
43 | }
44 |
--------------------------------------------------------------------------------
/modules/platform/ec2_deployment/template_files/post_install.tftpl:
--------------------------------------------------------------------------------
1 | # Login to ECR registry. This is needed so that CI jobs can access our "ops"
2 | # containers we store in ECR.
3 | %{ if length(ecr_registries) > 0 ~}
4 | %{ for registry in ecr_registries ~}
5 | aws ecr get-login-password \
6 | --region $(echo ${registry} | awk -F. '{print $4}') \
7 | | su -l ${runner_user} -c \
8 | "docker --config /home/${runner_user}/.docker login \
9 | --username AWS \
10 | --password-stdin ${registry}"
11 | %{ endfor ~}
12 |
13 | %{ endif ~}
14 |
--------------------------------------------------------------------------------
/modules/platform/ec2_deployment/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | aws = {
4 | source = "hashicorp/aws"
5 | version = ">= 5.90"
6 | }
7 | external = {
8 | source = "hashicorp/external"
9 | version = ">= 2.3"
10 | }
11 | }
12 |
13 | # OpenTofu version.
14 | required_version = ">= 1.9.1"
15 | }
16 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/arc_runners.tf:
--------------------------------------------------------------------------------
1 |
2 |
3 | module "arc_runners" {
4 | # Using multi-runner example as a baseline.
5 | source = "../arc_deployment"
6 |
7 | aws_profile = var.aws_profile
8 | aws_region = var.aws_region
9 |
10 | tenant_configs = {
11 | ecr_registries = var.tenant.ecr_registries
12 | name = var.tenant.name
13 | tags = local.all_security_tags
14 | }
15 |
16 | runner_configs = {
17 | arc_cluster_name = var.arc_cluster_name
18 | prefix = var.deployment_config.prefix
19 | ghes_url = var.ghes_url
20 | ghes_org = var.ghes_org
21 | log_level = var.log_level
22 | runner_iam_role_managed_policy_arns = local.runner_iam_role_managed_policy_arns
23 | github_app = {
24 | key_base64 = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_key"].secret_string
25 | id = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_id"].secret_string
26 | installation_id = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_installation_id"].secret_string
27 | }
28 | runner_group_name = var.runner_group_name
29 | runner_specs = var.arc_runner_specs
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/backend.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | # Intentionally empty. Re-use what's provided by the root module.
3 | backend "s3" {}
4 | }
5 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/budget.tf:
--------------------------------------------------------------------------------
1 | resource "aws_budgets_budget" "budget_monthly_overall" {
2 | for_each = var.ec2_runner_specs
3 |
4 | name = "Tenant (${var.deployment_config.prefix} ${each.key}) => Runner Type Monthly Budget"
5 | budget_type = "COST"
6 | limit_amount = each.value.aws_budget.budget_limit
7 | limit_unit = "USD"
8 | time_unit = "MONTHLY"
9 | time_period_start = "2020-01-01_00:00"
10 |
11 | cost_filter {
12 | # Filter by service type (case-sensitive).
13 | name = "TagKeyValue"
14 | values = [
15 | "user:Name${"$"}${var.deployment_config.prefix}-${each.key}-action-runner"
16 | ]
17 | }
18 |
19 | tags = local.all_security_tags
20 | }
21 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/ec2_runners.tf:
--------------------------------------------------------------------------------
1 |
2 | # For generating a webhook secret. Apparently this is a cryptographically secure
3 | # PRNG.
4 | resource "random_id" "random" {
5 | byte_length = 20
6 | }
7 |
8 | module "ec2_runners" {
9 | # Using multi-runner example as a baseline.
10 | source = "../ec2_deployment"
11 |
12 | aws_region = var.aws_region
13 |
14 | network_configs = {
15 | vpc_id = var.vpc_id
16 | subnet_ids = var.subnet_ids
17 | lambda_subnet_ids = var.lambda_subnet_ids
18 | }
19 |
20 | tenant_configs = {
21 | ecr_registries = var.tenant.ecr_registries
22 | tags = local.all_security_tags
23 | }
24 |
25 | runner_configs = {
26 | prefix = var.deployment_config.prefix
27 | ghes_url = var.ghes_url
28 | ghes_org = var.ghes_org
29 | log_level = var.log_level
30 | logging_retention_in_days = var.logging_retention_in_days
31 | runner_iam_role_managed_policy_arns = local.runner_iam_role_managed_policy_arns
32 | github_app = {
33 | key_base64 = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_key"].secret_string
34 | id = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_id"].secret_string
35 | webhook_secret = random_id.random.hex
36 | }
37 | runner_group_name = var.runner_group_name
38 | runner_specs = var.ec2_runner_specs
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/lambda/requirements.txt:
--------------------------------------------------------------------------------
1 | PyJWT==2.10.1
2 | requests==2.32.4
3 | boto3==1.38.14
4 | cryptography==44.0.3
5 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/locals.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | runner_iam_role_managed_policy_arns = concat(
3 | # If the policy exists, include it, otherwise skip it
4 | length(var.tenant.iam_roles_to_assume) > 0 ? [aws_iam_policy.role_assumption_for_forge_runners[0].arn] : [],
5 | [
6 | aws_iam_policy.ecr_access_for_ec2_instances.arn,
7 | aws_iam_policy.dynamodb_policy.arn,
8 | ]
9 | )
10 |
11 | github_app_installation = "${var.ghes_url == "" ? "https://github.com" : var.ghes_url}/apps/${data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_name"].secret_string}/installations/${data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_installation_id"].secret_string}"
12 | github_api = var.ghes_url == "" ? "https://api.github.com" : "https://api.${replace(var.ghes_url, "https://", "")}"
13 | }
14 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/outputs.tf:
--------------------------------------------------------------------------------
1 | # Needed for the GitHub App to issue callbacks.
2 | output "webhook_endpoint" {
3 | value = module.ec2_runners.webhook_endpoint
4 | }
5 |
6 | output "webhook_secret" {
7 | value = random_id.random.hex
8 | sensitive = true
9 | }
10 |
11 | output "ec2_runners_arn_map" {
12 | value = module.ec2_runners.ec2_runners_arn_map
13 | }
14 |
15 | output "ec2_runners_ami_name_map" {
16 | value = module.ec2_runners.ec2_runners_ami_name_map
17 | }
18 |
19 | output "ec2_subnet_cidr_blocks" {
20 | value = module.ec2_runners.subnet_cidr_blocks
21 | }
22 |
23 | output "arc_runners_arn_map" {
24 | value = module.arc_runners.arc_runners_arn_map
25 | }
26 |
27 | output "arc_subnet_cidr_blocks" {
28 | value = module.arc_runners.subnet_cidr_blocks
29 | }
30 |
31 | output "github_app_installation" {
32 | value = local.github_app_installation
33 | sensitive = true
34 | }
35 | output "runner_group_name" {
36 | value = var.runner_group_name
37 | }
38 |
39 | output "tenant" {
40 | value = var.tenant
41 | }
42 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/providers.tf:
--------------------------------------------------------------------------------
1 | # Re-use AWS settings from root module.
2 | provider "aws" {
3 | region = var.aws_region
4 | profile = var.aws_profile
5 |
6 | # Required, as per security guidelines.
7 | default_tags {
8 | tags = var.default_tags
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/scripts/generate_and_patch_github_app.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #shellcheck disable=SC2086,SC2004
3 | set -o pipefail
4 |
5 | now=$(date +%s)
6 | iat=$((${now} - 60)) # Issues 60 seconds in the past
7 | exp=$((${now} + 600)) # Expires 10 minutes in the future
8 |
9 | b64enc() { openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n'; }
10 |
11 | header_json='{
12 | "typ":"JWT",
13 | "alg":"RS256"
14 | }'
15 | # Header encode
16 | header=$(echo -n "${header_json}" | b64enc)
17 |
18 | payload_json="{
19 | \"iat\":${iat},
20 | \"exp\":${exp},
21 | \"iss\":\"${CLIENT_ID}\"
22 | }"
23 | # Payload encode
24 | payload=$(echo -n "${payload_json}" | b64enc)
25 |
26 | # Signature
27 | header_payload="${header}"."${payload}"
28 | signature=$(
29 | openssl dgst -sha256 -sign <(echo -n "${PRIVATE_KEY}") \
30 | <(echo -n "${header_payload}") | b64enc
31 | )
32 |
33 | # Create JWT
34 | JWT="${header_payload}"."${signature}"
35 |
36 | # Call GitHub API
37 | LOG_FILE="/tmp/github_api_response.log"
38 |
39 | response=$(curl -s -X PATCH "${GITHUB_API}/app/hook/config" \
40 | -H "Authorization: Bearer $JWT" \
41 | -H "Accept: application/vnd.github+json" \
42 | -H "Content-Type: application/json" \
43 | -d "{
44 | \"url\": \"$WEBHOOK_URL\",
45 | \"content_type\": \"json\",
46 | \"insecure_ssl\": \"0\",
47 | \"secret\": \"$SECRET\"
48 | }")
49 |
50 | echo "$response" | tee "$LOG_FILE"
51 | echo "Response saved to $LOG_FILE"
52 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/scripts/requirements_clean_global_lock.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TENANT_PATH="$1"
4 |
5 | # Paths
6 | LAMBDA_DIR="${PWD}/lambda"
7 | PACKAGE_DIR="/${TENANT_PATH}/lambda_package/package"
8 | LAMBDA_PACKAGE_DIR="/${TENANT_PATH}/lambda_package"
9 |
10 | # Ensure the target directories exist
11 | rm -rf "$PACKAGE_DIR"
12 | mkdir -p "$PACKAGE_DIR"
13 |
14 | pip3 install -r "${LAMBDA_DIR}/requirements.txt" \
15 | --platform manylinux2014_x86_64 \
16 | --target="$PACKAGE_DIR" \
17 | --implementation cp \
18 | --python-version 3.11 \
19 | --only-binary=:all: --upgrade >/dev/null 2>&1
20 |
21 | # Step 2: Copy the Python script to the package directory
22 | cp "${LAMBDA_DIR}/github_clean_global_lock.py" "$LAMBDA_PACKAGE_DIR"
23 |
24 | # Output the result in JSON format
25 | echo "{\"status\": \"success\", \"message\": \"Dependencies installed successfully.\", \"lambda_package_dir\": \"$LAMBDA_PACKAGE_DIR\"}"
26 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/scripts/requirements_runner_group.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TENANT_PATH="$1"
4 |
5 | # Paths
6 | LAMBDA_DIR="${PWD}/lambda"
7 | PACKAGE_DIR="/${TENANT_PATH}/lambda_package/package"
8 | LAMBDA_PACKAGE_DIR="/${TENANT_PATH}/lambda_package"
9 |
10 | # Ensure the target directories exist
11 | rm -rf "$PACKAGE_DIR"
12 | mkdir -p "$PACKAGE_DIR"
13 |
14 | pip3 install -r "${LAMBDA_DIR}/requirements.txt" \
15 | --platform manylinux2014_x86_64 \
16 | --target="$PACKAGE_DIR" \
17 | --implementation cp \
18 | --python-version 3.11 \
19 | --only-binary=:all: --upgrade >/dev/null 2>&1
20 |
21 | # Step 2: Copy the Python script to the package directory
22 | cp "${LAMBDA_DIR}/github_app_runner_group.py" "$LAMBDA_PACKAGE_DIR"
23 |
24 | # Output the result in JSON format
25 | echo "{\"status\": \"success\", \"message\": \"Dependencies installed successfully.\", \"lambda_package_dir\": \"$LAMBDA_PACKAGE_DIR\"}"
26 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/tags.tf:
--------------------------------------------------------------------------------
1 | # Common tags we propagate project-wide.
2 | locals {
3 | all_security_tags = merge(var.default_tags, var.tags)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/update_gh_app.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "update_github_app_webhook" {
2 | triggers = {
3 | webhook_url = module.ec2_runners.webhook_endpoint
4 | secret = random_id.random.hex
5 | secret_version = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_key"].id
6 | }
7 |
8 | provisioner "local-exec" {
9 | environment = {
10 | CLIENT_ID = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_client_id"].secret_string
11 | PRIVATE_KEY = base64decode(
12 | data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_key"].secret_string
13 | )
14 | WEBHOOK_URL = self.triggers.webhook_url
15 | SECRET = self.triggers.secret
16 | GITHUB_API = local.github_api
17 | }
18 |
19 | command = "${path.module}/scripts/generate_and_patch_github_app.sh"
20 | }
21 |
22 | depends_on = [
23 | data.aws_secretsmanager_secret_version.data_cicd_secrets,
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/modules/platform/forge_runners/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | aws = {
4 | source = "hashicorp/aws"
5 | version = ">= 5.90"
6 | }
7 | local = {
8 | source = "hashicorp/local"
9 | version = ">= 2.5"
10 | }
11 | random = {
12 | source = "hashicorp/random"
13 | version = ">= 3.6"
14 | }
15 | time = {
16 | source = "hashicorp/time"
17 | version = ">= 0.13"
18 | }
19 | null = {
20 | source = "hashicorp/null"
21 | version = ">= 3.2"
22 | }
23 | external = {
24 | source = "hashicorp/external"
25 | version = ">= 2.3"
26 | }
27 | archive = {
28 | source = "hashicorp/archive"
29 | version = ">= 2.7.0"
30 | }
31 | }
32 |
33 | # OpenTofu version.
34 | required_version = ">= 1.9.1"
35 | }
36 |
--------------------------------------------------------------------------------
/scripts/update-terraform-docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # terraform-docs
4 |
5 | # renovate: datasource=github-releases depName=terraform-docs/terraform-docs registryUrl=https://github.com/
6 | TERRAFORM_DOCS_VERSION="0.20.0"
7 | curl -sqLo /tmp/terraform-docs.tar.gz "https://github.com/terraform-docs/terraform-docs/releases/download/v${TERRAFORM_DOCS_VERSION}/terraform-docs-v${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz"
8 | tar -zxvf /tmp/terraform-docs.tar.gz -C /usr/local/bin/
9 | chmod +x /usr/local/bin/terraform-docs
10 |
11 | # renovate: datasource=github-releases depName=opentofu/opentofu registryUrl=https://github.com/
12 | OPENTOFU_VERSION="1.9.1"
13 | curl -sqLo /tmp/opentofu.tar.gz "https://github.com/opentofu/opentofu/releases/download/v${OPENTOFU_VERSION}/tofu_${OPENTOFU_VERSION}_linux_amd64.zip"
14 | unzip -o /tmp/opentofu.tar.gz -d /usr/local/bin/
15 | chmod +x /usr/local/bin/tofu
16 |
17 | find modules/* -type d -not -path '*/\.*' -print0 | xargs -0 -I {} tofu -chdir={} init -backend=false
18 | find modules/* -type f -name "*.tf" \
19 | -not -path '*/.*' \
20 | -not -path 'modules/integrations/splunk_cloud_data_manager/*' \
21 | -not -path 'modules/infra/forge_subscription/*' \
22 | -not -path 'modules/integrations/splunk_secrets/*' \
23 | -exec dirname {} \; | sort -u | xargs -I {} terraform-docs -c .terraform-docs.yml {}
24 |
--------------------------------------------------------------------------------