rails_template_18f 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/Gemfile.lock +9 -7
  4. data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +4 -3
  5. data/lib/generators/rails_template18f/auditree/auditree_generator.rb +36 -6
  6. data/lib/generators/rails_template18f/auditree/templates/gitlab/auditree.yml.tt +48 -0
  7. data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +12 -2
  8. data/lib/generators/rails_template18f/cloud_gov_config/cloud_gov_config_generator.rb +0 -8
  9. data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +6 -7
  10. data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +13 -19
  11. data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +0 -4
  12. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +3 -1
  13. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +3 -1
  14. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +3 -1
  15. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +3 -1
  16. data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +138 -0
  17. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/node.yml.tt +11 -0
  18. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +75 -0
  19. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/ruby.yml +7 -0
  20. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +33 -0
  21. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +213 -0
  22. data/lib/generators/rails_template18f/oscal/oscal_generator.rb +15 -1
  23. data/lib/generators/rails_template18f/oscal/templates/bin/trestle.tt +10 -1
  24. data/lib/generators/rails_template18f/oscal/templates/gitlab/trestle.yml.tt +29 -0
  25. data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +16 -32
  26. data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +1 -1
  27. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/apply.sh +25 -0
  28. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/main.tf.tt +98 -0
  29. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +59 -0
  30. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/backend_config.tftpl +6 -0
  31. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/bot_secrets.tftpl +5 -0
  32. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/users.auto.tfvars +5 -0
  33. data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +4 -11
  34. data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +3 -3
  35. data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
  36. data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +38 -36
  37. data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +1 -6
  38. data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +30 -19
  39. data/lib/generators/rails_template18f/terraform/templates/terraform/production.tfvars.tt +3 -0
  40. data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +4 -24
  41. data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +5 -5
  42. data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +40 -55
  43. data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +11 -12
  44. data/lib/generators/rails_template18f/terraform/terraform_generator.rb +78 -6
  45. data/lib/rails_template18f/version.rb +1 -1
  46. data/template.rb +50 -25
  47. data/templates/{pa11yci.js → pa11yci.js.tt} +5 -0
  48. metadata +28 -20
  49. data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
  50. data/lib/generators/rails_template18f/terraform/templates/terraform/sandbox_bot/main.tf +0 -74
  51. data/lib/generators/rails_template18f/terraform/templates/terraform/sandbox_bot/run.sh +0 -17
  52. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/assemble-ssp.yml.tt +0 -0
  53. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/validate-ssp.yml +0 -0
  54. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap/templates → gitlab_bootstrap}/bot_secrets.tftpl +0 -0
  55. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → gitlab_bootstrap}/users.auto.tfvars +0 -0
  56. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/apply.sh +0 -0
  57. /data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/imports.tf.tftpl +0 -0
  58. /data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/imports.tf.tftpl +0 -0
@@ -3,7 +3,7 @@ terraform {
3
3
  required_providers {
4
4
  cloudfoundry = {
5
5
  source = "cloudfoundry/cloudfoundry"
6
- version = "1.2.0"
6
+ version = "~> 1.7"
7
7
  }
8
8
  }
9
9
  }
@@ -30,7 +30,7 @@ data "cloudfoundry_space" "space" {
30
30
  }
31
31
 
