rails_template_18f 1.3.0 → 2.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +64 -61
- data/README.md +11 -16
- data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +7 -6
- data/lib/generators/rails_template18f/circleci/circleci_generator.rb +28 -27
- data/lib/generators/rails_template18f/circleci/templates/Dockerfile.ci.tt +0 -1
- data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +162 -163
- data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +9 -1
- data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +31 -30
- data/lib/generators/rails_template18f/github_actions/templates/github/actions/compile-assets/action.yml +50 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/actions/setup-project/action.yml.tt +4 -8
- data/lib/generators/rails_template18f/github_actions/templates/github/dependabot.yml.tt +2 -4
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +74 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +74 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-daily-scan.yml.tt +10 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-scan.yml.tt +1 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/pa11y.yml.tt +2 -2
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +49 -4
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +49 -4
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/validate-ssp.yml +2 -2
- data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +147 -0
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/node.yml.tt +11 -0
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +75 -0
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/ruby.yml +7 -0
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +28 -0
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +212 -0
- data/lib/generators/rails_template18f/i18n_js/i18n_js_generator.rb +2 -2
- data/lib/generators/rails_template18f/i18n_js/templates/app/javascript/{i18n.js → i18n/index.js} +1 -1
- data/lib/generators/rails_template18f/i18n_js/templates/config/i18n-js.yml +1 -1
- data/lib/generators/rails_template18f/newrelic/newrelic_generator.rb +4 -2
- data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +71 -55
- data/lib/generators/rails_template18f/sidekiq/sidekiq_generator.rb +8 -17
- data/lib/generators/rails_template18f/terraform/templates/full_bootstrap/imports.tf.tftpl +25 -0
- data/lib/generators/rails_template18f/terraform/templates/full_bootstrap/main.tf.tt +159 -0
- data/lib/generators/rails_template18f/terraform/templates/sandbox_bootstrap/imports.tf.tftpl +10 -0
- data/lib/generators/rails_template18f/terraform/templates/sandbox_bootstrap/main.tf.tt +117 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +69 -95
- data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +57 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/apply.sh +15 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +8 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/bot_secrets.tftpl +5 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/users.auto.tfvars +5 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +117 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/production.tfvars.tt +13 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +18 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +8 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +95 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +98 -0
- data/lib/generators/rails_template18f/terraform/terraform_generator.rb +12 -4
- data/lib/rails_template18f/generators/cloud_gov_options.rb +9 -6
- data/lib/rails_template18f/generators/cloud_gov_parsing.rb +7 -7
- data/lib/rails_template18f/generators.rb +0 -1
- data/lib/rails_template18f/version.rb +1 -1
- data/rails-template-18f.gemspec +4 -4
- data/railsrc +4 -2
- data/railsrc-hotwire +4 -2
- data/template.rb +80 -82
- data/templates/README.md.tt +21 -8
- data/templates/app/assets/stylesheets/uswds-settings.scss +3 -2
- data/templates/app/views/application/_header.html.erb +1 -1
- data/templates/app/views/application/_usa_banner.html.erb +3 -3
- data/templates/bin/ops/create_service_account.sh.tt +20 -11
- data/templates/bin/ops/destroy_service_account.sh.tt +3 -3
- data/templates/browserslistrc +1 -2
- data/templates/doc/compliance/TODO.md +1 -4
- data/templates/{pa11yci.js → pa11yci.js.tt} +5 -0
- metadata +36 -35
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml.tt +0 -50
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml.tt +0 -50
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/import.sh +0 -13
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/main.tf.tt +0 -22
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/providers.tf +0 -16
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/run.sh.tt +0 -40
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/teardown_creds.sh.tt +0 -5
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/variables.tf +0 -2
- data/lib/generators/rails_template18f/terraform/templates/terraform/production/main.tf.tt +0 -90
- data/lib/generators/rails_template18f/terraform/templates/terraform/production/providers.tf +0 -23
- data/lib/generators/rails_template18f/terraform/templates/terraform/production/variables.tf +0 -2
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging/main.tf.tt +0 -70
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging/providers.tf +0 -23
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging/variables.tf +0 -2
- data/lib/rails_template18f/generators/pipeline_options.rb +0 -18
- data/templates/app/assets/images/uswds.js +0 -6
- data/templates/config/deployment/production.yml +0 -3
- data/templates/config/deployment/staging.yml +0 -3
- data/templates/manifest.yml.tt +0 -17
@@ -0,0 +1,212 @@
|
|
1
|
+
# Note that environment variables can be set in several places
|
2
|
+
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
|
3
|
+
|
4
|
+
workflow:
|
5
|
+
rules:
|
6
|
+
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
7
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
8
|
+
- if: $CI_COMMIT_BRANCH == "production"
|
9
|
+
|
10
|
+
stages:
|
11
|
+
- build
|
12
|
+
- test
|
13
|
+
- deploy
|
14
|
+
|
15
|
+
variables:
|
16
|
+
POSTGRES_DB: <%= app_name %>_test
|
17
|
+
POSTGRES_PASSWORD: not-actually-secret
|
18
|
+
POSTGRES_VERSION: <%= postgres_version %>
|
19
|
+
RUBY_VERSION: <%= RUBY_VERSION %>
|
20
|
+
|
21
|
+
include:
|
22
|
+
- local: ".gitlab/ruby.yml"
|
23
|
+
- local: ".gitlab/node.yml"
|
24
|
+
- local: ".gitlab/rails.yml"
|
25
|
+
- local: ".gitlab/terraform.yml"
|
26
|
+
|
27
|
+
default:
|
28
|
+
image: "ruby:${RUBY_VERSION}"
|
29
|
+
before_script:
|
30
|
+
- !reference [.setup-ruby]
|
31
|
+
cache:
|
32
|
+
- !reference [.cache-dependencies, cache]
|
33
|
+
|
34
|
+
build-project:
|
35
|
+
stage: build
|
36
|
+
extends: [.cache-dependencies, .setup-languages]
|
37
|
+
cache:
|
38
|
+
policy: pull-push
|
39
|
+
script:
|
40
|
+
- !reference [.bundle-install]
|
41
|
+
- !reference [.yarn-install]
|
42
|
+
- bin/rake assets:precompile
|
43
|
+
artifacts:
|
44
|
+
expire_in: 1 hour
|
45
|
+
paths:
|
46
|
+
- app/assets/builds
|
47
|
+
- public/assets
|
48
|
+
rules:
|
49
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
50
|
+
|
51
|
+
brakeman-scan:
|
52
|
+
stage: test
|
53
|
+
script:
|
54
|
+
- bin/brakeman --no-pager --ensure-ignore-notes -f sarif -o output.sarif.json
|
55
|
+
artifacts:
|
56
|
+
when: always
|
57
|
+
expose_as: "Brakeman results"
|
58
|
+
paths:
|
59
|
+
- output.sarif.json
|
60
|
+
|
61
|
+
dependency_scanning:
|
62
|
+
stage: test
|
63
|
+
extends: .setup-languages
|
64
|
+
script:
|
65
|
+
- bin/rake bundler:audit
|
66
|
+
- bin/rake yarn:audit
|
67
|
+
- gem install cyclonedx-ruby
|
68
|
+
- cyclonedx-ruby -p . -o ruby_bom.xml
|
69
|
+
artifacts:
|
70
|
+
expose_as: "Ruby SBOM"
|
71
|
+
paths:
|
72
|
+
- ruby_bom.xml
|
73
|
+
|
74
|
+
rspec:
|
75
|
+
stage: test
|
76
|
+
extends: .setup-project
|
77
|
+
script:
|
78
|
+
- bundle exec rspec
|
79
|
+
rules:
|
80
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
81
|
+
|
82
|
+
pa11y_scan:
|
83
|
+
stage: test
|
84
|
+
extends: .run-server
|
85
|
+
script:
|
86
|
+
- !reference [.install-puppet-deps]
|
87
|
+
- yarn run pa11y-ci -c pa11yci.js
|
88
|
+
rules:
|
89
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
90
|
+
|
91
|
+
owasp_scan:
|
92
|
+
extends: .owasp:setup
|
93
|
+
script:
|
94
|
+
- /zap/zap-baseline.py -t http://localhost:3000 -c zap.conf -I -r zap_report.html
|
95
|
+
rules:
|
96
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
97
|
+
|
98
|
+
owasp_daily_scan:
|
99
|
+
extends: .owasp:setup
|
100
|
+
script:
|
101
|
+
- /zap/zap-full-scan.py -t http://localhost:3000 -c zap.conf -I -r zap_report.html
|
102
|
+
rules:
|
103
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
104
|
+
|
105
|
+
terraform:fmt:
|
106
|
+
stage: test
|
107
|
+
extends: .terraform:setup
|
108
|
+
script:
|
109
|
+
- terraform fmt -check -recursive .
|
110
|
+
|
111
|
+
terraform:validate:
|
112
|
+
stage: test
|
113
|
+
extends: .terraform:setup
|
114
|
+
script:
|
115
|
+
- terraform validate
|
116
|
+
|
117
|
+
terraform:assets:staging:
|
118
|
+
extends: .assets:builder
|
119
|
+
cache:
|
120
|
+
- !reference [.cache-dependencies, cache]
|
121
|
+
- key: staging-assets
|
122
|
+
unprotect: true
|
123
|
+
paths:
|
124
|
+
- public/assets
|
125
|
+
- app/assets/builds
|
126
|
+
policy: $CACHE_POLICY
|
127
|
+
variables:
|
128
|
+
RAILS_ENV: staging
|
129
|
+
rules:
|
130
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
131
|
+
when: never
|
132
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
133
|
+
variables:
|
134
|
+
CACHE_POLICY: pull-push
|
135
|
+
- variables:
|
136
|
+
CACHE_POLICY: pull
|
137
|
+
<% if terraform_manage_spaces? %>
|
138
|
+
terraform:assets:production:
|
139
|
+
extends: .assets:builder
|
140
|
+
cache:
|
141
|
+
- !reference [.cache-dependencies, cache]
|
142
|
+
- key: production-assets
|
143
|
+
paths:
|
144
|
+
- public/assets
|
145
|
+
- app/assets/builds
|
146
|
+
policy: $CACHE_POLICY
|
147
|
+
variables:
|
148
|
+
RAILS_ENV: production
|
149
|
+
rules:
|
150
|
+
- if: $CI_COMMIT_BRANCH == "production"
|
151
|
+
variables:
|
152
|
+
CACHE_POLICY: pull-push
|
153
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
154
|
+
variables:
|
155
|
+
CACHE_POLICY: pull
|
156
|
+
<% end %>
|
157
|
+
terraform:plan:staging:
|
158
|
+
extends:
|
159
|
+
- .terraform:setup
|
160
|
+
- .terraform:variables:staging
|
161
|
+
needs: ["terraform:assets:staging"]
|
162
|
+
script:
|
163
|
+
- apk add zip
|
164
|
+
- terraform plan -out=staging_plan.out -var-file=staging.tfvars -var rails_master_key=$RAILS_MASTER_KEY -var cf_user=$CF_USERNAME
|
165
|
+
artifacts:
|
166
|
+
paths:
|
167
|
+
- terraform/staging_plan.out
|
168
|
+
- terraform/dist
|
169
|
+
|
170
|
+
terraform:apply:staging:
|
171
|
+
extends:
|
172
|
+
- .terraform:setup
|
173
|
+
- .terraform:variables:staging
|
174
|
+
needs:
|
175
|
+
- terraform:plan:staging
|
176
|
+
- terraform:assets:staging
|
177
|
+
script:
|
178
|
+
- apk add zip
|
179
|
+
- terraform apply -var-file=staging.tfvars -var rails_master_key=$RAILS_MASTER_KEY -var cf_user=$CF_USERNAME staging_plan.out
|
180
|
+
rules:
|
181
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
182
|
+
when: never
|
183
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
184
|
+
<% if terraform_manage_spaces? %>
|
185
|
+
terraform:plan:production:
|
186
|
+
extends:
|
187
|
+
- .terraform:setup
|
188
|
+
- .terraform:variables:production
|
189
|
+
needs: ["terraform:assets:production"]
|
190
|
+
script:
|
191
|
+
- apk add zip
|
192
|
+
- terraform plan -out=production_plan.out -var-file=production.tfvars -var rails_master_key=$PRODUCTION_RAILS_MASTER_KEY -var cf_user=$CF_USERNAME
|
193
|
+
artifacts:
|
194
|
+
paths:
|
195
|
+
- terraform/production_plan.out
|
196
|
+
- terraform/dist
|
197
|
+
|
198
|
+
terraform:apply:production:
|
199
|
+
extends:
|
200
|
+
- .terraform:setup
|
201
|
+
- .terraform:variables:production
|
202
|
+
needs:
|
203
|
+
- terraform:plan:production
|
204
|
+
- terraform:assets:production
|
205
|
+
script:
|
206
|
+
- apk add zip
|
207
|
+
- terraform apply -var-file=production.tfvars -var rails_master_key=$PRODUCTION_RAILS_MASTER_KEY -var cf_user=$CF_USERNAME production_plan.out
|
208
|
+
rules:
|
209
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
210
|
+
when: never
|
211
|
+
- if: $CI_COMMIT_BRANCH == "production"
|
212
|
+
when: manual<% end %>
|
@@ -34,7 +34,7 @@ module RailsTemplate18f
|
|
34
34
|
def configure_asset_pipeline
|
35
35
|
copy_file "lib/tasks/i18n.rake"
|
36
36
|
copy_file "config/initializers/i18n_js.rb"
|
37
|
-
copy_file "app/javascript/i18n.js"
|
37
|
+
copy_file "app/javascript/i18n/index.js"
|
38
38
|
end
|
39
39
|
|
40
40
|
def ignore_generated_file
|
@@ -42,7 +42,7 @@ module RailsTemplate18f
|
|
42
42
|
append_to_file ".gitignore", <<~EOM
|
43
43
|
|
44
44
|
# Generated by i18n-js
|
45
|
-
/app/javascript/
|
45
|
+
/app/javascript/i18n/translations.json
|
46
46
|
EOM
|
47
47
|
end
|
48
48
|
end
|
@@ -24,7 +24,7 @@ module RailsTemplate18f
|
|
24
24
|
|
25
25
|
def install_gem
|
26
26
|
return if gem_installed?("newrelic_rpm")
|
27
|
-
gem "newrelic_rpm", "~> 9.
|
27
|
+
gem "newrelic_rpm", "~> 9.16"
|
28
28
|
bundle_install
|
29
29
|
end
|
30
30
|
|
@@ -33,7 +33,9 @@ module RailsTemplate18f
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def update_cloud_gov_manifest
|
36
|
-
insert_into_file "
|
36
|
+
insert_into_file file_path("terraform/app.tf"), <<EOT, after: "environment = {\n"
|
37
|
+
NEW_RELIC_LOG = "stdout"
|
38
|
+
EOT
|
37
39
|
end
|
38
40
|
|
39
41
|
def update_readme
|
@@ -22,44 +22,38 @@ module RailsTemplate18f
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def use_terraform_module
|
25
|
-
append_to_file file_path("terraform/
|
26
|
-
append_to_file file_path("terraform/
|
25
|
+
append_to_file file_path("terraform/main.tf"), terraform_module
|
26
|
+
append_to_file file_path("terraform/variables.tf"), <<~EOT
|
27
|
+
variable "egress_allowlist" {
|
28
|
+
type = set(string)
|
29
|
+
default = []
|
30
|
+
description = "The set of hostnames that the application is allowed to connect to"
|
31
|
+
}
|
32
|
+
EOT
|
33
|
+
insert_into_file file_path("terraform/app.tf"), <<EOT, after: "environment = {\n"
|
34
|
+
no_proxy = "apps.internal,s3-fips.us-gov-west-1.amazonaws.com"
|
35
|
+
EOT
|
36
|
+
insert_into_file file_path("terraform/app.tf"), <<EOT, after: "service_bindings = [\n"
|
37
|
+
{ service_instance = "egress-proxy-${var.env}-credentials" },
|
38
|
+
EOT
|
39
|
+
insert_into_file file_path("terraform/app.tf"), <<EOT, after: "depends_on = [\n"
|
40
|
+
cloudfoundry_service_instance.egress_proxy_credentials,
|
41
|
+
EOT
|
27
42
|
end
|
28
43
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
if file_exists?(".github/workflows/deploy-production.yml")
|
43
|
-
insert_into_file ".github/workflows/deploy-production.yml", <<EOD, before: " - name: Deploy app"
|
44
|
-
- name: Set public egress
|
45
|
-
uses: cloud-gov/cg-cli-tools@main
|
46
|
-
with:
|
47
|
-
cf_username: ${{ secrets.CF_USERNAME }}
|
48
|
-
cf_password: ${{ secrets.CF_PASSWORD }}
|
49
|
-
cf_org: #{cloud_gov_organization}
|
50
|
-
cf_space: #{cloud_gov_production_space}-egress
|
51
|
-
cf_command: bind-security-group public_networks_egress $INPUT_CF_ORG --space $INPUT_CF_SPACE
|
52
|
-
EOD
|
53
|
-
end
|
54
|
-
if file_exists?(".circleci/config.yml")
|
55
|
-
insert_into_file ".circleci/config.yml", <<EOD, before: " name: Push application with deployment vars"
|
56
|
-
name: Set public egress
|
57
|
-
command: |
|
58
|
-
cf bind-security-group public_networks_egress << parameters.cloudgov_org >> \
|
59
|
-
--space << parameters.cloudgov_space >>-egress
|
60
|
-
- run:
|
61
|
-
EOD
|
62
|
-
end
|
44
|
+
def setup_proxy_vars
|
45
|
+
create_file ".profile", <<~EOP unless file_exists?(".profile")
|
46
|
+
##
|
47
|
+
# Cloud Foundry app initialization script
|
48
|
+
# https://docs.cloudfoundry.org/devguide/deploy-apps/deploy-app.html#profile
|
49
|
+
##
|
50
|
+
|
51
|
+
EOP
|
52
|
+
insert_into_file ".profile", <<~EOP
|
53
|
+
proxy_creds=$(echo "$VCAP_SERVICES" | jq --arg service_name "egress-proxy-$RAILS_ENV-credentials" '.[][] | select(.name == $service_name) | .credentials')
|
54
|
+
export http_proxy=$(echo "$proxy_creds" | jq --raw-output ".http_uri")
|
55
|
+
export https_proxy=$(echo "$proxy_creds" | jq --raw-output ".https_uri")
|
56
|
+
EOP
|
63
57
|
end
|
64
58
|
|
65
59
|
def update_readme
|
@@ -94,9 +88,10 @@ EOB
|
|
94
88
|
### Public Egress Proxy
|
95
89
|
|
96
90
|
Traffic to be delivered to the public internet must be proxied through the [cg-egress-proxy](https://github.com/GSA-TTS/cg-egress-proxy) app. Hostnames that the app should be able to
|
97
|
-
reach should be added to the `
|
91
|
+
reach should be added to the `egress_allowlist` terraform variable in `terraform/production.tfvars` and `terraform/staging.tfvars`
|
98
92
|
|
99
93
|
See the [ruby troubleshooting doc](https://github.com/GSA-TTS/cg-egress-proxy/blob/main/docs/ruby.md) first if you have any problems making outbound connections through the proxy.
|
94
|
+
|
100
95
|
README
|
101
96
|
end
|
102
97
|
|
@@ -104,30 +99,51 @@ EOB
|
|
104
99
|
<<~EOT
|
105
100
|
|
106
101
|
module "egress_space" {
|
107
|
-
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=
|
108
|
-
|
109
|
-
cf_org_name
|
110
|
-
cf_space_name
|
111
|
-
|
112
|
-
deployers
|
113
|
-
|
114
|
-
|
102
|
+
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
|
103
|
+
|
104
|
+
cf_org_name = local.cf_org_name
|
105
|
+
cf_space_name = "${var.cf_space_name}-egress"
|
106
|
+
allow_ssh = var.allow_space_ssh
|
107
|
+
deployers = local.space_deployers
|
108
|
+
developers = var.space_developers
|
109
|
+
auditors = var.space_auditors
|
110
|
+
security_group_names = ["public_networks_egress"]
|
115
111
|
}
|
116
112
|
|
117
113
|
module "egress_proxy" {
|
118
|
-
source = "github.com/gsa-tts/terraform-cloudgov//egress_proxy?ref=
|
119
|
-
|
120
|
-
cf_org_name
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
# comment out allowlist if this module is being deployed before the app has ever been deployed
|
125
|
-
allowlist = {
|
126
|
-
"${local.app_name}-${local.env}" = []
|
127
|
-
}
|
114
|
+
source = "github.com/gsa-tts/terraform-cloudgov//egress_proxy?ref=v2.3.0"
|
115
|
+
|
116
|
+
cf_org_name = local.cf_org_name
|
117
|
+
cf_egress_space = module.egress_space.space
|
118
|
+
name = "egress-proxy-${var.env}"
|
119
|
+
allowlist = var.egress_allowlist
|
128
120
|
# depends_on line is needed only for initial creation and destruction. It should be commented out for updates to prevent unwanted cascading effects
|
129
121
|
depends_on = [module.app_space, module.egress_space]
|
130
122
|
}
|
123
|
+
|
124
|
+
resource "cloudfoundry_network_policy" "egress_routing" {
|
125
|
+
policies = [
|
126
|
+
{
|
127
|
+
source_app = cloudfoundry_app.app.id
|
128
|
+
destination_app = module.egress_proxy.app_id
|
129
|
+
port = module.egress_proxy.https_port
|
130
|
+
},
|
131
|
+
{
|
132
|
+
source_app = cloudfoundry_app.app.id
|
133
|
+
destination_app = module.egress_proxy.app_id
|
134
|
+
port = module.egress_proxy.http_port
|
135
|
+
}
|
136
|
+
]
|
137
|
+
}
|
138
|
+
|
139
|
+
resource "cloudfoundry_service_instance" "egress_proxy_credentials" {
|
140
|
+
name = "egress-proxy-${var.env}-credentials"
|
141
|
+
space = module.app_space.space_id
|
142
|
+
type = "user-provided"
|
143
|
+
credentials = module.egress_proxy.json_credentials
|
144
|
+
# depends_on line is needed only for initial creation and destruction. It should be commented out for updates to prevent unwanted cascading effects
|
145
|
+
depends_on = [module.app_space]
|
146
|
+
}
|
131
147
|
EOT
|
132
148
|
end
|
133
149
|
end
|
@@ -29,23 +29,14 @@ module RailsTemplate18f
|
|
29
29
|
|
30
30
|
def configure_server_runner
|
31
31
|
append_to_file "Procfile.dev", "worker: bundle exec sidekiq\n"
|
32
|
-
insert_into_file "
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
append_to_file "staging.yml", <<~EOYAML
|
41
|
-
worker_instances: 1
|
42
|
-
worker_memory: 256M
|
43
|
-
EOYAML
|
44
|
-
append_to_file "production.yml", <<~EOYAML
|
45
|
-
worker_instances: 1
|
46
|
-
worker_memory: 512M
|
47
|
-
EOYAML
|
48
|
-
end
|
32
|
+
insert_into_file file_path("terraform/app.tf"), <<EOT, after: "processes = [\n"
|
33
|
+
{
|
34
|
+
type = "worker"
|
35
|
+
instances = var.worker_instances
|
36
|
+
memory = var.worker_memory
|
37
|
+
command = "bundle exec sidekiq"
|
38
|
+
},
|
39
|
+
EOT
|
49
40
|
end
|
50
41
|
|
51
42
|
def configure_active_job
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# This file takes care of importing bootstrap
|
2
|
+
# resources onto a new developer's machine if needed
|
3
|
+
# import happens automatically on a normal ./apply.sh run
|
4
|
+
|
5
|
+
%{ for resource_name, id in import_map ~}
|
6
|
+
import {
|
7
|
+
to = ${resource_name}
|
8
|
+
id = "${id}"
|
9
|
+
}
|
10
|
+
%{ endfor ~}
|
11
|
+
|
12
|
+
locals {
|
13
|
+
developer_import_map = "${replace(jsonencode(developer_map), "\"", "\\\"")}"
|
14
|
+
manager_import_map = "${replace(jsonencode(manager_map), "\"", "\\\"")}"
|
15
|
+
}
|
16
|
+
import {
|
17
|
+
for_each = jsondecode(local.developer_import_map)
|
18
|
+
to = module.mgmt_space.cloudfoundry_space_role.developers[each.key]
|
19
|
+
id = each.value
|
20
|
+
}
|
21
|
+
import {
|
22
|
+
for_each = jsondecode(local.manager_import_map)
|
23
|
+
to = module.mgmt_space.cloudfoundry_space_role.managers[each.key]
|
24
|
+
id = each.value
|
25
|
+
}
|
@@ -0,0 +1,159 @@
|
|
1
|
+
terraform {
|
2
|
+
required_version = "~> 1.10"
|
3
|
+
required_providers {
|
4
|
+
cloudfoundry = {
|
5
|
+
source = "cloudfoundry/cloudfoundry"
|
6
|
+
version = "1.2.0"
|
7
|
+
}
|
8
|
+
}
|
9
|
+
}
|
10
|
+
# empty config will let terraform borrow cf-cli's auth
|
11
|
+
provider "cloudfoundry" {}
|
12
|
+
|
13
|
+
variable "terraform_users" {
|
14
|
+
type = set(string)
|
15
|
+
description = "The list of developer emails and service account usernames who should be granted access to retrieve state bucket credentials"
|
16
|
+
|
17
|
+
validation {
|
18
|
+
condition = length(var.terraform_users) > 0
|
19
|
+
error_message = "terraform_users must include at least the current user calling apply.sh"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
variable "mgmt_space_name" {
|
23
|
+
type = string
|
24
|
+
default = "<%= cloud_gov_production_space %>-mgmt"
|
25
|
+
description = "The name of the mgmt space"
|
26
|
+
}
|
27
|
+
variable "create_bot_secrets_file" {
|
28
|
+
type = bool
|
29
|
+
default = false
|
30
|
+
description = "Flag whether to create secrets.cicd.tfvars file"
|
31
|
+
}
|
32
|
+
|
33
|
+
locals {
|
34
|
+
org_name = "<%= cloud_gov_organization %>"
|
35
|
+
# s3_plan_name should be basic when holding production data, though basic-sandbox will make early iterations easier
|
36
|
+
s3_plan_name = "basic"
|
37
|
+
}
|
38
|
+
module "mgmt_space" {
|
39
|
+
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
|
40
|
+
|
41
|
+
cf_org_name = local.org_name
|
42
|
+
cf_space_name = var.mgmt_space_name
|
43
|
+
developers = var.terraform_users
|
44
|
+
}
|
45
|
+
|
46
|
+
module "s3" {
|
47
|
+
source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.3.0"
|
48
|
+
|
49
|
+
cf_space_id = module.mgmt_space.space_id
|
50
|
+
name = "<%= app_name %>-terraform-state"
|
51
|
+
s3_plan_name = local.s3_plan_name
|
52
|
+
depends_on = [module.mgmt_space]
|
53
|
+
}
|
54
|
+
|
55
|
+
data "cloudfoundry_service_plans" "cg_service_account" {
|
56
|
+
name = "space-deployer"
|
57
|
+
service_offering_name = "cloud-gov-service-account"
|
58
|
+
}
|
59
|
+
locals {
|
60
|
+
sa_service_name = "<%= app_name %>-cicd-deployer"
|
61
|
+
sa_key_name = "cicd-deployer-access-key"
|
62
|
+
sa_bot_credentials = jsondecode(data.cloudfoundry_service_credential_binding.runner_sa_key.credential_bindings.0.credential_binding).credentials
|
63
|
+
sa_cf_username = nonsensitive(local.sa_bot_credentials.username)
|
64
|
+
sa_cf_password = local.sa_bot_credentials.password
|
65
|
+
}
|
66
|
+
resource "cloudfoundry_service_instance" "runner_service_account" {
|
67
|
+
name = local.sa_service_name
|
68
|
+
type = "managed"
|
69
|
+
space = module.mgmt_space.space_id
|
70
|
+
service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans.0.id
|
71
|
+
depends_on = [module.mgmt_space]
|
72
|
+
}
|
73
|
+
resource "cloudfoundry_service_credential_binding" "runner_sa_key" {
|
74
|
+
name = local.sa_key_name
|
75
|
+
service_instance = cloudfoundry_service_instance.runner_service_account.id
|
76
|
+
type = "key"
|
77
|
+
}
|
78
|
+
data "cloudfoundry_service_credential_binding" "runner_sa_key" {
|
79
|
+
name = local.sa_key_name
|
80
|
+
service_instance = cloudfoundry_service_instance.runner_service_account.id
|
81
|
+
depends_on = [cloudfoundry_service_credential_binding.runner_sa_key]
|
82
|
+
}
|
83
|
+
data "cloudfoundry_org" "org" {
|
84
|
+
name = local.org_name
|
85
|
+
}
|
86
|
+
data "cloudfoundry_user" "sa_user" {
|
87
|
+
name = local.sa_cf_username
|
88
|
+
}
|
89
|
+
resource "cloudfoundry_org_role" "sa_org_manager" {
|
90
|
+
user = data.cloudfoundry_user.sa_user.users.0.id
|
91
|
+
type = "organization_manager"
|
92
|
+
org = data.cloudfoundry_org.org.id
|
93
|
+
}
|
94
|
+
|
95
|
+
locals {
|
96
|
+
bucket_creds_key_name = "backend-state-bucket-creds"
|
97
|
+
}
|
98
|
+
resource "cloudfoundry_service_credential_binding" "bucket_creds" {
|
99
|
+
name = local.bucket_creds_key_name
|
100
|
+
service_instance = module.s3.bucket_id
|
101
|
+
type = "key"
|
102
|
+
}
|
103
|
+
data "cloudfoundry_service_credential_binding" "bucket_creds" {
|
104
|
+
name = local.bucket_creds_key_name
|
105
|
+
service_instance = module.s3.bucket_id
|
106
|
+
depends_on = [cloudfoundry_service_credential_binding.bucket_creds]
|
107
|
+
}
|
108
|
+
|
109
|
+
locals {
|
110
|
+
import_map = {
|
111
|
+
"module.mgmt_space.cloudfoundry_space.space" = module.mgmt_space.space_id
|
112
|
+
"module.s3.cloudfoundry_service_instance.bucket" = module.s3.bucket_id
|
113
|
+
"cloudfoundry_service_credential_binding.bucket_creds" = cloudfoundry_service_credential_binding.bucket_creds.id
|
114
|
+
"cloudfoundry_service_instance.runner_service_account" = cloudfoundry_service_instance.runner_service_account.id
|
115
|
+
"cloudfoundry_service_credential_binding.runner_sa_key" = cloudfoundry_service_credential_binding.runner_sa_key.id
|
116
|
+
"cloudfoundry_org_role.sa_org_manager" = cloudfoundry_org_role.sa_org_manager.id
|
117
|
+
}
|
118
|
+
|
119
|
+
recreate_state_template = templatefile("${path.module}/templates/imports.tf.tftpl", {
|
120
|
+
import_map = local.import_map,
|
121
|
+
developer_map = { for username, id in module.mgmt_space.developer_role_ids : username => id },
|
122
|
+
manager_map = { for username, id in module.mgmt_space.manager_role_ids : username => id }
|
123
|
+
})
|
124
|
+
}
|
125
|
+
resource "local_file" "recreate_script" {
|
126
|
+
content = local.recreate_state_template
|
127
|
+
filename = "${path.module}/imports.tf"
|
128
|
+
file_permission = "0644"
|
129
|
+
}
|
130
|
+
|
131
|
+
locals {
|
132
|
+
bucket_creds = jsondecode(data.cloudfoundry_service_credential_binding.bucket_creds.credential_bindings.0.credential_binding).credentials
|
133
|
+
backend_config = templatefile("${path.module}/templates/backend_config.tftpl", { creds = local.bucket_creds })
|
134
|
+
}
|
135
|
+
resource "local_sensitive_file" "bucket_creds" {
|
136
|
+
content = local.backend_config
|
137
|
+
filename = "${path.module}/../secrets.backend.tfvars"
|
138
|
+
file_permission = "0600"
|
139
|
+
}
|
140
|
+
|
141
|
+
resource "local_sensitive_file" "bot_secrets_file" {
|
142
|
+
count = (var.create_bot_secrets_file ? 1 : 0)
|
143
|
+
filename = "${path.module}/../secrets.cicd.tfvars"
|
144
|
+
file_permission = "0600"
|
145
|
+
|
146
|
+
content = templatefile("${path.module}/templates/bot_secrets.tftpl", {
|
147
|
+
service_name = local.sa_service_name,
|
148
|
+
key_name = local.sa_key_name,
|
149
|
+
username = local.sa_cf_username,
|
150
|
+
password = local.sa_cf_password
|
151
|
+
})
|
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
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# This file takes care of importing bootstrap
|
2
|
+
# resources onto a new developer's machine if needed
|
3
|
+
# import happens automatically on a normal ./apply.sh run
|
4
|
+
|
5
|
+
%{ for resource_name, id in import_map ~}
|
6
|
+
import {
|
7
|
+
to = ${resource_name}
|
8
|
+
id = "${id}"
|
9
|
+
}
|
10
|
+
%{ endfor ~}
|