├── .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 |
10 | 11 | 12 |
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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/examples/deployments/forge-eks/terragrunt/root.hcl -------------------------------------------------------------------------------- /examples/deployments/forge-eks/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/forge/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/examples/deployments/forge-extras/terragrunt/root.hcl -------------------------------------------------------------------------------- /examples/deployments/forge-extras/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/forge/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/examples/deployments/forge-integrations/terragrunt/root.hcl -------------------------------------------------------------------------------- /examples/deployments/forge-integrations/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/forge/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/examples/deployments/forge-tenant/terragrunt/root.hcl -------------------------------------------------------------------------------- /examples/deployments/forge-tenant/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/forge/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/examples/deployments/splunk-deployment/terragrunt/root.hcl -------------------------------------------------------------------------------- /examples/deployments/splunk-deployment/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/forge/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/examples/infra-forge/terragrunt/root.hcl -------------------------------------------------------------------------------- /examples/infra-forge/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/forge/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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/459e1e23dc7264198a9b14dd883d66eb5365f854/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 | runner_iam_role_managed_policy_arns = local.runner_iam_role_managed_policy_arns 31 | github_app = { 32 | key_base64 = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_key"].secret_string 33 | id = data.aws_secretsmanager_secret_version.data_cicd_secrets["${local.cicd_secrets_prefix}github_actions_runners_app_id"].secret_string 34 | webhook_secret = random_id.random.hex 35 | } 36 | runner_group_name = var.runner_group_name 37 | runner_specs = var.ec2_runner_specs 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /modules/platform/forge_runners/lambda/requirements.txt: -------------------------------------------------------------------------------- 1 | PyJWT==2.10.1 2 | requests==2.32.3 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 | --------------------------------------------------------------------------------