├── .circleci └── example.yml ├── .env ├── .envrc ├── .gitignore ├── LICENSE ├── README.md ├── base ├── .terraform-version ├── base.tfvars ├── iam.tf ├── init.sh ├── initialize.tf ├── outputs.tf ├── root_dns.tf ├── s3.tf └── variables.tf ├── env-development ├── .env ├── .envrc ├── .terraform-version ├── examples │ ├── aurora-postgresql.tf │ ├── consul.tf │ ├── ecs-service.tf │ ├── edge.tf │ ├── metadata.tf │ ├── pingdom.tf │ ├── providers.tf │ ├── vault-with-aurora-mysql-secret-engine.tf │ ├── vault-with-postgresql-secret-engine.tf │ ├── vault.tf │ └── waf-authentication.tf ├── files │ └── iam │ │ ├── assume_role_ec2.json │ │ ├── assume_role_rds_monitoring.json │ │ ├── assume_role_vpc_flow.json │ │ └── vpc_flow_policy.json ├── init.sh ├── initialize.tf ├── locals.tf ├── main.tf ├── providers.tf └── terraform.tfvars ├── env-production ├── .env ├── .envrc ├── .terraform-version ├── files │ └── iam │ │ ├── assume_role_ec2.json │ │ ├── assume_role_rds_monitoring.json │ │ ├── assume_role_vpc_flow.json │ │ └── vpc_flow_policy.json ├── init.sh ├── initialize.tf ├── locals.tf ├── main.tf ├── providers.tf └── terraform.tfvars ├── env-staging ├── .env ├── .envrc ├── .terraform-version ├── files │ └── iam │ │ ├── assume_role_ec2.json │ │ ├── assume_role_rds_monitoring.json │ │ ├── assume_role_vpc_flow.json │ │ └── vpc_flow_policy.json ├── init.sh ├── initialize.tf ├── locals.tf ├── main.tf ├── providers.tf └── terraform.tfvars ├── env.example ├── init-variables.tf.sh ├── initialize.tf ├── modules └── .gitsave └── variables.tf /.circleci/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Anchors for aliases 3 | # Original refrence file https://github.com/asicsdigital/terraform-reference 4 | # 5 | # This file should provide a working example of one possible workflow for an app 6 | # deployed using docker containers. This example builds and deploys an application 7 | # git tags to deploy to development, staging, and production with "deploy-dev/staging/hotfix-" 8 | # tag prefix. Production releases are initiated by deploying a tag with a symantic version. (vXX.XX.Xx) 9 | # 10 | # It should provide a starting point and should be changed as needed. 11 | # We use YAML Aliases https://blog.daemonl.com/2016/02/yaml.html to 12 | # decrease code duplication and make the CircleCI config easier to read. 13 | # At some point in the future, we will start using Orbs which will also help address 14 | # Some of the challenges that our use of Aliases does. 15 | # # 16 | # Change IMAGE_NAME for your project 17 | # Change SERVICE_IDENTIFIER for our project. This should match service_identifier in terraform 18 | project_env_vars: &project_env_vars 19 | environment: 20 | SERVICE_IDENTIFIER: payments 21 | TASK_IDENTIFIER: app 22 | IMAGE_NAME: asicsdigital/payments 23 | GOSS_PATH: /home/circleci/bin/goss 24 | GOSS_FILES_STRATEGY: cp 25 | 26 | # Docker Image used to run terraform. 27 | # Change to use the version of terraform you want to use asicsdigital/hermes:terraform-XX.XX.XX 28 | docker_terraform: &docker_terraform 29 | working_directory: ~/app 30 | docker: 31 | - image: asicsdigital/hermes:terraform-0.12.17 32 | entrypoint: /bin/sh 33 | 34 | # Docker Image is used to build you docker image, this can be changed as needed 35 | docker_image: &docker_image 36 | docker: 37 | - image: circleci/buildpack-deps:stable-curl 38 | 39 | # This is the VAULT_ADDR for the Vault to be used for each step in the CI process. 40 | # This should be a reasonable default but could be changed as needed. Possible values are: 41 | # https://vault.us-east-1.dev.asics.digital 42 | # https://vault.us-west-1.dev.asics.digital 43 | # https://vault.us-east-1.dev.rkcloud.us 44 | vault_addr_dev: &vault_addr_dev 45 | environment: 46 | VAULT_ADDR: https://vault.us-east-1.dev.asics.digital 47 | 48 | vault_addr_staging: &vault_addr_staging 49 | environment: 50 | VAULT_ADDR: https://vault.us-east-1.staging.asics.digital 51 | 52 | vault_addr_prod: &vault_addr_prod 53 | environment: 54 | VAULT_ADDR: https://vault.us-east-1.prod.asics.digital 55 | # End of values to be changed, in most cases. 56 | 57 | # Docker login - These credentials exit as a global env var in our CI Tool 58 | docker_login: &docker_login 59 | name: "Docker Login" 60 | command: | 61 | docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD 62 | 63 | install_goss: &install_goss 64 | name: Install goss 65 | command: | 66 | # rather than give internet scripts SU rights, we install to local user bin and add to path 67 | mkdir ~/bin 68 | export GOSS_DST=~/bin 69 | export PATH=$PATH:~/bin 70 | curl -fsSL https://goss.rocks/install | sh 71 | goss -version 72 | 73 | run_goss_tests: &run_goss_tests 74 | name: "Run goss Tests" 75 | command: | 76 | docker build . -t app:$TAG 77 | cd tests 78 | export PATH=$PATH:~/bin 79 | dgoss run -it --entrypoint /bin/sh app:$TAG 80 | 81 | build_for_deployment: &build_for_deployment 82 | name: "Docker build and push Docker Image for Deployment" 83 | command: | 84 | DOCKER_IMAGE=${IMAGE_NAME}:${CIRCLE_SHA1} 85 | DOCKER_BUILD_TAG=${IMAGE_NAME}:build-${CIRCLE_BUILD_NUM} 86 | DOCKER_DEPLOY_DEFAULT=${IMAGE_NAME}:${TAG} 87 | mkdir -p /tmp/workspace 88 | echo ${DOCKER_IMAGE} > /tmp/workspace/docker_image 89 | echo ${SERVICE_IDENTIFIER} > /tmp/workspace/service_identifier 90 | echo ${TASK_IDENTIFIER} > /tmp/workspace/task_identifier 91 | docker build -t ${DOCKER_IMAGE} . 92 | docker tag ${DOCKER_IMAGE} ${DOCKER_BUILD_TAG} 93 | docker tag ${DOCKER_IMAGE} ${DOCKER_DEPLOY_DEFAULT} 94 | docker push ${DOCKER_IMAGE} 95 | docker push ${DOCKER_BUILD_TAG} 96 | docker push ${DOCKER_DEPLOY_DEFAULT} 97 | echo "Pushed: ${DOCKER_IMAGE}" 98 | 99 | upload_build_to_consul: &upload_build_to_consul 100 | name: "Upload Deployment Data to Consul" 101 | command: | 102 | DOCKER_IMAGE=$(cat /tmp/workspace/docker_image) 103 | SERVICE_IDENTIFIER=$(cat /tmp/workspace/service_identifier) 104 | TASK_IDENTIFIER=$(cat /tmp/workspace/task_identifier) 105 | put-consul-kv "${SERVICE_IDENTIFIER}/${TASK_IDENTIFIER}/docker-image" "${DOCKER_IMAGE}" 106 | put-consul-kv ${SERVICE_IDENTIFIER}/${TASK_IDENTIFIER}/sha1hash "${CIRCLE_SHA1}" 107 | 108 | upload_rc_build_to_consul: &upload_rc_build_to_consul 109 | name: "Upload Deployment Data to Consul" 110 | command: | 111 | DOCKER_IMAGE=$(cat /tmp/workspace/docker_image) 112 | SERVICE_IDENTIFIER=$(cat /tmp/workspace/service_identifier) 113 | TASK_IDENTIFIER=$(cat /tmp/workspace/task_identifier) 114 | put-consul-kv ${SERVICE_IDENTIFIER}/${TASK_IDENTIFIER}/rc/docker-image "${DOCKER_IMAGE}" 115 | put-consul-kv ${SERVICE_IDENTIFIER}/${TASK_IDENTIFIER}/rc/sha1hash "${CIRCLE_SHA1}" 116 | 117 | terraform_fmt: &terraform_fmt 118 | name: terraform-fmt 119 | command: terraform fmt -write=false -list=true -diff=true 120 | 121 | terraform_init: &terraform_init 122 | name: terraform-init 123 | command: terraform init -input=false -lock-timeout=120s 124 | 125 | terraform_validate: &terraform_validate 126 | name: terraform-validate 127 | command: terraform validate -check-variables=false 128 | 129 | terraform_plan: &terraform_plan 130 | name: terraform-plan 131 | command: terraform plan -lock-timeout=120s 132 | 133 | terraform_apply: &terraform_apply 134 | name: terraform-apply 135 | command: terraform apply -auto-approve=true -lock-timeout=120s 136 | 137 | set_dev_env: &set_dev_env 138 | name: Setup Dev Environment Variables 139 | command: | 140 | echo 'export "VAULT_PAYLOAD=$DEV_vault_payload_us_east_1"' >> $BASH_ENV 141 | #The above variables are set in circle ci environment TODO: Move to vault? 142 | 143 | set_staging_env: &set_staging_env 144 | name: Setup Staging Environment Variables 145 | command: | 146 | echo 'export "VAULT_PAYLOAD=$STAGING_vault_payload_us_east_1"' >> $BASH_ENV 147 | 148 | set_prod_env: &set_prod_env 149 | name: Setup Prod Environment Variables 150 | command: | 151 | echo 'export "VAULT_PAYLOAD=$PROD_vault_payload_us_east_1"' >> $BASH_ENV 152 | 153 | set_auth_tokens: &set_auth_tokens 154 | name: "Get credentials from Vault" 155 | command: | 156 | echo "VAULT_PAYLOAD: ${VAULT_PAYLOAD}" 157 | echo "VAULT_ADDR: ${VAULT_ADDR}" 158 | set-vault-token 159 | get-iam-auth 160 | 161 | get_consul_htpasswd: &get_consul_htpasswd 162 | name: get-consul-htpasswd 163 | command: get-consul-http-auth 164 | 165 | revoke_lease: &revoke_lease 166 | name: "Revoke AWS IAM credentials from Vault" 167 | command: lease-revoke 168 | # End Anchors 169 | 170 | # In this section we will define all the jobs that are used in the workflow 171 | version: 2 172 | jobs: 173 | # This step tests and builds a docker image 174 | build: 175 | working_directory: ~/app 176 | <<: *docker_image 177 | <<: *project_env_vars 178 | steps: 179 | - checkout 180 | - setup_remote_docker 181 | - run: 182 | <<: *docker_login 183 | - run: 184 | <<: *install_goss 185 | - run: 186 | environment: 187 | TAG: core 188 | <<: *run_goss_tests 189 | - run: 190 | environment: 191 | TAG: deploy-dev 192 | <<: *build_for_deployment 193 | 194 | build-for-deployment-dev: 195 | working_directory: ~/app 196 | <<: *docker_image 197 | <<: *project_env_vars 198 | steps: 199 | - checkout 200 | - setup_remote_docker 201 | - run: 202 | <<: *docker_login 203 | - run: 204 | <<: *install_goss 205 | - run: 206 | environment: 207 | TAG: core 208 | <<: *run_goss_tests 209 | - run: 210 | environment: 211 | TAG: deploy-dev 212 | <<: *build_for_deployment 213 | - persist_to_workspace: 214 | root: /tmp/workspace 215 | paths: 216 | - docker_image 217 | - service_identifier 218 | - task_identifier 219 | 220 | build-for-deployment-staging: 221 | working_directory: ~/app 222 | <<: *docker_image 223 | <<: *project_env_vars 224 | steps: 225 | - checkout 226 | - setup_remote_docker 227 | - run: 228 | <<: *docker_login 229 | - run: 230 | <<: *install_goss 231 | - run: 232 | environment: 233 | TAG: deploy-staging 234 | <<: *run_goss_tests 235 | - run: 236 | environment: 237 | TAG: deploy-staging 238 | <<: *build_for_deployment 239 | - persist_to_workspace: 240 | root: /tmp/workspace 241 | paths: 242 | - docker_image 243 | - service_identifier 244 | - task_identifier 245 | 246 | build-for-deployment-prod: 247 | working_directory: ~/app 248 | <<: *docker_image 249 | <<: *project_env_vars 250 | steps: 251 | - checkout 252 | - setup_remote_docker 253 | - run: 254 | <<: *docker_login 255 | - run: 256 | <<: *install_goss 257 | - run: 258 | environment: 259 | TAG: deploy-prod 260 | <<: *run_goss_tests 261 | - run: 262 | environment: 263 | TAG: deploy-prod 264 | <<: *build_for_deployment 265 | - persist_to_workspace: 266 | root: /tmp/workspace 267 | paths: 268 | - docker_image 269 | - service_identifier 270 | - task_identifier 271 | 272 | # This section defines uploading artifact (image) metadata to consul 273 | upload-to-consul-dev: 274 | working_directory: ~/app 275 | <<: *docker_terraform 276 | <<: *vault_addr_dev 277 | <<: *project_env_vars 278 | steps: 279 | - checkout 280 | - attach_workspace: 281 | at: /tmp/workspace 282 | - run: 283 | <<: *set_dev_env 284 | - run: 285 | <<: *set_auth_tokens 286 | - run: 287 | <<: *get_consul_htpasswd 288 | - run: 289 | <<: *upload_build_to_consul 290 | 291 | upload-to-consul-staging: 292 | working_directory: ~/app 293 | <<: *docker_terraform 294 | <<: *vault_addr_staging 295 | <<: *project_env_vars 296 | steps: 297 | - checkout 298 | - attach_workspace: 299 | at: /tmp/workspace 300 | - run: 301 | <<: *set_staging_env 302 | - run: 303 | <<: *set_auth_tokens 304 | - run: 305 | <<: *get_consul_htpasswd 306 | - run: 307 | <<: *upload_build_to_consul 308 | 309 | upload-to-consul-prod: 310 | working_directory: ~/app 311 | <<: *docker_terraform 312 | <<: *vault_addr_prod 313 | <<: *project_env_vars 314 | steps: 315 | - checkout 316 | - attach_workspace: 317 | at: /tmp/workspace 318 | - run: 319 | <<: *set_prod_env 320 | - run: 321 | <<: *set_auth_tokens 322 | - run: 323 | <<: *get_consul_htpasswd 324 | - run: 325 | <<: *upload_build_to_consul 326 | 327 | # This job uploads image metadata in the staging job to the *prod* consul 328 | # This was done to make artifact re-use easier if that is a part of your workflow. 329 | upload-rc-to-consul-prod: 330 | working_directory: ~/app 331 | <<: *docker_terraform 332 | <<: *vault_addr_prod 333 | <<: *project_env_vars 334 | steps: 335 | - checkout 336 | - attach_workspace: 337 | at: /tmp/workspace 338 | - run: 339 | <<: *set_prod_env 340 | - run: 341 | <<: *set_auth_tokens 342 | - run: 343 | <<: *get_consul_htpasswd 344 | - run: 345 | <<: *upload_rc_build_to_consul 346 | fmt: 347 | <<: *docker_terraform 348 | steps: 349 | - checkout 350 | - run: 351 | <<: *terraform_fmt 352 | 353 | # Base is mostly unused but is left in for completness and can be used by 354 | # projects that would like to run terraform outside a specifig tier. 355 | base: 356 | <<: *docker_terraform 357 | <<: *vault_addr_prod 358 | steps: 359 | - checkout 360 | - run: 361 | <<: *set_prod_env 362 | - run: 363 | <<: *set_auth_tokens 364 | - run: 365 | working_directory: ~/app/terraform/base 366 | <<: *terraform_init 367 | - run: 368 | working_directory: ~/app/terraform/base 369 | <<: *terraform_validate 370 | - run: 371 | name: terraform-plan 372 | command: | 373 | echo "base" 374 | working_directory: ~/app/terraform/base 375 | - run: 376 | <<: *revoke_lease 377 | 378 | base-deploy: 379 | <<: *docker_terraform 380 | <<: *vault_addr_prod 381 | steps: 382 | - checkout 383 | - run: 384 | <<: *set_prod_env 385 | - run: 386 | <<: *set_auth_tokens 387 | - run: 388 | working_directory: ~/app/terraform/base 389 | <<: *terraform_init 390 | - run: 391 | name: terraform-apply -auto-approve=true 392 | command: | 393 | if [ "${CIRCLE_BRANCH}" == "base-release" ]; then 394 | cd ~/app/terraform/base ; 395 | terraform apply -lock-timeout=120s \ 396 | -var 'consul_htpasswd=""' \ 397 | -var 'consul_http_auth=""' \ 398 | -var 'consul_http_addr'=""' \ 399 | -var 'database_cidrs=[]' \ 400 | -var 'elasticache_cidrs=[]' \ 401 | -var 'private_cidrs=[]' \ 402 | -var 'public_cidrs=[]' \ 403 | -var 'vpc_cidr=null' \ 404 | -var 'kms_secret_vault_unseal_key=null' 405 | fi 406 | working_directory: ~/app/terraform/base 407 | - run: 408 | <<: *revoke_lease 409 | 410 | # Terraform Jobs for development 411 | plan-dev: 412 | <<: *docker_terraform 413 | <<: *vault_addr_dev 414 | steps: 415 | - checkout 416 | - run: 417 | <<: *set_dev_env 418 | - run: 419 | <<: *set_auth_tokens 420 | - run: 421 | working_directory: ~/app/terraform/env-development 422 | <<: *get_consul_htpasswd 423 | - run: 424 | working_directory: ~/app/terraform/env-development 425 | <<: *terraform_init 426 | - run: 427 | working_directory: ~/app/terraform/env-development 428 | <<: *terraform_validate 429 | - run: 430 | working_directory: ~/app/terraform/env-development 431 | <<: *terraform_plan 432 | - run: 433 | <<: *revoke_lease 434 | 435 | deploy-dev: 436 | <<: *docker_terraform 437 | <<: *vault_addr_dev 438 | steps: 439 | - checkout 440 | - run: 441 | <<: *set_dev_env 442 | - run: 443 | <<: *set_auth_tokens 444 | - run: 445 | working_directory: ~/app/terraform/env-development 446 | <<: *get_consul_htpasswd 447 | - run: 448 | working_directory: ~/app/terraform/env-development 449 | <<: *terraform_init 450 | - run: 451 | working_directory: ~/app/terraform/env-development 452 | <<: *terraform_validate 453 | - run: 454 | working_directory: ~/app/terraform/env-development 455 | <<: *terraform_plan 456 | - run: 457 | working_directory: ~/app/terraform/env-development 458 | <<: *terraform_apply 459 | - run: 460 | <<: *revoke_lease 461 | 462 | # Terraform Jobs for Staging 463 | plan-staging: 464 | <<: *docker_terraform 465 | <<: *vault_addr_staging 466 | steps: 467 | - checkout 468 | - run: 469 | <<: *set_staging_env 470 | - run: 471 | <<: *set_auth_tokens 472 | - run: 473 | working_directory: ~/app/terraform/env-staging 474 | <<: *get_consul_htpasswd 475 | - run: 476 | working_directory: ~/app/terraform/env-staging 477 | <<: *terraform_init 478 | - run: 479 | working_directory: ~/app/terraform/env-staging 480 | <<: *terraform_validate 481 | - run: 482 | working_directory: ~/app/terraform/env-staging 483 | <<: *terraform_plan 484 | - run: 485 | <<: *revoke_lease 486 | 487 | deploy-staging: 488 | <<: *docker_terraform 489 | <<: *vault_addr_staging 490 | steps: 491 | - checkout 492 | - run: 493 | <<: *set_staging_env 494 | - run: 495 | <<: *set_auth_tokens 496 | - run: 497 | working_directory: ~/app/terraform/env-staging 498 | <<: *get_consul_htpasswd 499 | - run: 500 | working_directory: ~/app/terraform/env-staging 501 | <<: *terraform_init 502 | - run: 503 | working_directory: ~/app/terraform/env-staging 504 | <<: *terraform_validate 505 | - run: 506 | working_directory: ~/app/terraform/env-staging 507 | <<: *terraform_plan 508 | - run: 509 | working_directory: ~/app/terraform/env-staging 510 | <<: *terraform_apply 511 | - run: 512 | <<: *revoke_lease 513 | 514 | # Terraform Jobs for Production 515 | plan-prod: 516 | <<: *docker_terraform 517 | <<: *vault_addr_prod 518 | steps: 519 | - checkout 520 | - run: 521 | <<: *set_prod_env 522 | - run: 523 | <<: *set_auth_tokens 524 | - run: 525 | working_directory: ~/app/terraform/env-production 526 | <<: *get_consul_htpasswd 527 | - run: 528 | working_directory: ~/app/terraform/env-production 529 | <<: *terraform_init 530 | - run: 531 | working_directory: ~/app/terraform/env-production 532 | <<: *terraform_validate 533 | - run: 534 | working_directory: ~/app/terraform/env-production 535 | <<: *terraform_plan 536 | - run: 537 | <<: *revoke_lease 538 | 539 | deploy-prod: 540 | <<: *docker_terraform 541 | <<: *vault_addr_prod 542 | steps: 543 | - checkout 544 | - run: 545 | <<: *set_prod_env 546 | - run: 547 | <<: *set_auth_tokens 548 | - run: 549 | working_directory: ~/app/terraform/env-production 550 | <<: *get_consul_htpasswd 551 | - run: 552 | working_directory: ~/app/terraform/env-production 553 | <<: *terraform_init 554 | - run: 555 | working_directory: ~/app/terraform/env-production 556 | <<: *terraform_validate 557 | - run: 558 | working_directory: ~/app/terraform/env-production 559 | <<: *terraform_plan 560 | - run: 561 | working_directory: ~/app/terraform/env-production 562 | <<: *terraform_apply 563 | - run: 564 | <<: *revoke_lease 565 | 566 | # This section defines workflows 567 | # filters are used to trigger partifular flow based on tags in this example but 568 | # can be changed to use branches as desired. https://circleci.com/docs/2.0/configuration-reference/#filters 569 | workflows: 570 | version: 2 571 | build-app: 572 | jobs: 573 | # Build Workflow runs tests, builds images and runs terraform plans 574 | - build: 575 | context: org-global 576 | filters: 577 | branches: 578 | ignore: master 579 | - fmt: 580 | requires: 581 | - build 582 | - base: 583 | context: org-global 584 | requires: 585 | - fmt 586 | - plan-dev: 587 | context: org-global 588 | requires: 589 | - fmt 590 | - plan-staging: 591 | context: org-global 592 | requires: 593 | - fmt 594 | - plan-prod: 595 | context: org-global 596 | requires: 597 | - fmt 598 | 599 | deploy-dev: 600 | jobs: 601 | - build-for-deployment-dev: 602 | context: org-global 603 | filters: 604 | tags: 605 | only: /^deploy-dev-.+/ 606 | branches: 607 | ignore: /.*/ 608 | - upload-to-consul-dev: 609 | context: org-global 610 | requires: 611 | - build-for-deployment-dev 612 | filters: 613 | tags: 614 | only: /^deploy-dev-.+/ 615 | branches: 616 | ignore: /.*/ 617 | - fmt: 618 | requires: 619 | - upload-to-consul-dev 620 | filters: 621 | tags: 622 | only: /^deploy-dev-.+/ 623 | branches: 624 | ignore: /.*/ 625 | - deploy-dev: 626 | context: org-global 627 | requires: 628 | - fmt 629 | filters: 630 | tags: 631 | only: /^deploy-dev-.+/ 632 | branches: 633 | ignore: /.*/ 634 | 635 | deploy-staging: 636 | jobs: 637 | - build-for-deployment-staging: 638 | context: org-global 639 | filters: 640 | tags: 641 | only: /^deploy-staging-.+/ 642 | branches: 643 | ignore: /.*/ 644 | - upload-to-consul-staging: 645 | context: org-global 646 | requires: 647 | - build-for-deployment-staging 648 | filters: 649 | tags: 650 | only: /^deploy-staging-.+/ 651 | branches: 652 | ignore: /.*/ 653 | - fmt: 654 | requires: 655 | - upload-to-consul-staging 656 | filters: 657 | tags: 658 | only: /^deploy-staging-.+/ 659 | branches: 660 | ignore: /.*/ 661 | - deploy-staging: 662 | context: org-global 663 | requires: 664 | - fmt 665 | filters: 666 | tags: 667 | only: /^deploy-staging-.+/ 668 | branches: 669 | ignore: /.*/ 670 | # Upload release candidatate build info to Consul 671 | - upload-rc-to-consul-prod: 672 | context: org-global 673 | requires: 674 | - deploy-staging 675 | filters: 676 | tags: 677 | only: /^deploy-staging-.+/ 678 | branches: 679 | ignore: /.*/ 680 | 681 | deploy-prod: 682 | jobs: 683 | - build-for-deployment-prod: 684 | context: org-global 685 | filters: 686 | tags: 687 | only: /^deploy-prod-.+/ 688 | branches: 689 | ignore: /.*/ 690 | - upload-to-consul-prod: 691 | context: org-global 692 | requires: 693 | - build-for-deployment-prod 694 | filters: 695 | tags: 696 | only: /^deploy-prod-.+/ 697 | branches: 698 | ignore: /.*/ 699 | - fmt: 700 | requires: 701 | - upload-to-consul-prod 702 | filters: 703 | tags: 704 | only: /v[0-9]+(\.[0-9]+)*/ 705 | branches: 706 | ignore: /.*/ 707 | - deploy-prod: 708 | context: org-global 709 | requires: 710 | - fmt 711 | filters: 712 | tags: 713 | only: /v[0-9]+(\.[0-9]+)*/ 714 | branches: 715 | ignore: /.*/ 716 | deploy-hotfix: 717 | jobs: 718 | - build-for-deployment-prod: 719 | context: org-global 720 | filters: 721 | tags: 722 | only: /^deploy-hotfix-.+/ 723 | branches: 724 | ignore: /.*/ 725 | - upload-to-consul-prod: 726 | context: org-global 727 | requires: 728 | - build-for-deployment-prod 729 | filters: 730 | tags: 731 | only: /^deploy-hotfix-.+/ 732 | branches: 733 | ignore: /.*/ 734 | - fmt: 735 | context: org-global 736 | requires: 737 | - upload-to-consul-prod 738 | filters: 739 | tags: 740 | only: /^deploy-hotfix-.+/ 741 | branches: 742 | ignore: /.*/ 743 | - deploy-prod: 744 | context: org-global 745 | requires: 746 | - fmt 747 | filters: 748 | tags: 749 | only: /^deploy-hotfix-.+/ 750 | branches: 751 | ignore: /.*/ 752 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | TF_VAR_aws_profile=asics-digital 2 | AWS_PROFILE=asics-digital 3 | AWS_DEFAULT_REGION=us-east-1 4 | AWS_SDK_LOAD_CONFIG=1 5 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | if [[ -f .env ]]; then 3 | dotenv 4 | fi 5 | 6 | 7 | # auth against Vault if configured 8 | if has vault; then 9 | if [[ "$VAULT_ADDR" && "$VAULT_AUTH_GITHUB_TOKEN" ]]; then 10 | log_status "vault: are we already authenticated?" 11 | vault token lookup -format=json > /dev/null && vault token renew -format=json > /dev/null 12 | 13 | if [[ "$?" == "0" ]]; then 14 | log_status "vault: authenticated with existing token!" 15 | else 16 | log_status "vault: authenticate, since our token could not be refreshed" 17 | vault login -method=github -no-print 18 | log_status "vault: authenticated with new token!" 19 | fi 20 | fi 21 | fi 22 | 23 | function get_vault_kv { 24 | vault_path=$1 25 | vault_key=${2:-value} 26 | if [[ "$VAULT_ADDR" ]]; then 27 | VAULT_KV=$(curl -s -H "X-Vault-Token: $(cat ~/.vault-token )" -X GET $VAULT_ADDR/v1/${vault_path} | jq -r .data.${vault_key}) 28 | fi 29 | } 30 | 31 | # vim: set et fenc=utf-8 ff=unix ft=sh sts=2 sw=2 ts=2 : 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # local 2 | _* 3 | secrets.tfvars 4 | .DS_Store 5 | 6 | /packer/override.yaml 7 | 8 | # vim-workspace 9 | .session.vim* 10 | 11 | ### https://raw.github.com/github/gitignore/abad92dac5a4306f72242dae3bca6e277bce3615/Terraform.gitignore 12 | 13 | # Compiled files 14 | *.tfstate 15 | *.tfstate.*.backup 16 | *.tfstate.backup 17 | 18 | # Module directory 19 | .terraform/ 20 | 21 | 22 | ### https://raw.github.com/github/gitignore/abad92dac5a4306f72242dae3bca6e277bce3615/Global/Vim.gitignore 23 | 24 | # swap 25 | [._]*.s[a-w][a-z] 26 | [._]s[a-w][a-z] 27 | # session 28 | Session.vim 29 | # temporary 30 | .netrwhist 31 | *~ 32 | # auto-generated tag files 33 | tags 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Tim Hartmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Terraform Control repo built following the pattern as outlined by [Charity Majors](https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/) 2 | 3 | TLDR, but really, go read the post, it's way better then what I'm going to write here.. 4 | 5 | ### Terraform Version 6 | 7 | The Current production [terraform version](https://github.com/FitnessKeeper/terraform-runkeeper#terraform-version) can be found here 8 | ### To create a new repo using the terraform-reference repo. 9 | 10 | - Clone the repo into a new directory for your project `git clone https://github.com/FitnessKeeper/terraform-reference terraform-` 11 | - Edit .env in the root of the repo, in particular make sure you add a TF_PROJECT_NAME (this should be the new name of the repo, `terraform-`) 12 | - When creating a `spike` make sure you update TF_SPINE in env if something other then `rk` is needed, at the time of this writing `rk` and `asics` are valid spines. 13 | - Also when creating ASICS `spikes` update to `TF_LOCK_TABLE=asics-services-terraformStateLock` 14 | - If needed, set TF_STACK for the `stack` variable 15 | - Initialize variables.tf, this only needs to be done once, when the repo is created run `./init-variables.tf.sh` 16 | - Remove the old origin `git remote rm origin` 17 | - Add your new repo `git remote add origin https://github.com/FitnessKeeper/terraform-.git` 18 | - Commit your changes 19 | - `git push -u origin master` 20 | - Edit variables.tf to reflect your new service 21 | 22 | 23 | 24 | ### To use an environment in the control repo 25 | - `cd` into the base dir for the env you want to work on 26 | - `cd terraform-/env-development/` 27 | - `./init.sh` # to initialize your environment 28 | - `terraform get` # to load your modules 29 | - `terraform plan -var-file=development.tfvars` # manage all the things! 30 | 31 | ### Design pattern 32 | 33 | We are trying to follow a pattern where we have an infrastructure repo with 3 tiers - dev, stage, and production, known as FitnessKeeper/terraform-runkeeper. We will use that control repo to build VPC, ECS Clusters, DNS Zones, and other resources that can be presented as a platform for use by services. 34 | 35 | Services, will be created using atomic control repos, based off this skel, and have distinct state files for each of the tiers. In this way, we can make changes to the state of a service living atop our infrastructure, without having to push stage changes to the underlying resources. 36 | -------------------------------------------------------------------------------- /base/.terraform-version: -------------------------------------------------------------------------------- 1 | 0.11.11 2 | -------------------------------------------------------------------------------- /base/base.tfvars: -------------------------------------------------------------------------------- 1 | env = "base" 2 | -------------------------------------------------------------------------------- /base/iam.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsdigital/terraform-reference/d61cf528b95036cec33acb83fbc4eb454927a273/base/iam.tf -------------------------------------------------------------------------------- /base/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: ./init.sh once to initialize remote storage for this environment. 4 | # Subsequent tf actions in this environment don't require re-initialization, 5 | # unless you have completely cleared your .terraform cache. 6 | # 7 | # terraform plan -var-file=./production.tfvars 8 | # terraform apply -var-file=./production.tfvars 9 | # 10 | # Make sure you populate the repo's .env file in the root of the repo 11 | source ../.env 12 | 13 | if [ -z "$(which terraform 2>/dev/null)" ]; then 14 | echo "unable to find 'terraform' in \$PATH, exiting." 15 | exit 1 16 | fi 17 | 18 | if [ -z ${TF_PROJECT_NAME} ]; then 19 | echo "'TF_PROJECT_NAME' is empty, exiting with failure." 20 | exit 1 21 | fi 22 | 23 | set -e 24 | 25 | tf_spine="${TF_SPINE:-rk}" 26 | tf_env="base" 27 | 28 | aws_default_region="${AWS_DEFAULT_REGION:-us-east-1}" 29 | 30 | s3_bucket="${tf_spine}-devops-state-${aws_default_region}" 31 | s3_prefix="${TF_PROJECT_NAME}/state/${tf_env}" 32 | 33 | tf_version="${TF_VERSION:-0.11.11}" 34 | tf_lock_table="${TF_LOCK_TABLE:-asics-services-terraformStateLock}" 35 | 36 | FILE="terraform.tf" 37 | 38 | export TF=$(cat < $FILE 55 | terraform fmt -list=false $FILE 56 | fi 57 | 58 | terraform init -backend=true \ 59 | -backend-config="bucket=${s3_bucket}" \ 60 | -backend-config="key=${s3_prefix}/${tf_env}.tfstate" \ 61 | -backend-config="region=${aws_default_region}" 62 | 63 | echo "set remote s3 state to ${s3_bucket}/${s3_prefix}/${tf_env}.tfstate" 64 | # vim: set et fenc=utf-8 ff=unix sts=2 sw=2 ts=2 : 65 | -------------------------------------------------------------------------------- /base/initialize.tf: -------------------------------------------------------------------------------- 1 | ../initialize.tf -------------------------------------------------------------------------------- /base/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsdigital/terraform-reference/d61cf528b95036cec33acb83fbc4eb454927a273/base/outputs.tf -------------------------------------------------------------------------------- /base/root_dns.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsdigital/terraform-reference/d61cf528b95036cec33acb83fbc4eb454927a273/base/root_dns.tf -------------------------------------------------------------------------------- /base/s3.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsdigital/terraform-reference/d61cf528b95036cec33acb83fbc4eb454927a273/base/s3.tf -------------------------------------------------------------------------------- /base/variables.tf: -------------------------------------------------------------------------------- 1 | ../variables.tf -------------------------------------------------------------------------------- /env-development/.env: -------------------------------------------------------------------------------- 1 | VAULT_ENV=dev 2 | VAULT_ADDR=https://vault.$AWS_DEFAULT_REGION.$VAULT_ENV.asics.digital 3 | -------------------------------------------------------------------------------- /env-development/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | # load any .env in this directory, but ignore if missing 4 | if [[ -f .env ]]; then 5 | dotenv 6 | fi 7 | 8 | # load the .envrc files in any of the directories above this one 9 | 10 | 11 | if get_vault_kv "secret/consul_htpasswd"; then 12 | echo "consul_htpasswd = \"${VAULT_KV}\"" > _consul_htpasswd.auto.tfvars 13 | fi 14 | if get_vault_kv "secret/consul" "http_auth"; then 15 | echo "consul_http_auth = \"${VAULT_KV}\"" > _consul_http_auth.auto.tfvars 16 | fi 17 | if get_vault_kv "secret/consul" "http_addr"; then 18 | echo "consul_http_addr = \"${VAULT_KV}\"" > _consul_http_addr.auto.tfvars 19 | fi 20 | # vim: set et fenc=utf-8 ff=unix ft=sh sts=2 sw=2 ts=2 : 21 | -------------------------------------------------------------------------------- /env-development/.terraform-version: -------------------------------------------------------------------------------- 1 | 0.12.17 2 | -------------------------------------------------------------------------------- /env-development/examples/aurora-postgresql.tf: -------------------------------------------------------------------------------- 1 | module "aurora" { 2 | source = "github.com/terraform-aws-modules/terraform-aws-rds-aurora?ref=v2.15.0" 3 | name = "${local.service_identifier}-${var.env}" 4 | database_name = local.service_identifier 5 | 6 | #deletion_protection = true 7 | engine = "aurora-postgresql" 8 | engine_version = "10.5" 9 | vpc_id = data.aws_vpc.vpc.id 10 | subnets = [data.aws_subnet_ids.database.ids] 11 | replica_count = 1 12 | allowed_security_groups = local.security_groups 13 | instance_type = "db.r4.large" 14 | storage_encrypted = true 15 | apply_immediately = false 16 | monitoring_interval = 10 17 | backup_retention_period = var.db_backup_retention_period 18 | username = local.service_identifier 19 | password = local.db_password 20 | db_parameter_group_name = aws_db_parameter_group.app_db_aurora_parameter_grp.name 21 | db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.app_db_cluster_parameter_grp.name 22 | 23 | tags = { 24 | Environment = var.env 25 | Terraform = "true" 26 | } 27 | } 28 | 29 | resource "aws_db_parameter_group" "app_db_aurora_parameter_grp" { 30 | name = "tf-rds-${local.service_identifier}-${data.aws_vpc.vpc.tags["Name"]}" 31 | family = var.db_family 32 | description = "Terraform-managed parameter group for ${local.service_identifier}-${data.aws_vpc.vpc.tags["Name"]}" 33 | 34 | tags = { 35 | Name = "tf-rds-${local.service_identifier}-${data.aws_vpc.vpc.tags["Name"]}" 36 | } 37 | } 38 | 39 | resource "aws_rds_cluster_parameter_group" "app_db_cluster_parameter_grp" { 40 | name = "tf-rds-${local.service_identifier}-${data.aws_vpc.vpc.tags["Name"]}" 41 | family = var.db_family 42 | description = "Terraform-managed cluster parameter group for ${local.service_identifier}-${data.aws_vpc.vpc.tags["Name"]}" 43 | 44 | tags = { 45 | Name = "tf-rds-${local.service_identifier}-${data.aws_vpc.vpc.tags["Name"]}" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /env-development/examples/consul.tf: -------------------------------------------------------------------------------- 1 | # Connect to Consul and Get VPC Info from the KV 2 | data "consul_keys" "vpc" { 3 | key { 4 | name = "id" 5 | path = "aws/vpc/VpcId" 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /env-development/examples/ecs-service.tf: -------------------------------------------------------------------------------- 1 | # app.tf 2 | 3 | variable "app_port" { 4 | description = "Port on which application listens (default 80)" 5 | default = 80 6 | } 7 | 8 | variable "api_docker_image" { 9 | description = "Docker image to pull for api ECS task" 10 | default = "" 11 | } 12 | 13 | variable "docker_memory" { 14 | default = "512" 15 | description = "Max Memory reservation for ECS Task" 16 | } 17 | 18 | variable "docker_memory_reservation" { 19 | default = "128" 20 | description = "Min Memory reservation for ECS Task" 21 | } 22 | 23 | variable "ecs_desired_count" { 24 | default = "1" 25 | description = "Desired count of ECS Tasks running" 26 | } 27 | 28 | module "app" { 29 | source = "github.com/FitnessKeeper/terraform-aws-ecs-service?ref=v4.0.3" 30 | region = data.aws_region.current.name 31 | vpc_id = data.aws_vpc.vpc.id 32 | ecs_security_group_id = data.aws_security_group.ecs_cluster.id 33 | ecs_cluster_arn = data.aws_ecs_cluster.ecs.arn 34 | service_identifier = "${local.service_identifier}-${var.env}" 35 | task_identifier = local.task_identifier 36 | docker_image = data.consul_keys.app.var.docker_image 37 | app_port = var.app_port 38 | acm_cert_domain = "${var.env}.asics.digital" 39 | alb_subnet_ids = [data.aws_subnet_ids.public.ids] 40 | alb_healthcheck_path = local.healthcheck_path 41 | lb_bucket_name = "asics-devops-${data.aws_region.current.name}" 42 | alb_healthcheck_interval = 10 43 | ecs_desired_count = var.ecs_desired_count 44 | docker_memory = var.docker_memory 45 | docker_memory_reservation = var.docker_memory_reservation 46 | 47 | docker_port_mappings = [ 48 | { 49 | "containerPort" = var.app_port 50 | }, 51 | ] 52 | 53 | docker_environment = [ 54 | { 55 | "name" = "CONSUL_PREFIX" 56 | "value" = local.consul_prefix 57 | }, 58 | { 59 | "name" = "EXTRA_ARGS" 60 | "value" = local.extra_args 61 | }, 62 | { 63 | "name" = "VAULT_ROLE" 64 | "value" = "${local.service_identifier}-${local.task_identifier}" 65 | }, 66 | { 67 | "name" = "DB_HOST" 68 | "value" = module.aurora.this_rds_cluster_endpoint 69 | }, 70 | ] 71 | } 72 | 73 | resource "aws_cloudwatch_log_subscription_filter" "logdna_lambdafunction_logfilter" { 74 | name = "${local.service_identifier}_${local.task_identifier}_${var.env}_filter" 75 | log_group_name = "${local.service_identifier}-${var.env}-${local.task_identifier}" 76 | filter_pattern = "" 77 | destination_arn = replace(data.aws_lambda_function.logdna.arn, ":$LATEST", "") 78 | } 79 | 80 | resource "aws_lambda_permission" "allow_cloudwatch" { 81 | statement_id = "${local.service_identifier}-${var.env}-${local.task_identifier}-AllowExecutionFromCloudWatch-${data.aws_lambda_function.logdna.function_name}-${data.aws_region.current.name}" 82 | action = "lambda:InvokeFunction" 83 | function_name = data.aws_lambda_function.logdna.function_name 84 | principal = "logs.amazonaws.com" 85 | source_arn = "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:${local.service_identifier}-${var.env}-${local.task_identifier}:*" 86 | } 87 | -------------------------------------------------------------------------------- /env-development/examples/edge.tf: -------------------------------------------------------------------------------- 1 | # edge.tf 2 | 3 | resource "aws_route53_record" "app_env_cname" { 4 | zone_id = data.aws_route53_zone.env.zone_id 5 | name = "${local.service_identifier}-${local.task_identifier}.${var.env}.asics.digital" 6 | type = "CNAME" 7 | ttl = "60" 8 | 9 | weighted_routing_policy { 10 | weight = 100 11 | } 12 | 13 | set_identifier = data.aws_region.current.name 14 | 15 | records = [aws_route53_record.app_a.name] 16 | } 17 | 18 | resource "aws_route53_record" "app_a" { 19 | zone_id = data.aws_route53_zone.region.zone_id 20 | name = "${local.service_identifier}-${local.task_identifier}.${data.aws_region.current.name}.${var.env}.asics.digital" 21 | type = "A" 22 | 23 | alias { 24 | name = module.app.alb_dns_name 25 | zone_id = module.app.alb_zone_id 26 | evaluate_target_health = false 27 | } 28 | } 29 | 30 | resource "aws_route53_record" "app_aaaa" { 31 | zone_id = data.aws_route53_zone.region.zone_id 32 | name = "${local.service_identifier}-${local.task_identifier}.${data.aws_region.current.name}.${var.env}.asics.digital" 33 | type = "AAAA" 34 | 35 | alias { 36 | name = module.app.alb_dns_name 37 | zone_id = module.app.alb_zone_id 38 | evaluate_target_health = false 39 | } 40 | } 41 | 42 | resource "aws_cloudfront_origin_access_identity" "static" { 43 | comment = "CloudFront access to S3 bucket as.${var.env}.asics.digital" 44 | } 45 | 46 | -------------------------------------------------------------------------------- /env-development/examples/metadata.tf: -------------------------------------------------------------------------------- 1 | # Add metadata to Consul 2 | data "template_file" "terraform_version" { 3 | template = file(".terraform-version") 4 | } 5 | 6 | resource "consul_key_prefix" "terraform_app_metadata" { 7 | path_prefix = "${local.service_identifier}/${local.task_identifier}/metadata/" 8 | 9 | subkeys = { 10 | "version" = trimspace(data.template_file.terraform_version.rendered) 11 | "last-run" = timestamp() 12 | "terraform" = "true" 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /env-development/examples/pingdom.tf: -------------------------------------------------------------------------------- 1 | # This examples assumes that you have the vault provider configured 2 | # Usage : https://github.com/russellcardullo/terraform-provider-pingdom/blob/master/README.md#usage 3 | 4 | provider "pingdom" { 5 | user = data.vault_generic_secret.pingdom.data["user"] 6 | password = data.vault_generic_secret.pingdom.data["password"] 7 | api_key = data.vault_generic_secret.pingdom.data["apikey"] 8 | account_email = data.vault_generic_secret.pingdom.data["account_email"] # Optional: only required for multi-user accounts 9 | } 10 | 11 | resource "pingdom_check" "example" { 12 | type = "http" 13 | name = "my http check" 14 | host = "google.com" 15 | resolution = 5 16 | } 17 | -------------------------------------------------------------------------------- /env-development/examples/providers.tf: -------------------------------------------------------------------------------- 1 | provider "vault" { 2 | version = "~> 2.0" 3 | address = local.vault_addr 4 | } 5 | 6 | provider "consul" { 7 | address = "asics-services.${data.aws_region.current.name}.${var.env}.asics.digital" 8 | http_auth = var.consul_http_auth 9 | scheme = "https" 10 | } 11 | 12 | provider "aws" { 13 | version = "~> 2.46.0" 14 | } 15 | -------------------------------------------------------------------------------- /env-development/examples/vault-with-aurora-mysql-secret-engine.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | connection_url = "${var.db_username}:${local.db_password}@tcp(${module.aurora.writer_endpoint}:3306)/" 3 | vault_sql = "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';" 4 | vault_rw_sql = "${local.vault_sql} GRANT SELECT,INSERT,UPDATE,DELETE ON ${var.db_name}.* TO '{{name}}'@'%';" 5 | } 6 | 7 | resource "vault_mount" "secret" { 8 | path = "${local.service_identifier}/secret" 9 | type = "kv" 10 | description = "KV Mount for ASICS ${local.service_identifier}" 11 | } 12 | 13 | data "vault_generic_secret" "app" { 14 | path = "${local.service_identifier}/secret/${local.task_identifier}" 15 | } 16 | 17 | data "vault_generic_secret" "db_password" { 18 | path = "${local.service_identifier}/secret/aws/rds/${var.db_name}" 19 | } 20 | 21 | # Allow the ECS Task to auth to vault 22 | resource "vault_aws_auth_backend_role" "app" { 23 | backend = "aws/" 24 | role = "${local.service_identifier}-${local.task_identifier}" 25 | auth_type = "iam" 26 | # TF-UPGRADE-TODO: In Terraform v0.10 and earlier, it was sometimes necessary to 27 | # force an interpolation expression to be interpreted as a list by wrapping it 28 | # in an extra set of list brackets. That form was supported for compatibility in 29 | # v0.11, but is no longer supported in Terraform v0.12. 30 | # 31 | # If the expression in the following list itself returns a list, remove the 32 | # brackets to avoid interpretation as a list of lists. If the expression 33 | # returns a single list item then leave it as-is and remove this TODO comment. 34 | bound_iam_principal_arns = [module.app.task_iam_role_arn] 35 | policies = [vault_policy.app.name] 36 | ttl = "86400" 37 | } 38 | 39 | # Policy the ECS Task gets 40 | resource "vault_policy" "app" { 41 | name = "${local.service_identifier}-${local.task_identifier}" 42 | 43 | policy = </dev/null)" ]; then 14 | echo "unable to find 'terraform' in \$PATH, exiting." 15 | exit 1 16 | fi 17 | 18 | if [ -z ${TF_PROJECT_NAME} ]; then 19 | echo "'TF_PROJECT_NAME' is empty, exiting with failure." 20 | exit 1 21 | fi 22 | 23 | set -e 24 | 25 | tf_spine="${TF_SPINE:-rk}" 26 | tf_env="dev" 27 | 28 | aws_default_region="${AWS_DEFAULT_REGION:-us-east-1}" 29 | 30 | s3_bucket="${tf_spine}-devops-state-${aws_default_region}" 31 | s3_prefix="${TF_PROJECT_NAME}/state/${tf_env}" 32 | 33 | tf_version="${TF_VERSION:-0.11.11}" 34 | tf_lock_table="${TF_LOCK_TABLE:-asics-services-terraformStateLock}" 35 | 36 | FILE="terraform.tf" 37 | 38 | export TF=$(cat < $FILE 56 | terraform fmt -list=false $FILE 57 | fi 58 | 59 | terraform init -backend=true \ 60 | -backend-config="bucket=${s3_bucket}" \ 61 | -backend-config="key=${s3_prefix}/${tf_env}.tfstate" \ 62 | -backend-config="region=${aws_default_region}" 63 | 64 | echo "set remote s3 state to ${s3_bucket}/${s3_prefix}/${tf_env}.tfstate" 65 | # vim: set et fenc=utf-8 ff=unix sts=2 sw=2 ts=2 : 66 | -------------------------------------------------------------------------------- /env-development/initialize.tf: -------------------------------------------------------------------------------- 1 | ../initialize.tf -------------------------------------------------------------------------------- /env-development/locals.tf: -------------------------------------------------------------------------------- 1 | # For all locals that will be used in more than 1 location 2 | locals { 3 | hostname = "${var.env}.asics.digital" 4 | consul_addr = "https://asics-services.us-east-1.${local.hostname}" 5 | vault_addr = "https://vault.${data.aws_region.current.name}.${local.hostname}" 6 | ecs_cluster_name = "asics-services-${var.env}-infra-svc" 7 | service_identifier = "service identifier" 8 | task_identifier = "app" 9 | security_groups = [ 10 | data.aws_security_group.ecs_cluster.id, 11 | data.aws_security_group.consul.id, 12 | data.aws_security_group.consul_secondary.id, 13 | ] 14 | consul_prefix = local.service_identifier 15 | extra_args = "-consul-retry -consul-retry-attempts=3" 16 | # db_password = "${coalesce(var.db_password, data.vault_generic_secret.db.data["password"])}" 17 | } 18 | 19 | -------------------------------------------------------------------------------- /env-development/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "available" { #TODO: is this right? 2 | } 3 | 4 | data "aws_region" "current" { 5 | } 6 | 7 | data "aws_vpc" "vpc" { 8 | id = data.consul_keys.vpc.var.id 9 | } 10 | 11 | data "aws_route53_zone" "region" { 12 | name = "${data.aws_region.current.name}.${var.env}.asics.digital." 13 | } 14 | 15 | data "aws_route53_zone" "env" { 16 | name = "${var.env}.asics.digital." 17 | } 18 | 19 | data "aws_ecs_cluster" "ecs" { 20 | cluster_name = local.ecs_cluster_name 21 | } 22 | 23 | data "aws_subnet_ids" "public" { 24 | vpc_id = data.aws_vpc.vpc.id 25 | 26 | tags = { 27 | Tier = "public" 28 | } 29 | } 30 | 31 | data "aws_subnet_ids" "private" { 32 | vpc_id = data.aws_vpc.vpc.id 33 | 34 | tags = { 35 | Tier = "private" 36 | } 37 | } 38 | 39 | data "aws_subnet_ids" "database" { 40 | vpc_id = data.aws_vpc.vpc.id 41 | 42 | tags = { 43 | Tier = "database" 44 | } 45 | } 46 | 47 | data "aws_acm_certificate" "cert" { 48 | domain = "${var.env}.asics.digital" 49 | statuses = ["ISSUED"] 50 | most_recent = true 51 | } 52 | 53 | data "aws_acm_certificate" "us-east-1" { 54 | provider = aws.us-east-1 55 | domain = "${var.env}.asics.digital" 56 | statuses = ["ISSUED"] 57 | most_recent = true 58 | } 59 | 60 | data "aws_security_group" "ecs_cluster" { 61 | tags = { 62 | Name = "ecs-sg-asics-services-${var.env}-infra-svc" 63 | } 64 | } 65 | 66 | data "aws_security_group" "consul" { 67 | tags = { 68 | Name = "ecs-sg-consul-${var.env}" 69 | } 70 | } 71 | 72 | data "aws_security_group" "consul_secondary" { 73 | tags = { 74 | Name = "ecs-sg-consul-${var.env}-secondary" 75 | } 76 | } 77 | 78 | data "aws_caller_identity" "current" { 79 | } 80 | 81 | data "aws_lambda_function" "logdna" { 82 | function_name = "LogDNA-${var.env}" 83 | } 84 | 85 | data "consul_keys" "vpc" { 86 | key { 87 | name = "id" 88 | path = "aws/vpc/VpcId" 89 | } 90 | } 91 | 92 | data "consul_keys" "app" { 93 | key { 94 | name = "docker_image" 95 | path = "${local.service_identifier}/${local.task_identifier}/docker-image" 96 | default = "asicsdigital/${local.service_identifier}-${local.task_identifier}:deploy-${var.env}" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /env-development/providers.tf: -------------------------------------------------------------------------------- 1 | provider "vault" { 2 | version = "~> 2.0" 3 | address = local.vault_addr 4 | } 5 | 6 | provider "consul" { 7 | address = "asics-services.${data.aws_region.current.name}.${var.env}.asics.digital" 8 | http_auth = var.consul_http_auth 9 | scheme = "https" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /env-development/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # DEVELOPMENT 2 | 3 | env = "dev" 4 | -------------------------------------------------------------------------------- /env-production/.env: -------------------------------------------------------------------------------- 1 | VAULT_ENV=prod 2 | VAULT_ADDR=https://vault.$AWS_DEFAULT_REGION.$VAULT_ENV.asics.digital 3 | -------------------------------------------------------------------------------- /env-production/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | # load any .env in this directory, but ignore if missing 4 | if [[ -f .env ]]; then 5 | dotenv 6 | fi 7 | 8 | # load the .envrc files in any of the directories above this one 9 | 10 | 11 | if get_vault_kv "secret/consul_htpasswd"; then 12 | echo "consul_htpasswd = \"${VAULT_KV}\"" > _consul_htpasswd.auto.tfvars 13 | fi 14 | if get_vault_kv "secret/consul" "http_auth"; then 15 | echo "consul_http_auth = \"${VAULT_KV}\"" > _consul_http_auth.auto.tfvars 16 | fi 17 | if get_vault_kv "secret/consul" "http_addr"; then 18 | echo "consul_http_addr = \"${VAULT_KV}\"" > _consul_http_addr.auto.tfvars 19 | fi 20 | # vim: set et fenc=utf-8 ff=unix ft=sh sts=2 sw=2 ts=2 : 21 | -------------------------------------------------------------------------------- /env-production/.terraform-version: -------------------------------------------------------------------------------- 1 | 0.12.17 2 | -------------------------------------------------------------------------------- /env-production/files/iam/assume_role_ec2.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": "sts:AssumeRole", 6 | "Principal": { 7 | "Service": "ec2.amazonaws.com" 8 | }, 9 | "Effect": "Allow", 10 | "Sid": "" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /env-production/files/iam/assume_role_rds_monitoring.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": "sts:AssumeRole", 6 | "Principal": { 7 | "Service": "monitoring.rds.amazonaws.com" 8 | }, 9 | "Effect": "Allow", 10 | "Sid": "" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /env-production/files/iam/assume_role_vpc_flow.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "", 6 | "Effect": "Allow", 7 | "Principal": { 8 | "Service": "vpc-flow-logs.amazonaws.com" 9 | }, 10 | "Action": "sts:AssumeRole" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /env-production/files/iam/vpc_flow_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": [ 6 | "logs:CreateLogGroup", 7 | "logs:CreateLogStream", 8 | "logs:PutLogEvents", 9 | "logs:DescribeLogGroups", 10 | "logs:DescribeLogStreams" 11 | ], 12 | "Effect": "Allow", 13 | "Resource": "*" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /env-production/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: ./init.sh once to initialize remote storage for this environment. 4 | # Subsequent tf actions in this environment don't require re-initialization, 5 | # unless you have completely cleared your .terraform cache. 6 | # 7 | # terraform plan -var-file=./production.tfvars 8 | # terraform apply -var-file=./production.tfvars 9 | # 10 | # Make sure you populate the repo's .env file in the root of the repo 11 | source ../.env 12 | 13 | if [ -z "$(which terraform 2>/dev/null)" ]; then 14 | echo "unable to find 'terraform' in \$PATH, exiting." 15 | exit 1 16 | fi 17 | 18 | if [ -z ${TF_PROJECT_NAME} ]; then 19 | echo "'TF_PROJECT_NAME' is empty, exiting with failure." 20 | exit 1 21 | fi 22 | 23 | set -e 24 | 25 | tf_spine="${TF_SPINE:-rk}" 26 | tf_env="prod" 27 | 28 | aws_default_region="${AWS_DEFAULT_REGION:-us-east-1}" 29 | 30 | s3_bucket="${tf_spine}-devops-state-${aws_default_region}" 31 | s3_prefix="${TF_PROJECT_NAME}/state/${tf_env}" 32 | 33 | tf_version="${TF_VERSION:-0.11.11}" 34 | tf_lock_table="${TF_LOCK_TABLE:-asics-services-terraformStateLock}" 35 | 36 | FILE="terraform.tf" 37 | 38 | export TF=$(cat < $FILE 56 | terraform fmt -list=false $FILE 57 | fi 58 | 59 | terraform init -backend=true \ 60 | -backend-config="bucket=${s3_bucket}" \ 61 | -backend-config="key=${s3_prefix}/${tf_env}.tfstate" \ 62 | -backend-config="region=${aws_default_region}" 63 | 64 | echo "set remote s3 state to ${s3_bucket}/${s3_prefix}/${tf_env}.tfstate" 65 | # vim: set et fenc=utf-8 ff=unix sts=2 sw=2 ts=2 : 66 | -------------------------------------------------------------------------------- /env-production/initialize.tf: -------------------------------------------------------------------------------- 1 | ../initialize.tf -------------------------------------------------------------------------------- /env-production/locals.tf: -------------------------------------------------------------------------------- 1 | # For all locals that will be used in more than 1 location 2 | locals { 3 | hostname = "${var.env}.asics.digital" 4 | consul_addr = "https://asics-services.us-east-1.${local.hostname}" 5 | vault_addr = "https://vault.${data.aws_region.current.name}.${local.hostname}" 6 | ecs_cluster_name = "asics-services-${var.env}-infra-svc" 7 | service_identifier = "service identifier" 8 | task_identifier = "app" 9 | security_groups = [ 10 | data.aws_security_group.ecs_cluster.id, 11 | data.aws_security_group.consul.id, 12 | data.aws_security_group.consul_secondary.id, 13 | ] 14 | consul_prefix = local.service_identifier 15 | extra_args = "-consul-retry -consul-retry-attempts=3" 16 | # db_password = "${coalesce(var.db_password, data.vault_generic_secret.db.data["password"])}" 17 | } 18 | 19 | -------------------------------------------------------------------------------- /env-production/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "available" { #TODO: is this right? 2 | } 3 | 4 | data "aws_region" "current" { 5 | } 6 | 7 | data "aws_vpc" "vpc" { 8 | id = data.consul_keys.vpc.var.id 9 | } 10 | 11 | data "aws_route53_zone" "region" { 12 | name = "${data.aws_region.current.name}.${var.env}.asics.digital." 13 | } 14 | 15 | data "aws_route53_zone" "env" { 16 | name = "${var.env}.asics.digital." 17 | } 18 | 19 | data "aws_ecs_cluster" "ecs" { 20 | cluster_name = local.ecs_cluster_name 21 | } 22 | 23 | data "aws_subnet_ids" "public" { 24 | vpc_id = data.aws_vpc.vpc.id 25 | 26 | tags = { 27 | Tier = "public" 28 | } 29 | } 30 | 31 | data "aws_subnet_ids" "private" { 32 | vpc_id = data.aws_vpc.vpc.id 33 | 34 | tags = { 35 | Tier = "private" 36 | } 37 | } 38 | 39 | data "aws_subnet_ids" "database" { 40 | vpc_id = data.aws_vpc.vpc.id 41 | 42 | tags = { 43 | Tier = "database" 44 | } 45 | } 46 | 47 | data "aws_acm_certificate" "cert" { 48 | domain = "${var.env}.asics.digital" 49 | statuses = ["ISSUED"] 50 | most_recent = true 51 | } 52 | 53 | data "aws_acm_certificate" "us-east-1" { 54 | provider = aws.us-east-1 55 | domain = "${var.env}.asics.digital" 56 | statuses = ["ISSUED"] 57 | most_recent = true 58 | } 59 | 60 | data "aws_security_group" "ecs_cluster" { 61 | tags = { 62 | Name = "ecs-sg-asics-services-${var.env}-infra-svc" 63 | } 64 | } 65 | 66 | data "aws_security_group" "consul" { 67 | tags = { 68 | Name = "ecs-sg-consul-${var.env}" 69 | } 70 | } 71 | 72 | data "aws_security_group" "consul_secondary" { 73 | tags = { 74 | Name = "ecs-sg-consul-${var.env}-secondary" 75 | } 76 | } 77 | 78 | data "aws_caller_identity" "current" { 79 | } 80 | 81 | data "aws_lambda_function" "logdna" { 82 | function_name = "LogDNA-${var.env}" 83 | } 84 | 85 | data "consul_keys" "vpc" { 86 | key { 87 | name = "id" 88 | path = "aws/vpc/VpcId" 89 | } 90 | } 91 | 92 | data "consul_keys" "app" { 93 | key { 94 | name = "docker_image" 95 | path = "${local.service_identifier}/${local.task_identifier}/docker-image" 96 | default = "asicsdigital/${local.service_identifier}-${local.task_identifier}:deploy-${var.env}" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /env-production/providers.tf: -------------------------------------------------------------------------------- 1 | provider "vault" { 2 | version = "~> 2.0" 3 | address = local.vault_addr 4 | } 5 | 6 | provider "consul" { 7 | address = "asics-services.${data.aws_region.current.name}.${var.env}.asics.digital" 8 | http_auth = var.consul_http_auth 9 | scheme = "https" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /env-production/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # PRODUCTION 2 | 3 | env = "prod" 4 | -------------------------------------------------------------------------------- /env-staging/.env: -------------------------------------------------------------------------------- 1 | VAULT_ENV=staging 2 | VAULT_ADDR=https://vault.$AWS_DEFAULT_REGION.$VAULT_ENV.asics.digital 3 | -------------------------------------------------------------------------------- /env-staging/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | # load any .env in this directory, but ignore if missing 4 | if [[ -f .env ]]; then 5 | dotenv 6 | fi 7 | 8 | # load the .envrc files in any of the directories above this one 9 | 10 | 11 | if get_vault_kv "secret/consul_htpasswd"; then 12 | echo "consul_htpasswd = \"${VAULT_KV}\"" > _consul_htpasswd.auto.tfvars 13 | fi 14 | if get_vault_kv "secret/consul" "http_auth"; then 15 | echo "consul_http_auth = \"${VAULT_KV}\"" > _consul_http_auth.auto.tfvars 16 | fi 17 | if get_vault_kv "secret/consul" "http_addr"; then 18 | echo "consul_http_addr = \"${VAULT_KV}\"" > _consul_http_addr.auto.tfvars 19 | fi 20 | # vim: set et fenc=utf-8 ff=unix ft=sh sts=2 sw=2 ts=2 : 21 | -------------------------------------------------------------------------------- /env-staging/.terraform-version: -------------------------------------------------------------------------------- 1 | 0.12.17 2 | -------------------------------------------------------------------------------- /env-staging/files/iam/assume_role_ec2.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": "sts:AssumeRole", 6 | "Principal": { 7 | "Service": "ec2.amazonaws.com" 8 | }, 9 | "Effect": "Allow", 10 | "Sid": "" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /env-staging/files/iam/assume_role_rds_monitoring.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": "sts:AssumeRole", 6 | "Principal": { 7 | "Service": "monitoring.rds.amazonaws.com" 8 | }, 9 | "Effect": "Allow", 10 | "Sid": "" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /env-staging/files/iam/assume_role_vpc_flow.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "", 6 | "Effect": "Allow", 7 | "Principal": { 8 | "Service": "vpc-flow-logs.amazonaws.com" 9 | }, 10 | "Action": "sts:AssumeRole" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /env-staging/files/iam/vpc_flow_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": [ 6 | "logs:CreateLogGroup", 7 | "logs:CreateLogStream", 8 | "logs:PutLogEvents", 9 | "logs:DescribeLogGroups", 10 | "logs:DescribeLogStreams" 11 | ], 12 | "Effect": "Allow", 13 | "Resource": "*" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /env-staging/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: ./init.sh once to initialize remote storage for this environment. 4 | # Subsequent tf actions in this environment don't require re-initialization, 5 | # unless you have completely cleared your .terraform cache. 6 | # 7 | # terraform plan -var-file=./production.tfvars 8 | # terraform apply -var-file=./production.tfvars 9 | # 10 | # Make sure you populate the repo's .env file in the root of the repo 11 | source ../.env 12 | 13 | if [ -z "$(which terraform 2>/dev/null)" ]; then 14 | echo "unable to find 'terraform' in \$PATH, exiting." 15 | exit 1 16 | fi 17 | 18 | if [ -z ${TF_PROJECT_NAME} ]; then 19 | echo "'TF_PROJECT_NAME' is empty, exiting with failure." 20 | exit 1 21 | fi 22 | 23 | set -e 24 | 25 | tf_spine="${TF_SPINE:-rk}" 26 | tf_env="staging" 27 | 28 | aws_default_region="${AWS_DEFAULT_REGION:-us-east-1}" 29 | 30 | s3_bucket="${tf_spine}-devops-state-${aws_default_region}" 31 | s3_prefix="${TF_PROJECT_NAME}/state/${tf_env}" 32 | 33 | tf_version="${TF_VERSION:-0.11.11}" 34 | tf_lock_table="${TF_LOCK_TABLE:-asics-services-terraformStateLock}" 35 | 36 | FILE="terraform.tf" 37 | 38 | export TF=$(cat < $FILE 56 | terraform fmt -list=false $FILE 57 | fi 58 | 59 | terraform init -backend=true \ 60 | -backend-config="bucket=${s3_bucket}" \ 61 | -backend-config="key=${s3_prefix}/${tf_env}.tfstate" \ 62 | -backend-config="region=${aws_default_region}" 63 | 64 | echo "set remote s3 state to ${s3_bucket}/${s3_prefix}/${tf_env}.tfstate" 65 | # vim: set et fenc=utf-8 ff=unix sts=2 sw=2 ts=2 : 66 | -------------------------------------------------------------------------------- /env-staging/initialize.tf: -------------------------------------------------------------------------------- 1 | ../initialize.tf -------------------------------------------------------------------------------- /env-staging/locals.tf: -------------------------------------------------------------------------------- 1 | # For all locals that will be used in more than 1 location 2 | locals { 3 | hostname = "${var.env}.asics.digital" 4 | consul_addr = "https://asics-services.us-east-1.${local.hostname}" 5 | vault_addr = "https://vault.${data.aws_region.current.name}.${local.hostname}" 6 | ecs_cluster_name = "asics-services-${var.env}-infra-svc" 7 | service_identifier = "service identifier" 8 | task_identifier = "app" 9 | security_groups = [ 10 | data.aws_security_group.ecs_cluster.id, 11 | data.aws_security_group.consul.id, 12 | data.aws_security_group.consul_secondary.id, 13 | ] 14 | consul_prefix = local.service_identifier 15 | extra_args = "-consul-retry -consul-retry-attempts=3" 16 | # db_password = "${coalesce(var.db_password, data.vault_generic_secret.db.data["password"])}" 17 | } 18 | 19 | -------------------------------------------------------------------------------- /env-staging/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "available" { #TODO: is this right? 2 | } 3 | 4 | data "aws_region" "current" { 5 | } 6 | 7 | data "aws_vpc" "vpc" { 8 | id = data.consul_keys.vpc.var.id 9 | } 10 | 11 | data "aws_route53_zone" "region" { 12 | name = "${data.aws_region.current.name}.${var.env}.asics.digital." 13 | } 14 | 15 | data "aws_route53_zone" "env" { 16 | name = "${var.env}.asics.digital." 17 | } 18 | 19 | data "aws_ecs_cluster" "ecs" { 20 | cluster_name = local.ecs_cluster_name 21 | } 22 | 23 | data "aws_subnet_ids" "public" { 24 | vpc_id = data.aws_vpc.vpc.id 25 | 26 | tags = { 27 | Tier = "public" 28 | } 29 | } 30 | 31 | data "aws_subnet_ids" "private" { 32 | vpc_id = data.aws_vpc.vpc.id 33 | 34 | tags = { 35 | Tier = "private" 36 | } 37 | } 38 | 39 | data "aws_subnet_ids" "database" { 40 | vpc_id = data.aws_vpc.vpc.id 41 | 42 | tags = { 43 | Tier = "database" 44 | } 45 | } 46 | 47 | data "aws_acm_certificate" "cert" { 48 | domain = "${var.env}.asics.digital" 49 | statuses = ["ISSUED"] 50 | most_recent = true 51 | } 52 | 53 | data "aws_acm_certificate" "us-east-1" { 54 | provider = aws.us-east-1 55 | domain = "${var.env}.asics.digital" 56 | statuses = ["ISSUED"] 57 | most_recent = true 58 | } 59 | 60 | data "aws_security_group" "ecs_cluster" { 61 | tags = { 62 | Name = "ecs-sg-asics-services-${var.env}-infra-svc" 63 | } 64 | } 65 | 66 | data "aws_security_group" "consul" { 67 | tags = { 68 | Name = "ecs-sg-consul-${var.env}" 69 | } 70 | } 71 | 72 | data "aws_security_group" "consul_secondary" { 73 | tags = { 74 | Name = "ecs-sg-consul-${var.env}-secondary" 75 | } 76 | } 77 | 78 | data "aws_caller_identity" "current" { 79 | } 80 | 81 | data "aws_lambda_function" "logdna" { 82 | function_name = "LogDNA-${var.env}" 83 | } 84 | 85 | data "consul_keys" "vpc" { 86 | key { 87 | name = "id" 88 | path = "aws/vpc/VpcId" 89 | } 90 | } 91 | 92 | data "consul_keys" "app" { 93 | key { 94 | name = "docker_image" 95 | path = "${local.service_identifier}/${local.task_identifier}/docker-image" 96 | default = "asicsdigital/${local.service_identifier}-${local.task_identifier}:deploy-${var.env}" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /env-staging/providers.tf: -------------------------------------------------------------------------------- 1 | provider "vault" { 2 | version = "~> 2.0" 3 | address = local.vault_addr 4 | } 5 | 6 | provider "consul" { 7 | address = "asics-services.${data.aws_region.current.name}.${var.env}.asics.digital" 8 | http_auth = var.consul_http_auth 9 | scheme = "https" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /env-staging/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # STAGING 2 | 3 | env = "staging" 4 | -------------------------------------------------------------------------------- /env.example: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | AWS_DEFAULT_REGION=us-east-1 3 | TF_LOCK_TABLE=asics-services-terraformStateLock 4 | TF_PROJECT_NAME=event-system 5 | TF_SPINE=asics 6 | TF_VERSION=0.11.11 7 | -------------------------------------------------------------------------------- /init-variables.tf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FILE=variables.tf 4 | 5 | source .env 6 | aws_default_region="${AWS_DEFAULT_REGION:-us-east-1}" 7 | 8 | if [ -z ${TF_PROJECT_NAME} ]; then 9 | echo "'TF_PROJECT_NAME' is empty, exiting with failure." 10 | exit 1 11 | fi 12 | echo $TF_PROJECT_NAME 13 | 14 | tf_spine="${TF_SPINE:-asics}" 15 | 16 | # Set stack if TF_STACK is set; if not, comment out the stack variable entirely 17 | if [[ "${TF_STACK}" ]] ; then 18 | STACK_VAR_COMMENT_OPTIONAL="" 19 | STACK_VAR_DEFAULT="$TF_STACK" 20 | else 21 | STACK_VAR_COMMENT_OPTIONAL="# " 22 | STACK_VAR_DEFAULT="ref" 23 | fi 24 | 25 | export VARIABLES_TF=$(cat < $FILE 102 | fi 103 | -------------------------------------------------------------------------------- /initialize.tf: -------------------------------------------------------------------------------- 1 | #Initialize.tf contains empty variable declarations for the variables that will be populated in each env’s .tfvars file 2 | 3 | variable "env" { 4 | type = string 5 | } 6 | 7 | variable "consul_http_auth" { 8 | } 9 | 10 | variable "fqdn" { 11 | type = string 12 | } 13 | 14 | variable "vpc_id" { 15 | type = string 16 | } 17 | 18 | variable "aws_key_name" { 19 | type = string 20 | } 21 | 22 | -------------------------------------------------------------------------------- /modules/.gitsave: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsdigital/terraform-reference/d61cf528b95036cec33acb83fbc4eb454927a273/modules/.gitsave -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asicsdigital/terraform-reference/d61cf528b95036cec33acb83fbc4eb454927a273/variables.tf --------------------------------------------------------------------------------