32
32
  module "s3" {
33
- source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.1.0"
33
+ source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.3.0"
34
34
 
35
35
  cf_space_id = data.cloudfoundry_space.space.id
36
36
  name = "<%= app_name %>-terraform-state"
@@ -99,7 +99,7 @@ locals {
99
99
  }
100
100
  resource "local_sensitive_file" "bucket_creds" {
101
101
  content = local.backend_config
102
- filename = "${path.module}/../secrets.backend.tfvars"
102
+ filename = "${path.module}/../.shadowenv.d/500_tf_backend_secrets.lisp"
103
103
  file_permission = "0600"
104
104
  }
105
105
 
@@ -1,7 +1,6 @@
1
1
  # Terraform
2
2
 
3
3
  This directory holds the terraform module for maintaining the system infrastructure and deploying the application.
4
-
5
4
  <% unless terraform_manage_spaces? %>
6
5
  ## READ ME FIRST
7
6
 
@@ -11,48 +10,57 @@ is very limited.
11
10
  When you are ready to move the application to a non-sandbox cloud.gov organization, please re-run the terraform generator with…
12
11
 
13
12
  ```bash
14
- bin/rails generate rails_template18f:terraform --cg-org=<ORG_NAME> --cg-staging=<STAGING_SPACE_NAME> --cg-prod=<PRODUCTION_SPACE_NAME>
13
+ bin/rails generate rails_template18f:terraform --cg-org=<ORG_NAME> --cg-staging=<STAGING_SPACE_NAME> --cg-prod=<PRODUCTION_SPACE_NAME> --backend=<%= backend_unless_local %>
15
14
  ```
16
15
 
17
16
  …to take full advantage of the generator, and then re-run your CI generator of choice to add production terraform plan and apply steps to your workflow.
18
17
  <% end %>
18
+ <% unless use_local_backend? %>## Terraform State Credentials
19
19
 
20
- ## Terraform State Credentials
20
+ The `bootstrap` module is used to create resources that must be created by an individual developers credentials before automation can be run:
21
21
 
22
- The `bootstrap` module is used to create an s3 bucket for later terraform runs to store their state in as well as
23
- create credentials files so developers can use that s3 bucket to create their own sandbox environments.
22
+ * service account and credentials to provide to the CI/CD pipeline to perform future updates<% unless use_gitlab_backend? %>
23
+ * an s3 bucket for later terraform runs to store their state in<% end %>
24
24
 
25
- ### Initial project setup
25
+ ### Initial <%= use_gitlab_backend? ? "CI/CD pipeline" : "project" %> setup
26
26
 
27
27
  These steps only need to be run once per project.
28
28
 
29
- 1. `cd bootstrap`<% if terraform_manage_spaces? %>
30
- 1. Add any users who should have access to the terraform state bucket to `users.auto.tfvars`<% end %>
29
+ 1. `cd bootstrap`<% if use_gitlab_backend? %>
30
+ 1. Run `./setup_shadowenv.sh`<% end %><% if terraform_manage_spaces? %>
31
+ 1. Add any users who should have access to the management space to `users.auto.tfvars`<% end %><% if use_gitlab_backend? %>
32
+ 1. Run `./apply.sh`<% else %>
31
33
  1. Run `./apply.sh -var create_bot_secrets_file=true`
32
- 1. Add `imports.tf` to git and commit the changes
33
- 1. Setup your CI/CD Pipeline to run terraform and deploy your staging and production environments
34
- 1. Copy backend credentials from `/terraform/secrets.backend.tfvars` to your CI/CD secrets using the instructions in the base README
35
- 1. Copy the cf_user and cf_password credentials from `/terraform/secrets.cicd.tfvars` to your CI/CD secrets using the instructions in the base README
36
- 1. Delete the two secrets files
34
+ 1. Add `imports.tf` to git and commit the changes<% end %>
35
+ 1. Setup your CI/CD Pipeline to run terraform and deploy your staging and production environments<% unless use_gitlab_backend? %>
36
+ 1. Copy backend credentials from `/terraform/.shadowenv.d/500_tf_backend_secrets.lisp` to your CI/CD secrets using the instructions in the base README<% end %>
37
+ 1. Copy the `cf_user` and `cf_password` credentials from `secrets.cicd.tfvars` to your CI/CD secrets using the instructions in the base README
38
+ 1. Delete `secrets.cicd.tfvars`
39
+ 1. Delete `.shadowenv.d/500_tf_backend_secrets.lisp` if you won't be running terraform locally
37
40
 
38
41
  ### To make changes to the bootstrap module
39
42
 
40
- *This should not be necessary in most cases<% if terraform_manage_spaces? %>, other than adding or removing users who should have access to the state bucket in `bootstrap/users.auto.tfvars`<% end %>*
43
+ *This should not be necessary in most cases<% if terraform_manage_spaces? %>, other than adding or removing users who should have access to the mgmt space in `bootstrap/users.auto.tfvars`<% end %>*
41
44
 
42
45
  1. Make your changes
43
- 1. Run `./apply.sh` and verify the plan before entering `yes`
44
- 1. Commit any changes to `imports.tf`
46
+ 1. Run `./apply.sh` and verify the plan before entering `yes`<% unless use_gitlab_backend? %>
47
+ 1. Commit any changes to `imports.tf`<% end %><% end %>
45
48
 
46
- ## Set up a sandbox environment or review app
49
+ <% if use_local_backend? %>
50
+ ## Deploy the App
51
+ <% else %>
52
+ ## Set up a sandbox environment or review app<% unless use_gitlab_backend? %>
47
53
 
48
54
  ### Pre-requisites:
49
55
 
50
56
  1. Someone on the team has run the [Initial project setup](#initial-project-setup) steps and `imports.tf` is up-to-date on your branch.
51
- <% if terraform_manage_spaces? %>1. You are included in the list of users in `bootstrap/users.auto.tfvars` and `bootstrap/imports.tf`<% end %>
57
+ <% if terraform_manage_spaces? %>1. You are included in the list of users in `bootstrap/users.auto.tfvars` and `bootstrap/imports.tf`<% end %><% end %><% end %>
52
58
 
53
59
  ### Steps:
54
-
55
- <% if terraform_manage_spaces? %>1. Create a new `sandbox-<NAME>.tfvars` file to hold variable values for your environment. A good starting point is copying `staging.tfvars` and editing it with your values.<% end %>
60
+ <% if use_gitlab_backend? %>
61
+ 1. Run `./bootstrap/setup_shadowenv.sh`<% end %>
62
+ <% if terraform_manage_spaces? %>1. Create a new `sandbox-<NAME>.tfvars` file to hold variable values for your environment. A good starting point is copying `staging.tfvars` and editing it with your values
63
+ 1. Add a `cf_user = "your.email@gsa.gov"` line to the `sandbox-<NAME>.tfvars` file<% end %>
56
64
 
57
65
  1. Run terraform plan with:
58
66
  ```bash
@@ -71,22 +79,19 @@ These steps only need to be run once per project.
71
79
 
72
80
  ## Structure
73
81
 
74
- ```
82
+ ```<% unless use_local_backend? %>
75
83
  |- bootstrap/
76
84
  | |- main.tf
77
85
  | |- apply.sh
86
+ | |- users.auto.tfvars<% if use_gitlab_backend? %>
87
+ | |- setup_shadowenv.sh
88
+ | |- bot_secrets.tftpl<% else %>
78
89
  | |- imports.tf (automatically generated)
79
- | |- users.auto.tfvars
80
90
  | |- terraform.tfstate(.backup) (automatically generated)
81
91
  | |- templates/
82
92
  | |- backend_config.tftpl
83
93
  | |- bot_secrets.tftpl
84
- | |- imports.tf.tftpl<% if terraform_manage_spaces? %>
85
- |- sandbox_bot/
86
- | |- main.tf
87
- | |- run.sh
88
- | |- <sandbox_name>/ (automatically generated)
89
- | |- terraform.tfstate(.backup) (automatically generated)<% end %>
94
+ | |- imports.tf.tftpl<% end %><% end %>
90
95
  |- dist/
91
96
  | |- src.zip (automatically generated)
92
97
  |- README.md
@@ -106,12 +111,9 @@ In the root module:
106
111
  - `providers.tf` lists the required providers and shell backend config
107
112
  - `variables.tf` lists the variables that will be needed
108
113
 
109
- In the bootstrap module:
114
+ <% unless use_local_backend? %>In the bootstrap module:
110
115
  - `main.tf` sets up a management space, an s3 bucket to store terraform state files, and an initial SpaceDeployer for the system
111
- - `apply.sh` Helper script to either recreate the state locally or call `terraform apply` Any arguments are passed through to the `apply` call
112
- - `imports.tf` import blocks to create a new local state file when new developers need to access the state file. This file is automatically generated by calling `./apply.sh` and should be checked into git on any changes
113
- - `users.auto.tfvars` this file defines the list of cloud.gov accounts that should have access to the terraform state bucket
114
-
115
- In the sandbox_bot module:
116
- - `main.tf` sets up a cloud.gov SpaceDeployer to manage the sandbox environment and outputs its credentials into the main module `secrets.auto.tfvars`
117
- - `run.sh` Helper script to set up a separate local state file for each sandbox name. In normal use this will only ever be called by `./terraform.sh`
116
+ - `apply.sh` Helper script to setup terraform and call `terraform apply`. Any arguments are passed through to the `apply` call
117
+ - `users.auto.tfvars` this file defines the list of cloud.gov accounts that should have access to the management space<% if use_gitlab_backend? %>
118
+ - `setup_shadowenv.sh` helper script to set terraform backend values using the gitlab http backend in shadowenv<% else %>
119
+ - `imports.tf` import blocks to create a new local state file when new developers need to access the state file. This file is automatically generated by calling `./apply.sh` and should be checked into git on any changes<% end %><% end %>
@@ -14,11 +14,6 @@ data "archive_file" "src" {
14
14
  ]
15
15
  }
16
16
 
17
- locals {
18
- host_name = coalesce(var.host_name, "${local.app_name}-${var.env}")
19
- domain = coalesce(var.custom_domain_name, "app.cloud.gov")
20
- }
21
-
22
17
  resource "cloudfoundry_app" "app" {
23
18
  name = "${local.app_name}-${var.env}"
24
19
  space_name = var.cf_space_name
@@ -28,7 +23,7 @@ resource "cloudfoundry_app" "app" {
28
23
  source_code_hash = data.archive_file.src.output_base64sha256
29
24
  buildpacks = ["ruby_buildpack"]
30
25
  strategy = "rolling"
31
- routes = [{ route = "${local.host_name}.${local.domain}" }]
26
+ enable_ssh = var.allow_ssh
32
27
 
33
28
  environment = {
34
29
  RAILS_ENV = var.env
@@ -1,18 +1,18 @@
1
1
  locals {
2
2
  cf_org_name = "<%= cloud_gov_organization %>"
3
- app_name = "<%= app_name %>"
4
- space_deployers = setunion([var.cf_user], var.space_deployers)
3
+ app_name = "<%= app_name.tr("_", "-") %>"<% if terraform_manage_spaces? %>
4
+ space_deployers = setunion([var.cf_user], var.space_deployers)<% end %>
5
5
  }
6
-
7
6
  <% if terraform_manage_spaces? %>
8
7
  module "app_space" {
9
- source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.1.0"
8
+ source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
10
9
 
11
10
  cf_org_name = local.cf_org_name
12
11
  cf_space_name = var.cf_space_name
13
- allow_ssh = var.allow_space_ssh
12
+ allow_ssh = var.allow_ssh
14
13
  deployers = local.space_deployers
15
14
  developers = var.space_developers
15
+ auditors = var.space_auditors
16
16
  security_group_names = ["trusted_local_networks_egress"]
17
17
  }
18
18
  <% else %>
@@ -31,9 +31,8 @@ resource "cloudfoundry_security_group_space_bindings" "trusted_egress_binding" {
31
31
  running_spaces = [data.cloudfoundry_space.app_space.id]
32
32
  }
33
33
  <% end %>
34
-
35
34
  module "database" {
36
- source = "github.com/gsa-tts/terraform-cloudgov//database?ref=v2.1.0"
35
+ source = "github.com/gsa-tts/terraform-cloudgov//database?ref=v2.3.0"
37
36
 
38
37
  cf_space_id = <% if terraform_manage_spaces? %>module.app_space.space_id<% else %>data.cloudfoundry_space.app_space.id<% end %>
39
38
  name = "${local.app_name}-rds-${var.env}"
@@ -43,7 +42,7 @@ module "database" {
43
42
  }
44
43
  <% if has_active_job? %>
45
44
  module "redis" {
46
- source = "github.com/gsa-tts/terraform-cloudgov//redis?ref=v2.1.0"
45
+ source = "github.com/gsa-tts/terraform-cloudgov//redis?ref=v2.3.0"
47
46
 
48
47
  cf_space_id = <% if terraform_manage_spaces? %>module.app_space.space_id<% else %>data.cloudfoundry_space.app_space.id<% end %>
49
48
  name = "${local.app_name}-redis-${var.env}"
@@ -51,10 +50,9 @@ module "redis" {
51
50
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
52
51
  depends_on = [module.app_space]<% end %>
53
52
  }
54
- <% end %>
55
- <% if has_active_storage? %>
53
+ <% end %><% if has_active_storage? %>
56
54
  module "s3" {
57
- source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.1.0"
55
+ source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.3.0"
58
56
 
59
57
  cf_space_id = <% if terraform_manage_spaces? %>module.app_space.space_id<% else %>data.cloudfoundry_space.app_space.id<% end %>
60
58
  name = "${local.app_name}-s3-${var.env}"
@@ -64,7 +62,7 @@ module "s3" {
64
62
  }
65
63
 
66
64
  module "clamav" {
67
- source = "github.com/gsa-tts/terraform-cloudgov//clamav?ref=v2.1.0"
65
+ source = "github.com/gsa-tts/terraform-cloudgov//clamav?ref=v2.3.0"
68
66
 
69
67
  cf_org_name = local.cf_org_name
70
68
  cf_space_name = var.cf_space_name
@@ -76,31 +74,44 @@ module "clamav" {
76
74
  }
77
75
 
78
76
  resource "cloudfoundry_network_policy" "clamav_routing" {
79
- provider = cloudfoundry-community
80
- policy {
77
+ policies = [{
81
78
  source_app = cloudfoundry_app.app.id
82
79
  destination_app = module.clamav.app_id
83
80
  port = "61443"
84
- }
81
+ }]
85
82
  }
86
83
  <% end %>
87
-
88
- ###########################################################################
84
+ ###########################################################################<% if terraform_manage_spaces? %>
85
+ # Before setting var.custom_domain_name, ensure the ACME challenge record has been created:
86
+ # See https://cloud.gov/docs/services/external-domain-service/#how-to-create-an-instance-of-this-service<% else %>
89
87
  # Before setting var.custom_domain_name, perform the following steps:
90
88
  # 1) Domain must be manually created by an OrgManager:
91
89
  # cf create-domain var.cf_org_name var.domain_name
92
90
  # 2) ACME challenge record must be created.
93
- # See https://cloud.gov/docs/services/external-domain-service/#how-to-create-an-instance-of-this-service
91
+ # See https://cloud.gov/docs/services/external-domain-service/#how-to-create-an-instance-of-this-service<% end %>
94
92
  ###########################################################################
95
93
  module "domain" {
96
94
  count = (var.custom_domain_name == null ? 0 : 1)
97
- source = "github.com/gsa-tts/terraform-cloudgov//domain?ref=v2.1.0"
95
+ source = "github.com/gsa-tts/terraform-cloudgov//domain?ref=v2.3.0"
98
96
 
99
97
  cf_org_name = local.cf_org_name
100
98
  cf_space = <% if terraform_manage_spaces? %>module.app_space.space<% else %>data.cloudfoundry_space.app_space<% end %>
101
99
  cdn_plan_name = "domain"
102
100
  domain_name = var.custom_domain_name
101
+ create_domain = <%= terraform_manage_spaces? ? "true" : "false" %>
102
+ app_ids = [cloudfoundry_app.app.id]
103
103
  host_name = var.host_name<% if terraform_manage_spaces? %>
104
104
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
105
105
  depends_on = [module.app_space]<% end %>
106
106
  }
107
+ module "app_route" {
108
+ count = (var.custom_domain_name == null ? 1 : 0)
109
+ source = "github.com/gsa-tts/terraform-cloudgov//app_route?ref=v2.3.0"
110
+
111
+ cf_org_name = local.cf_org_name
112
+ cf_space_name = var.cf_space_name
113
+ app_ids = [cloudfoundry_app.app.id]
114
+ hostname = coalesce(var.host_name, "${local.app_name}-${var.env}")<% if terraform_manage_spaces? %>
115
+ # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
116
+ depends_on = [module.app_space]<% end %>
117
+ }
@@ -8,3 +8,6 @@ web_memory = "512M"
8
8
  <% if has_active_storage? %>s3_plan_name = "basic"<% end %>
9
9
  <% if has_active_job? %>redis_plan_name = "TKTK-production-redis-plan"<% end %>
10
10
  <% if has_active_job? %>worker_memory = "512M"<% end %>
11
+ space_auditors = [
12
+ # enter cloud.gov usernames that should have access to audit logs
13
+ ]
@@ -1,32 +1,12 @@
1
1
  terraform {
2
2
  required_version = "~> 1.10"
3
- required_providers {<% if has_active_storage? %>
4
- cloudfoundry-community = {
5
- source = "cloudfoundry-community/cloudfoundry"
6
- version = "0.53.1"
7
- }<% end %>
3
+ required_providers {
8
4
  cloudfoundry = {
9
5
  source = "cloudfoundry/cloudfoundry"
10
- version = "1.2.0"
6
+ version = "~> 1.7"
11
7
  }
12
8
  }
13
9
 
14
- backend "s3" {
15
- encrypt = true
16
- use_lockfile = true
17
- region = "us-gov-west-1"
18
- }
19
- }
10
+ <%= backend_block %>}
20
11
 
21
- provider "cloudfoundry" {
22
- api_url = "https://api.fr.cloud.gov"
23
- user = var.cf_user
24
- password = var.cf_password
25
- }
26
- <% if has_active_storage? %>
27
- provider "cloudfoundry-community" {
28
- api_url = "https://api.fr.cloud.gov"
29
- user = var.cf_user
30
- password = var.cf_password
31
- }
32
- <% end %>
12
+ provider "cloudfoundry" {}
@@ -1,8 +1,8 @@
1
- cf_space_name = "<%= cloud_gov_staging_space %>"
2
- env = "staging"
3
- allow_space_ssh = true
1
+ cf_space_name = "<%= cloud_gov_staging_space %>"
2
+ env = "staging"
3
+ allow_ssh = true
4
4
  # host_name must be unique across cloud.gov, default is "<%= app_name %>-${var.env}"
5
- host_name = null
5
+ host_name = null<% if terraform_manage_spaces? %>
6
6
  space_developers = [
7
7
  # enter developer emails that should have ssh access to staging
8
- ]
8
+ ]<% end %>
@@ -20,8 +20,8 @@ Options:
20
20
  "
21
21
 
22
22
 
23
- rmk=`cat $rmk_file || echo -n ""`
24
- env=""
23
+ rmk=$(cat $rmk_file || echo -n "")
24
+ env="<% unless terraform_manage_spaces? %>staging<% end %>"
25
25
  force=""
26
26
  args_to_shift=0
27
27
 
@@ -54,7 +54,21 @@ done
54
54
  shift $args_to_shift
55
55
  if [[ "$1" = "--" ]]; then
56
56
  shift 1
57
- fi
57
+ fi<% if use_gitlab_backend? %>
58
+
59
+ if [ -z "$GITLAB_PROJECT_ID" ] || [ -z "$GITLAB_HOSTNAME" ]; then
60
+ echo "GITLAB_PROJECT_ID or GITLAB_HOSTNAME have not been set. Running bootstrap/setup_shadowenv.sh first"
61
+ (cd bootstrap && ./setup_shadowenv.sh)
62
+ eval "$(shadowenv hook)"
63
+ fi<% elsif use_s3_backend? %>
64
+
65
+ if [[ ! -f .shadowenv.d/500_tf_backend_secrets.lisp ]]; then
66
+ echo "=============================================================================================================="
67
+ echo "= Recreating backend config file. It is fine if this step wants to delete any local_sensitive_file resources"
68
+ echo "=============================================================================================================="
69
+ (cd bootstrap && ./apply.sh $force)
70
+ shadowenv trust && eval "$(shadowenv hook)"
71
+ fi<% end %>
58
72
 
59
73
  if [[ -z "$env" ]]; then
60
74
  echo "-e <ENV_NAME> is required"
@@ -70,66 +84,37 @@ fi
70
84
  # ensure we're logged in via cli
71
85
  cf spaces &> /dev/null || cf login -a api.fr.cloud.gov --sso
72
86
 
73
- tfm_needs_init=true
87
+ tfm_needs_init=true<% if use_gitlab_backend? %>
88
+ tf_state_address="https://$GITLAB_HOSTNAME/api/v4/projects/$GITLAB_PROJECT_ID/terraform/state/$env"
74
89
  if [[ -f .terraform/terraform.tfstate ]]; then
75
- backend_state_env=`cat .terraform/terraform.tfstate | jq -r ".backend.config.key" | cut -d '.' -f3`
76
- if [[ "$backend_state_env" = "$env" ]]; then
90
+ backend_state_address=$(cat .terraform/terraform.tfstate | jq -r ".backend.config.address")
91
+ if [[ "$backend_state_address" = "$tf_state_address" ]]; then
77
92
  tfm_needs_init=false
78
93
  fi
79
- fi
80
-
81
- if [[ $tfm_needs_init = true ]]; then
82
- if [[ ! -f secrets.backend.tfvars ]]; then
83
- echo "=============================================================================================================="
84
- echo "= Recreating backend config file. It is fine if this step wants to delete any local_sensitive_file resources"
85
- echo "=============================================================================================================="
86
- (cd bootstrap && ./apply.sh $force)
94
+ fi<% elsif use_s3_backend? %>
95
+ if [[ -f .terraform/terraform.tfstate ]]; then
96
+ backend_state_env=$(cat .terraform/terraform.tfstate | jq -r ".backend.config.key" | cut -d '.' -f3)
97
+ if [[ "$backend_state_env" = "$env" ]]; then
98
+ tfm_needs_init=false
87
99
  fi
88
- terraform init -backend-config=secrets.backend.tfvars -backend-config="key=terraform.tfstate.$env" -reconfigure
89
- fi
90
-
91
- echo "=============================================================================================================="
92
- echo "= Creating a bot deployer for $env"
93
- echo "=============================================================================================================="
94
- <% if terraform_manage_spaces? %>
95
- if [[ "$env" = "staging" ]] || [[ "$env" = "production" ]]; then
96
- (cd bootstrap && ./apply.sh -var create_bot_secrets_file=true $force)
97
100
  else
98
- (cd sandbox_bot && ./run.sh "$env" apply $force)
99
- fi
100
- <% else %>
101
- if [[ ! -f secrets.auto.tfvars ]]; then
102
- ../bin/ops/create_service_account.sh -s <%= cloud_gov_staging_space %> -u terraform-deployer -n > secrets.auto.tfvars
103
- fi
104
- <% end %>
105
-
106
- if [[ -f secrets.backend.tfvars ]]; then
107
- rm secrets.backend.tfvars
101
+ echo "Sleeping for 10 seconds to avoid a bucket creation race condition"
102
+ sleep 10
103
+ fi<% else %>
104
+ if [[ -f .terraform.lock.hcl ]]; then
105
+ tfm_needs_init=false
106
+ fi<% end %>
107
+
108
+ if [[ $tfm_needs_init = true ]]; then<% if use_gitlab_backend? %>
109
+ terraform init -reconfigure \
110
+ -backend-config="address=$tf_state_address" \
111
+ -backend-config="lock_address=$tf_state_address/lock" \
112
+ -backend-config="unlock_address=$tf_state_address/lock"<% elsif use_s3_backend? %>
113
+ terraform init -backend-config="bucket=$S3_BUCKET_NAME" -backend-config="key=terraform.tfstate.$env" -reconfigure<% else %>
114
+ terraform init<% end %>
108
115
  fi
109
116
 
110
117
  echo "=============================================================================================================="
111
118
  echo "= Calling $cmd $force on the application infrastructure"
112
119
  echo "=============================================================================================================="
113
120
  terraform "$cmd" -var-file="$env.tfvars" -var rails_master_key="$rmk" $force "$@"
114
-
115
- <% if terraform_manage_spaces? %>
116
- if [[ "$cmd" = "destroy" ]] && [[ "$env" != "staging" ]] && [[ "$env" != "production" ]]; then
117
- <% else %>
118
- if [[ "$cmd" = "destroy" ]]; then
119
- <% end %>
120
- if [[ -z "$force" ]]; then
121
- read -p "Destroy the sandbox_bot user? (y/n) " confirm
122
- if [[ "$confirm" != "y" ]]; then
123
- exit 0
124
- fi
125
- fi
126
- echo "=============================================================================================================="
127
- echo "= Destroying the sandbox_bot user"
128
- echo "=============================================================================================================="
129
- <% if terraform_manage_spaces? %>
130
- (cd sandbox_bot && ./run.sh "$env" destroy -auto-approve)
131
- <% else %>
132
- ../bin/ops/destroy_service_account.sh -s <%= cloud_gov_staging_space %> -u terraform-deployer
133
- rm secrets.auto.tfvars
134
- <% end %>
135
- fi
@@ -1,19 +1,14 @@
1
- # Deploy user settings
1
+ <% if terraform_manage_spaces? %># Deploy user settings
2
2
  variable "cf_user" {
3
3
  type = string
4
- description = "The service account running the terraform"
4
+ description = "The user email or service account running the terraform"
5
5
  }
6
- variable "cf_password" {
7
- type = string
8
- sensitive = true
9
- description = "The service account password"
10
- }
11
-
6
+ <% end %>
12
7
  # app_space settings
13
8
  variable "cf_space_name" {
14
9
  type = string
15
10
  description = "The space name to deploy the app into"
16
- }
11
+ }<% if terraform_manage_spaces? %>
17
12
  variable "space_deployers" {
18
13
  type = set(string)
19
14
  default = []
@@ -24,10 +19,15 @@ variable "space_developers" {
24
19
  default = []
25
20
  description = "A list of users to be granted SpaceDeveloper on cf_space_name"
26
21
  }
27
- variable "allow_space_ssh" {
22
+ variable "space_auditors" {
23
+ type = set(string)
24
+ default = []
25
+ description = "A list of users to be granted SpaceAuditor on cf_space_name"
26
+ }<% end %>
27
+ variable "allow_ssh" {
28
28
  type = bool
29
29
  default = false
30
- description = "Whether to allow ssh to cf_space_name"
30
+ description = "Whether to allow ssh to the space and/or app"
31
31
  }
32
32
 
33
33
  # supporting services settings
@@ -50,7 +50,6 @@ variable "s3_plan_name" {
50
50
  description = "The name of the s3 plan to use"
51
51
  }
52
52
  <% end %>
53
-
54
53
  # routing settings
55
54
  variable "custom_domain_name" {
56
55
  type = string
@@ -8,6 +8,8 @@ module RailsTemplate18f
8
8
  include Base
9
9
  include CloudGovOptions
10
10
 
11
+ class_option :backend, default: "s3", desc: "Which terraform backend to use. Options: [s3, gitlab, local]"
12
+
11
13
  desc <<~DESC
12
14
  Description:
13
15
  Install terraform files for cloud.gov database and s3 services
@@ -16,18 +18,43 @@ module RailsTemplate18f
16
18
  def install
17
19
  directory "terraform", mode: :preserve
18
20
  chmod "terraform/terraform.sh", 0o755
19
- if terraform_manage_spaces?
20
- template "full_bootstrap/main.tf", "terraform/bootstrap/main.tf"
21
- copy_file "full_bootstrap/imports.tf.tftpl", "terraform/bootstrap/templates/imports.tf.tftpl"
21
+ end
22
+
23
+ def install_bootstrap
24
+ if use_gitlab_backend?
25
+ directory "gitlab_bootstrap", "terraform/bootstrap", mode: :preserve
26
+ elsif use_s3_backend?
27
+ directory "s3_bootstrap/common", "terraform/bootstrap", mode: :preserve
28
+ if terraform_manage_spaces?
29
+ template "s3_bootstrap/full/main.tf", "terraform/bootstrap/main.tf"
30
+ copy_file "s3_bootstrap/full/imports.tf.tftpl", "terraform/bootstrap/templates/imports.tf.tftpl"
31
+ else
32
+ template "s3_bootstrap/sandbox/main.tf", "terraform/bootstrap/main.tf"
33
+ copy_file "s3_bootstrap/sandbox/imports.tf.tftpl", "terraform/bootstrap/templates/imports.tf.tftpl"
34
+ end
22
35
  else
23
- template "sandbox_bootstrap/main.tf", "terraform/bootstrap/main.tf"
24
- copy_file "sandbox_bootstrap/imports.tf.tftpl", "terraform/bootstrap/templates/imports.tf.tftpl"
36
+ remove_dir "terraform/.shadowenv.d"
37
+ end
38
+ unless terraform_manage_spaces?
25
39
  remove_file "terraform/bootstrap/users.auto.tfvars"
26
- remove_dir "terraform/sandbox_bot"
27
40
  remove_file "terraform/production.tfvars"
28
41
  end
29
42
  end
30
43
 
44
+ def install_shadowenv
45
+ unless use_local_backend?
46
+ append_to_file "Brewfile", <<~EOB
47
+
48
+ # shadowenv for loading terraform backend secrets
49
+ brew "shadowenv"
50
+ EOB
51
+ insert_into_file "README.md", indent(<<~EOR), after: /\* Install homebrew dependencies: `brew bundle`\n/
52
+ * [shadowenv](https://shopify.github.io/shadowenv/)
53
+ * See the [quick start](https://shopify.github.io/shadowenv/getting-started/#add-to-your-shell-profile) for instructions on loading shadowenv in your shell
54
+ EOR
55
+ end
56
+ end
57
+
31
58
  def ignore_files
32
59
  unless skip_git?
33
60
  append_to_file ".gitignore", <<~EOM
@@ -87,6 +114,51 @@ module RailsTemplate18f
87
114
  done
88
115
  EOM
89
116
  end
117
+
118
+ def use_gitlab_backend?
119
+ backend == "gitlab"
120
+ end
121
+
122
+ def use_s3_backend?
123
+ backend == "s3"
124
+ end
125
+
126
+ def use_local_backend?
127
+ backend == "local"
128
+ end
129
+
130
+ def backend
131
+ options[:backend]
132
+ end
133
+
134
+ def backend_unless_local
135
+ if use_local_backend?
136
+ "<s3 or gitlab>"
137
+ else
138
+ backend
139
+ end
140
+ end
141
+
142
+ def backend_block
143
+ if use_gitlab_backend?
144
+ <<EOB
145
+ backend "http" {
146
+ lock_method = "POST"
147
+ unlock_method = "DELETE"
148
+ retry_wait_min = 5
149
+ }
150
+ EOB
151
+ elsif use_s3_backend?
152
+ <<EOB
153
+ backend "s3" {
154
+ encrypt = true
155
+ use_lockfile = true
156
+ use_fips_endpoint = true
157
+ region = "us-gov-west-1"
158
+ }
159
+ EOB
160
+ end
161
+ end
90
162
  end
91
163
  end
92
164
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsTemplate18f
4
- VERSION = "2.0.0"
4
+ VERSION = "2.2.0"
5
5
  end