rails_template_18f 2.1.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile.lock +5 -3
  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/cloud_gov_config/cloud_gov_config_generator.rb +0 -8
  8. data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +6 -15
  9. data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +13 -19
  10. data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +0 -4
  11. data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +0 -9
  12. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +2 -2
  13. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +8 -3
  14. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +2 -1
  15. data/lib/generators/rails_template18f/oscal/oscal_generator.rb +15 -1
  16. data/lib/generators/rails_template18f/oscal/templates/bin/trestle.tt +10 -1
  17. data/lib/generators/rails_template18f/oscal/templates/gitlab/trestle.yml.tt +29 -0
  18. data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +1 -1
  19. data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +1 -1
  20. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/apply.sh +25 -0
  21. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/main.tf.tt +98 -0
  22. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +59 -0
  23. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/backend_config.tftpl +6 -0
  24. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/bot_secrets.tftpl +5 -0
  25. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/users.auto.tfvars +5 -0
  26. data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +2 -9
  27. data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +2 -2
  28. data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
  29. data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +38 -26
  30. data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +1 -0
  31. data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +3 -3
  32. data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +2 -8
  33. data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +5 -5
  34. data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +40 -15
  35. data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +6 -6
  36. data/lib/generators/rails_template18f/terraform/terraform_generator.rb +78 -5
  37. data/lib/rails_template18f/version.rb +1 -1
  38. data/template.rb +32 -15
  39. metadata +21 -13
  40. data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
  41. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/assemble-ssp.yml.tt +0 -0
  42. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/validate-ssp.yml +0 -0
  43. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap/templates → gitlab_bootstrap}/bot_secrets.tftpl +0 -0
  44. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → gitlab_bootstrap}/users.auto.tfvars +0 -0
  45. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/apply.sh +0 -0
  46. /data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/imports.tf.tftpl +0 -0
  47. /data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/imports.tf.tftpl +0 -0
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Setup .shadowenv.d/ files for terraform configuration
4
+
5
+ set -e
6
+
7
+ # ensure we're operating with the correct relative paths
8
+ cd `dirname "$0"`
9
+
10
+ shadowenv trust && eval "$(shadowenv hook)"
11
+
12
+ ans=""
13
+ prompt_ans() {
14
+ local prompt="$1"
15
+ local default="$2"
16
+ if [ -n "$default" ]; then
17
+ prompt="$prompt (default: $default)"
18
+ fi
19
+ read -r -p "$prompt: " ans
20
+ }
21
+
22
+ prompt_ans "GitLab hostname" "${GITLAB_HOSTNAME:=gsa.gitlab-dedicated.us}"
23
+ if [ -n "$ans" ]; then
24
+ GITLAB_HOSTNAME="$ans"
25
+ fi
26
+
27
+ prompt_ans "GitLab project id" "$GITLAB_PROJECT_ID"
28
+ if [ -n "$ans" ]; then
29
+ GITLAB_PROJECT_ID="$ans"
30
+ fi
31
+
32
+ if [ ! -d ../.shadowenv.d ]; then
33
+ mkdir ../.shadowenv.d
34
+ fi
35
+
36
+ cat <<EOF > ../.shadowenv.d/100_gitlab_project.lisp
37
+ (provide "gitlab-backend-config")
38
+ (env/set "GITLAB_HOSTNAME" "$GITLAB_HOSTNAME")
39
+ (env/set "GITLAB_PROJECT_ID" "$GITLAB_PROJECT_ID")
40
+ EOF
41
+
42
+ prompt_ans "GitLab username" "$TF_HTTP_USERNAME"
43
+ if [ -n "$ans" ]; then
44
+ TF_HTTP_USERNAME=$ans
45
+ fi
46
+ if [ -z "$TF_HTTP_PASSWORD" ]; then
47
+ prompt_ans "GitLab PAT (with api scope)"
48
+ else
49
+ prompt_ans "GitLab PAT (with api scope, Leave blank to re-use existing PAT)"
50
+ fi
51
+ if [ -n "$ans" ]; then
52
+ TF_HTTP_PASSWORD=$ans
53
+ fi
54
+
55
+ cat <<EOF > ../.shadowenv.d/500_tf_backend_secrets.lisp
56
+ (provide "tf-backend-secrets")
57
+ (env/set "TF_HTTP_USERNAME" "$TF_HTTP_USERNAME")
58
+ (env/set "TF_HTTP_PASSWORD" "$TF_HTTP_PASSWORD")
59
+ EOF
@@ -0,0 +1,6 @@
1
+ (provide "terraform-backend-config")
2
+ (env/set "S3_BUCKET_NAME" "${creds.bucket}")
3
+ (env/set "AWS_ACCESS_KEY_ID" "${creds.access_key_id}")
4
+ (env/set "AWS_SECRET_ACCESS_KEY" "${creds.secret_access_key}")
5
+ ; not a secret, but setting it here enables the aws cli to work when in the terraform directory
6
+ (env/set "AWS_REGION" "${creds.region}")
@@ -0,0 +1,5 @@
1
+ # Generated via bootstrap module. Remove this file when finished
2
+ # credentials for service "${service_name}"/"${key_name}"
3
+
4
+ cf_user = "${username}"
5
+ cf_password = "${password}"
@@ -0,0 +1,5 @@
1
+ terraform_users = [
2
+ # add your terraform_users list here: example values:
3
+ # "team.member@gsa.gov",
4
+ # "cf_user-guid-value-for-space-developer-service-account",
5
+ ]
@@ -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
  }
@@ -134,7 +134,7 @@ locals {
134
134
  }
135
135
  resource "local_sensitive_file" "bucket_creds" {
136
136
  content = local.backend_config
137
- filename = "${path.module}/../secrets.backend.tfvars"
137
+ filename = "${path.module}/../.shadowenv.d/500_tf_backend_secrets.lisp"
138
138
  file_permission = "0600"
139
139
  }
140
140
 
@@ -150,10 +150,3 @@ resource "local_sensitive_file" "bot_secrets_file" {
150
150
  password = local.sa_cf_password
151
151
  })
152
152
  }
153
-
154
- output "mgmt_space_id" {
155
- value = module.mgmt_space.space_id
156
- }
157
- output "mgmt_org_id" {
158
- value = data.cloudfoundry_org.org.id
159
- }
@@ -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
  }
@@ -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
 
@@ -10,48 +10,57 @@ is very limited.
10
10
  When you are ready to move the application to a non-sandbox cloud.gov organization, please re-run the terraform generator with…
11
11
 
12
12
  ```bash
13
- 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 %>
14
14
  ```
15
15
 
16
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.
17
17
  <% end %>
18
- ## Terraform State Credentials
18
+ <% unless use_local_backend? %>## Terraform State Credentials
19
19
 
20
- The `bootstrap` module is used to create an s3 bucket for later terraform runs to store their state in as well as
21
- create credentials files so developers can use that s3 bucket to create their own sandbox environments.
20
+ The `bootstrap` module is used to create resources that must be created by an individual developers credentials before automation can be run:
22
21
 
23
- ### Initial project setup
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
+
25
+ ### Initial <%= use_gitlab_backend? ? "CI/CD pipeline" : "project" %> setup
24
26
 
25
27
  These steps only need to be run once per project.
26
28
 
27
- 1. `cd bootstrap`<% if terraform_manage_spaces? %>
28
- 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 %>
29
33
  1. Run `./apply.sh -var create_bot_secrets_file=true`
30
- 1. Add `imports.tf` to git and commit the changes
31
- 1. Setup your CI/CD Pipeline to run terraform and deploy your staging and production environments
32
- 1. Copy backend credentials from `/terraform/secrets.backend.tfvars` to your CI/CD secrets using the instructions in the base README
33
- 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
34
- 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
35
40
 
36
41
  ### To make changes to the bootstrap module
37
42
 
38
- *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 %>*
39
44
 
40
45
  1. Make your changes
41
- 1. Run `./apply.sh` and verify the plan before entering `yes`
42
- 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 %>
43
48
 
44
- ## 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? %>
45
53
 
46
54
  ### Pre-requisites:
47
55
 
48
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.
49
- <% 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 %>
50
58
 
51
59
  ### Steps:
52
-
60
+ <% if use_gitlab_backend? %>
61
+ 1. Run `./bootstrap/setup_shadowenv.sh`<% end %>
53
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
54
- 1. Add a `cf_user = "your.email@agency.gov"` line to the `sandbox-<NAME>.tfvars` file<% end %>
63
+ 1. Add a `cf_user = "your.email@gsa.gov"` line to the `sandbox-<NAME>.tfvars` file<% end %>
55
64
 
56
65
  1. Run terraform plan with:
57
66
  ```bash
@@ -70,17 +79,19 @@ These steps only need to be run once per project.
70
79
 
71
80
  ## Structure
72
81
 
73
- ```
82
+ ```<% unless use_local_backend? %>
74
83
  |- bootstrap/
75
84
  | |- main.tf
76
85
  | |- apply.sh
86
+ | |- users.auto.tfvars<% if use_gitlab_backend? %>
87
+ | |- setup_shadowenv.sh
88
+ | |- bot_secrets.tftpl<% else %>
77
89
  | |- imports.tf (automatically generated)
78
- | |- users.auto.tfvars
79
90
  | |- terraform.tfstate(.backup) (automatically generated)
80
91
  | |- templates/
81
92
  | |- backend_config.tftpl
82
93
  | |- bot_secrets.tftpl
83
- | |- imports.tf.tftpl
94
+ | |- imports.tf.tftpl<% end %><% end %>
84
95
  |- dist/
85
96
  | |- src.zip (automatically generated)
86
97
  |- README.md
@@ -100,8 +111,9 @@ In the root module:
100
111
  - `providers.tf` lists the required providers and shell backend config
101
112
  - `variables.tf` lists the variables that will be needed
102
113
 
103
- In the bootstrap module:
114
+ <% unless use_local_backend? %>In the bootstrap module:
104
115
  - `main.tf` sets up a management space, an s3 bucket to store terraform state files, and an initial SpaceDeployer for the system
105
- - `apply.sh` Helper script to either recreate the state locally or call `terraform apply` Any arguments are passed through to the `apply` call
106
- - `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
107
- - `users.auto.tfvars` this file defines the list of cloud.gov accounts that should have access to the terraform state bucket
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 %>
@@ -23,6 +23,7 @@ resource "cloudfoundry_app" "app" {
23
23
  source_code_hash = data.archive_file.src.output_base64sha256
24
24
  buildpacks = ["ruby_buildpack"]
25
25
  strategy = "rolling"
26
+ enable_ssh = var.allow_ssh
26
27
 
27
28
  environment = {
28
29
  RAILS_ENV = var.env
@@ -1,7 +1,7 @@
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
6
  <% if terraform_manage_spaces? %>
7
7
  module "app_space" {
@@ -9,7 +9,7 @@ module "app_space" {
9
9
 
10
10
  cf_org_name = local.cf_org_name
11
11
  cf_space_name = var.cf_space_name
12
- allow_ssh = var.allow_space_ssh
12
+ allow_ssh = var.allow_ssh
13
13
  deployers = local.space_deployers
14
14
  developers = var.space_developers
15
15
  auditors = var.space_auditors
@@ -3,16 +3,10 @@ terraform {
3
3
  required_providers {
4
4
  cloudfoundry = {
5
5
  source = "cloudfoundry/cloudfoundry"
6
- version = "1.5.0"
6
+ version = "~> 1.7"
7
7
  }
8
8
  }
9
9
 
10
- backend "s3" {
11
- encrypt = true
12
- use_lockfile = true
13
- use_fips_endpoint = true
14
- region = "us-gov-west-1"
15
- }
16
- }
10
+ <%= backend_block %>}
17
11
 
18
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,23 +84,34 @@ 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"
89
+ if [[ -f .terraform/terraform.tfstate ]]; then
90
+ backend_state_address=$(cat .terraform/terraform.tfstate | jq -r ".backend.config.address")
91
+ if [[ "$backend_state_address" = "$tf_state_address" ]]; then
92
+ tfm_needs_init=false
93
+ fi
94
+ fi<% elsif use_s3_backend? %>
74
95
  if [[ -f .terraform/terraform.tfstate ]]; then
75
- backend_state_env=`cat .terraform/terraform.tfstate | jq -r ".backend.config.key" | cut -d '.' -f3`
96
+ backend_state_env=$(cat .terraform/terraform.tfstate | jq -r ".backend.config.key" | cut -d '.' -f3)
76
97
  if [[ "$backend_state_env" = "$env" ]]; then
77
98
  tfm_needs_init=false
78
99
  fi
79
- fi
100
+ else
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 %>
80
107
 
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 -auto-approve)
87
- fi
88
- terraform init -backend-config=secrets.backend.tfvars -backend-config="key=terraform.tfstate.$env" -reconfigure
89
- rm secrets.backend.tfvars
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 %>
90
115
  fi
91
116
 
92
117
  echo "=============================================================================================================="
@@ -1,9 +1,9 @@
1
- # Deploy user settings
1
+ <% if terraform_manage_spaces? %># Deploy user settings
2
2
  variable "cf_user" {
3
3
  type = string
4
4
  description = "The user email or service account running the terraform"
5
5
  }
6
-
6
+ <% end %>
7
7
  # app_space settings
8
8
  variable "cf_space_name" {
9
9
  type = string
@@ -23,12 +23,12 @@ variable "space_auditors" {
23
23
  type = set(string)
24
24
  default = []
25
25
  description = "A list of users to be granted SpaceAuditor on cf_space_name"
26
- }
27
- variable "allow_space_ssh" {
26
+ }<% end %>
27
+ variable "allow_ssh" {
28
28
  type = bool
29
29
  default = false
30
- description = "Whether to allow ssh to cf_space_name"
31
- }<% end %>
30
+ description = "Whether to allow ssh to the space and/or app"
31
+ }
32
32
 
33
33
  # supporting services settings
34
34
  variable "rds_plan_name" {
@@ -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,17 +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
40
  remove_file "terraform/production.tfvars"
27
41
  end
28
42
  end
29
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
+
30
58
  def ignore_files
31
59
  unless skip_git?
32
60
  append_to_file ".gitignore", <<~EOM
@@ -86,6 +114,51 @@ module RailsTemplate18f
86
114
  done
87
115
  EOM
88
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
89
162
  end
90
163
  end
91
164
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsTemplate18f
4
- VERSION = "2.1.0"
4
+ VERSION = "2.2.0"
5
5
  end
data/template.rb CHANGED
@@ -102,6 +102,10 @@ cloud_gov_production_space = default_prod_space if cloud_gov_production_space.bl
102
102
  @gitlab_ci = yes?("Create GitLab CI config? (y/n)")
103
103
  @github_actions = yes?("Create GitHub Actions? (y/n)")
104
104
  @circleci_pipeline = yes?("Create CircleCI config? (y/n)")
105
+ local_terraform_backend = false
106
+ unless [@gitlab_ci, @github_actions, @circleci_pipeline].any?
107
+ local_terraform_backend = yes?("Use a local file to store terraform state? This is only appropriate for short-lived proofs of concept but will make it easier to deploy for a single dev. (y/n)")
108
+ end
105
109
  newrelic = yes?("Create FEDRAMP New Relic config files? (y/n)")
106
110
  dap = yes?("If this will be a public site, should we include Digital Analytics Program code? (y/n)")
107
111
  supported_languages = []
@@ -128,22 +132,27 @@ register_announcement("Documentation", <<~EOM)
128
132
  EOM
129
133
 
130
134
  # do early so later generators register files in the correct location
131
- if compliance_trestle
132
- after_bundle do
133
- generator_arguments = []
134
- generator_arguments << "--oscal_repo=#{compliance_trestle_repo}" if compliance_trestle_submodule
135
- generator_arguments << "--ci=github" if @github_actions
136
- generator_arguments << "--ci=gitlab" if @gitlab_ci
137
- generator_arguments << "--ci=circleci" if @circleci_pipeline
138
- generate "rails_template18f:oscal", *generator_arguments
139
- end
140
- register_announcement("OSCAL Documentation", <<~EOM)
141
- OSCAL files have been generated with some default implementation statements in `doc/compliance/oscal`
135
+ run_oscal_generator = ->(register_announcement = false) {
136
+ if compliance_trestle
137
+ after_bundle do
138
+ generator_arguments = []
139
+ generator_arguments << "--oscal_repo=#{compliance_trestle_repo}" if compliance_trestle_submodule
140
+ generator_arguments << "--ci=github" if @github_actions
141
+ generator_arguments << "--ci=gitlab" if @gitlab_ci
142
+ generator_arguments << "--ci=circleci" if @circleci_pipeline
143
+ generate "rails_template18f:oscal", *generator_arguments
144
+ end
145
+ if register_announcement
146
+ register_announcement("OSCAL Documentation", <<~EOM)
147
+ OSCAL files have been generated with some default implementation statements in `doc/compliance/oscal`
142
148
 
143
- All generated statements must be reviewed for accuracy with your system's implementation before being
144
- submitted for authorization.
145
- EOM
146
- end
149
+ All generated statements must be reviewed for accuracy with your system's implementation before being
150
+ submitted for authorization.
151
+ EOM
152
+ end
153
+ end
154
+ }
155
+ run_oscal_generator.call(true)
147
156
 
148
157
  # ensure dependencies are installed
149
158
  copy_file "Brewfile"
@@ -401,6 +410,11 @@ after_bundle do
401
410
  "--cg-staging=#{cloud_gov_staging_space}",
402
411
  "--cg-prod=#{cloud_gov_production_space}"
403
412
  ]
413
+ if @gitlab_ci
414
+ generator_arguments << "--backend=gitlab"
415
+ elsif local_terraform_backend
416
+ generator_arguments << "--backend=local"
417
+ end
404
418
  generate "rails_template18f:terraform", *generator_arguments
405
419
  end
406
420
  if cloud_gov_org_tktk?
@@ -467,6 +481,9 @@ if @gitlab_ci
467
481
  EOM
468
482
  end
469
483
 
484
+ # rerun so we can update the correct CI systems
485
+ run_oscal_generator.call
486
+
470
487
  if auditree
471
488
  after_bundle do
472
489
  generate "rails_template18f:auditree", "--evidence_locker=#{auditree_evidence_repo}"