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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +9 -7
- data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +4 -3
- data/lib/generators/rails_template18f/auditree/auditree_generator.rb +36 -6
- data/lib/generators/rails_template18f/auditree/templates/gitlab/auditree.yml.tt +48 -0
- data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +12 -2
- data/lib/generators/rails_template18f/cloud_gov_config/cloud_gov_config_generator.rb +0 -8
- data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +6 -7
- data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +13 -19
- data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +0 -4
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +3 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +3 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +3 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +3 -1
- data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +138 -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 +33 -0
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +213 -0
- data/lib/generators/rails_template18f/oscal/oscal_generator.rb +15 -1
- data/lib/generators/rails_template18f/oscal/templates/bin/trestle.tt +10 -1
- data/lib/generators/rails_template18f/oscal/templates/gitlab/trestle.yml.tt +29 -0
- data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +16 -32
- data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +1 -1
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/apply.sh +25 -0
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/main.tf.tt +98 -0
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +59 -0
- data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/backend_config.tftpl +6 -0
- data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/bot_secrets.tftpl +5 -0
- data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/users.auto.tfvars +5 -0
- data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +4 -11
- data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +3 -3
- data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +38 -36
- data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +1 -6
- data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +30 -19
- data/lib/generators/rails_template18f/terraform/templates/terraform/production.tfvars.tt +3 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +4 -24
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +5 -5
- data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +40 -55
- data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +11 -12
- data/lib/generators/rails_template18f/terraform/terraform_generator.rb +78 -6
- data/lib/rails_template18f/version.rb +1 -1
- data/template.rb +50 -25
- data/templates/{pa11yci.js → pa11yci.js.tt} +5 -0
- metadata +28 -20
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
- data/lib/generators/rails_template18f/terraform/templates/terraform/sandbox_bot/main.tf +0 -74
- data/lib/generators/rails_template18f/terraform/templates/terraform/sandbox_bot/run.sh +0 -17
- /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/assemble-ssp.yml.tt +0 -0
- /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/validate-ssp.yml +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap/templates → gitlab_bootstrap}/bot_secrets.tftpl +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → gitlab_bootstrap}/users.auto.tfvars +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/apply.sh +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/imports.tf.tftpl +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/imports.tf.tftpl +0 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# Shared setup helpers for terraform jobs
|
2
|
+
.terraform:setup:
|
3
|
+
stage: deploy
|
4
|
+
inherit:
|
5
|
+
default: false
|
6
|
+
image:
|
7
|
+
name: "hashicorp/terraform"
|
8
|
+
entrypoint: ["sh"]
|
9
|
+
variables:
|
10
|
+
CF_API_URL: https://api.fr.cloud.gov
|
11
|
+
TF_STATE_NAME: staging
|
12
|
+
TF_HTTP_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}
|
13
|
+
TF_HTTP_LOCK_ADDRESS: ${TF_HTTP_ADDRESS}/lock
|
14
|
+
TF_HTTP_UNLOCK_ADDRESS: ${TF_HTTP_ADDRESS}/lock
|
15
|
+
TF_HTTP_USERNAME: gitlab-ci-token
|
16
|
+
TF_HTTP_PASSWORD: ${CI_JOB_TOKEN}
|
17
|
+
dependencies: []
|
18
|
+
before_script:
|
19
|
+
- cd terraform
|
20
|
+
- terraform init
|
21
|
+
rules:
|
22
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
23
|
+
|
24
|
+
.terraform:variables:staging:
|
25
|
+
dependencies: null
|
26
|
+
variables:
|
27
|
+
CF_USER: $CF_USERNAME
|
28
|
+
|
29
|
+
.terraform:variables:production:
|
30
|
+
dependencies: null
|
31
|
+
variables:
|
32
|
+
CF_USER: $CF_USERNAME
|
33
|
+
TF_STATE_NAME: "production"
|
@@ -0,0 +1,213 @@
|
|
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
|
+
- scan
|
14
|
+
- deploy
|
15
|
+
|
16
|
+
variables:
|
17
|
+
POSTGRES_DB: <%= app_name %>_test
|
18
|
+
POSTGRES_PASSWORD: not-actually-secret
|
19
|
+
POSTGRES_VERSION: <%= postgres_version %>
|
20
|
+
RUBY_VERSION: <%= RUBY_VERSION %>
|
21
|
+
|
22
|
+
include:
|
23
|
+
- local: ".gitlab/ruby.yml"
|
24
|
+
- local: ".gitlab/node.yml"
|
25
|
+
- local: ".gitlab/rails.yml"
|
26
|
+
- local: ".gitlab/terraform.yml"
|
27
|
+
|
28
|
+
default:
|
29
|
+
image: "ruby:${RUBY_VERSION}"
|
30
|
+
before_script:
|
31
|
+
- !reference [.setup-ruby]
|
32
|
+
cache:
|
33
|
+
- !reference [.cache-dependencies, cache]
|
34
|
+
|
35
|
+
build-project:
|
36
|
+
stage: build
|
37
|
+
extends: [.cache-dependencies, .setup-languages]
|
38
|
+
cache:
|
39
|
+
policy: pull-push
|
40
|
+
script:
|
41
|
+
- !reference [.bundle-install]
|
42
|
+
- !reference [.yarn-install]
|
43
|
+
- bin/rake assets:precompile
|
44
|
+
artifacts:
|
45
|
+
expire_in: 1 hour
|
46
|
+
paths:
|
47
|
+
- app/assets/builds
|
48
|
+
- public/assets
|
49
|
+
rules:
|
50
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
51
|
+
|
52
|
+
brakeman-scan:
|
53
|
+
stage: test
|
54
|
+
script:
|
55
|
+
- bin/brakeman --no-pager --ensure-ignore-notes -f sarif -o output.sarif.json
|
56
|
+
artifacts:
|
57
|
+
when: always
|
58
|
+
expose_as: "Brakeman results"
|
59
|
+
paths:
|
60
|
+
- output.sarif.json
|
61
|
+
|
62
|
+
dependency_scanning:
|
63
|
+
stage: test
|
64
|
+
extends: .setup-languages
|
65
|
+
script:
|
66
|
+
- bin/rake bundler:audit
|
67
|
+
- bin/rake yarn:audit
|
68
|
+
- gem install cyclonedx-ruby
|
69
|
+
- cyclonedx-ruby -p . -o ruby_bom.xml
|
70
|
+
artifacts:
|
71
|
+
expose_as: "Ruby SBOM"
|
72
|
+
paths:
|
73
|
+
- ruby_bom.xml
|
74
|
+
|
75
|
+
rspec:
|
76
|
+
stage: test
|
77
|
+
extends: .setup-project
|
78
|
+
script:
|
79
|
+
- bundle exec rspec
|
80
|
+
rules:
|
81
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
82
|
+
|
83
|
+
pa11y_scan:
|
84
|
+
stage: scan
|
85
|
+
extends: .run-server
|
86
|
+
script:
|
87
|
+
- !reference [.install-puppet-deps]
|
88
|
+
- yarn run pa11y-ci -c pa11yci.js
|
89
|
+
rules:
|
90
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
91
|
+
|
92
|
+
owasp_scan:
|
93
|
+
extends: .owasp:setup
|
94
|
+
script:
|
95
|
+
- /zap/zap-baseline.py -t http://localhost:3000 -c zap.conf -I -r zap_report.html
|
96
|
+
rules:
|
97
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
98
|
+
|
99
|
+
owasp_daily_scan:
|
100
|
+
extends: .owasp:setup
|
101
|
+
script:
|
102
|
+
- /zap/zap-full-scan.py -t http://localhost:3000 -c zap.conf -I -r zap_report.html
|
103
|
+
rules:
|
104
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
105
|
+
|
106
|
+
terraform:fmt:
|
107
|
+
stage: test
|
108
|
+
extends: .terraform:setup
|
109
|
+
script:
|
110
|
+
- terraform fmt -check -recursive .
|
111
|
+
|
112
|
+
terraform:validate:
|
113
|
+
stage: test
|
114
|
+
extends: .terraform:setup
|
115
|
+
script:
|
116
|
+
- terraform validate
|
117
|
+
|
118
|
+
terraform:assets:staging:
|
119
|
+
extends: .assets:builder
|
120
|
+
cache:
|
121
|
+
- !reference [.cache-dependencies, cache]
|
122
|
+
- key: staging-assets
|
123
|
+
unprotect: true
|
124
|
+
paths:
|
125
|
+
- public/assets
|
126
|
+
- app/assets/builds
|
127
|
+
policy: $CACHE_POLICY
|
128
|
+
variables:
|
129
|
+
RAILS_ENV: staging
|
130
|
+
rules:
|
131
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
132
|
+
when: never
|
133
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
134
|
+
variables:
|
135
|
+
CACHE_POLICY: pull-push
|
136
|
+
- variables:
|
137
|
+
CACHE_POLICY: pull
|
138
|
+
<% if terraform_manage_spaces? %>
|
139
|
+
terraform:assets:production:
|
140
|
+
extends: .assets:builder
|
141
|
+
cache:
|
142
|
+
- !reference [.cache-dependencies, cache]
|
143
|
+
- key: production-assets
|
144
|
+
paths:
|
145
|
+
- public/assets
|
146
|
+
- app/assets/builds
|
147
|
+
policy: $CACHE_POLICY
|
148
|
+
variables:
|
149
|
+
RAILS_ENV: production
|
150
|
+
rules:
|
151
|
+
- if: $CI_COMMIT_BRANCH == "production"
|
152
|
+
variables:
|
153
|
+
CACHE_POLICY: pull-push
|
154
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
155
|
+
variables:
|
156
|
+
CACHE_POLICY: pull
|
157
|
+
<% end %>
|
158
|
+
terraform:plan:staging:
|
159
|
+
extends:
|
160
|
+
- .terraform:setup
|
161
|
+
- .terraform:variables:staging
|
162
|
+
needs: ["terraform:assets:staging"]
|
163
|
+
script:
|
164
|
+
- apk add zip
|
165
|
+
- terraform plan -out=staging_plan.out -var-file=staging.tfvars -var rails_master_key=$RAILS_MASTER_KEY -var cf_user=$CF_USERNAME
|
166
|
+
artifacts:
|
167
|
+
paths:
|
168
|
+
- terraform/staging_plan.out
|
169
|
+
- terraform/dist
|
170
|
+
|
171
|
+
terraform:apply:staging:
|
172
|
+
extends:
|
173
|
+
- .terraform:setup
|
174
|
+
- .terraform:variables:staging
|
175
|
+
needs:
|
176
|
+
- terraform:plan:staging
|
177
|
+
- terraform:assets:staging
|
178
|
+
script:
|
179
|
+
- apk add zip
|
180
|
+
- terraform apply -var-file=staging.tfvars -var rails_master_key=$RAILS_MASTER_KEY -var cf_user=$CF_USERNAME staging_plan.out
|
181
|
+
rules:
|
182
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
183
|
+
when: never
|
184
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
185
|
+
<% if terraform_manage_spaces? %>
|
186
|
+
terraform:plan:production:
|
187
|
+
extends:
|
188
|
+
- .terraform:setup
|
189
|
+
- .terraform:variables:production
|
190
|
+
needs: ["terraform:assets:production"]
|
191
|
+
script:
|
192
|
+
- apk add zip
|
193
|
+
- terraform plan -out=production_plan.out -var-file=production.tfvars -var rails_master_key=$PRODUCTION_RAILS_MASTER_KEY -var cf_user=$CF_USERNAME
|
194
|
+
artifacts:
|
195
|
+
paths:
|
196
|
+
- terraform/production_plan.out
|
197
|
+
- terraform/dist
|
198
|
+
|
199
|
+
terraform:apply:production:
|
200
|
+
extends:
|
201
|
+
- .terraform:setup
|
202
|
+
- .terraform:variables:production
|
203
|
+
needs:
|
204
|
+
- terraform:plan:production
|
205
|
+
- terraform:assets:production
|
206
|
+
script:
|
207
|
+
- apk add zip
|
208
|
+
- terraform apply -var-file=production.tfvars -var rails_master_key=$PRODUCTION_RAILS_MASTER_KEY -var cf_user=$CF_USERNAME production_plan.out
|
209
|
+
rules:
|
210
|
+
- if: $CI_PIPELINE_SOURCE == "schedule"
|
211
|
+
when: never
|
212
|
+
- if: $CI_COMMIT_BRANCH == "production"
|
213
|
+
when: manual<% end %>
|
@@ -49,6 +49,16 @@ module RailsTemplate18f
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
def copy_gitlab_ci
|
53
|
+
if use_gitlab_ci?
|
54
|
+
directory "gitlab", ".gitlab"
|
55
|
+
if file_exists? ".gitlab-ci.yml"
|
56
|
+
insert_into_file ".gitlab-ci.yml", " - local: \".gitlab/trestle.yml\"\n", after: /^include:\n/
|
57
|
+
insert_into_file ".gitlab-ci.yml", " TRESTLE_VERSION: #{docker_trestle_tag}\n", after: /^variables:\n/
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
52
62
|
def update_readme
|
53
63
|
if file_content("README.md").match?("## Documentation")
|
54
64
|
insert_into_file "README.md", readme_contents, after: "## Documentation\n"
|
@@ -85,13 +95,17 @@ module RailsTemplate18f
|
|
85
95
|
end
|
86
96
|
|
87
97
|
def docker_trestle_tag
|
88
|
-
options[:tag].present? ? options[:tag] : "
|
98
|
+
options[:tag].present? ? options[:tag] : "20250603"
|
89
99
|
end
|
90
100
|
|
91
101
|
def use_github_actions?
|
92
102
|
options[:ci] == "github" || file_exists?(".github/workflows")
|
93
103
|
end
|
94
104
|
|
105
|
+
def use_gitlab_ci?
|
106
|
+
options[:ci] == "gitlab" || file_exists?(".gitlab-ci.yml")
|
107
|
+
end
|
108
|
+
|
95
109
|
def readme_contents
|
96
110
|
content = <<~README
|
97
111
|
|
@@ -2,8 +2,17 @@
|
|
2
2
|
|
3
3
|
trestle_tag="<%= docker_trestle_tag %>"
|
4
4
|
|
5
|
+
if [ "$1" = "-h" ]; then
|
6
|
+
echo """
|
7
|
+
Usage: $0 [-h] [CMD [CMD ARGS]]
|
8
|
+
|
9
|
+
CMD defaults to 'bash'
|
10
|
+
"""
|
11
|
+
exit 0
|
12
|
+
fi
|
13
|
+
|
5
14
|
command="bash"
|
6
|
-
if [ "$1"
|
15
|
+
if [ -n "$1" ]; then
|
7
16
|
command=$1
|
8
17
|
shift 1
|
9
18
|
fi
|
@@ -0,0 +1,29 @@
|
|
1
|
+
.trestle:setup:
|
2
|
+
inherit:
|
3
|
+
default: false
|
4
|
+
image: "ghcr.io/gsa-tts/trestle:${TRESTLE_VERSION}"
|
5
|
+
before_script:
|
6
|
+
- cd doc/compliance/oscal
|
7
|
+
- export PATH="/app/bin:$PATH"
|
8
|
+
|
9
|
+
validate_ssp:
|
10
|
+
extends: .trestle:setup
|
11
|
+
stage: test
|
12
|
+
script:
|
13
|
+
- validate-ssp-json
|
14
|
+
rules:
|
15
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
16
|
+
|
17
|
+
assemble_ssp:
|
18
|
+
extends: .trestle:setup
|
19
|
+
stage: deploy
|
20
|
+
script:
|
21
|
+
- trestle assemble -n <%= app_name %> system-security-plan
|
22
|
+
- render-ssp
|
23
|
+
artifacts:
|
24
|
+
expose_as: "<%= app_name %> SSPP"
|
25
|
+
paths:
|
26
|
+
- doc/compliance/oscal/dist/system-security-plans/<%= app_name %>.json
|
27
|
+
- doc/compliance/oscal/ssp-render/<%= app_name %>_ssp.md
|
28
|
+
rules:
|
29
|
+
- if: $CI_PIPELINE_SOURCE != "schedule"
|
@@ -41,24 +41,6 @@ EOT
|
|
41
41
|
EOT
|
42
42
|
end
|
43
43
|
|
44
|
-
def setup_terraform_provider
|
45
|
-
insert_into_file file_path("terraform/providers.tf"), after: "required_providers {\n" do
|
46
|
-
<<-EOT
|
47
|
-
cloudfoundry-community = {
|
48
|
-
source = "cloudfoundry-community/cloudfoundry"
|
49
|
-
version = "0.53.1"
|
50
|
-
}
|
51
|
-
EOT
|
52
|
-
end
|
53
|
-
append_to_file file_path("terraform/providers.tf"), <<~EOT
|
54
|
-
provider "cloudfoundry-community" {
|
55
|
-
api_url = "https://api.fr.cloud.gov"
|
56
|
-
user = var.cf_user
|
57
|
-
password = var.cf_password
|
58
|
-
}
|
59
|
-
EOT
|
60
|
-
end
|
61
|
-
|
62
44
|
def setup_proxy_vars
|
63
45
|
create_file ".profile", <<~EOP unless file_exists?(".profile")
|
64
46
|
##
|
@@ -117,18 +99,19 @@ EOB
|
|
117
99
|
<<~EOT
|
118
100
|
|
119
101
|
module "egress_space" {
|
120
|
-
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.
|
102
|
+
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
|
121
103
|
|
122
104
|
cf_org_name = local.cf_org_name
|
123
105
|
cf_space_name = "${var.cf_space_name}-egress"
|
124
|
-
allow_ssh = var.
|
106
|
+
allow_ssh = var.allow_ssh
|
125
107
|
deployers = local.space_deployers
|
126
108
|
developers = var.space_developers
|
109
|
+
auditors = var.space_auditors
|
127
110
|
security_group_names = ["public_networks_egress"]
|
128
111
|
}
|
129
112
|
|
130
113
|
module "egress_proxy" {
|
131
|
-
source = "github.com/gsa-tts/terraform-cloudgov//egress_proxy?ref=v2.
|
114
|
+
source = "github.com/gsa-tts/terraform-cloudgov//egress_proxy?ref=v2.3.0"
|
132
115
|
|
133
116
|
cf_org_name = local.cf_org_name
|
134
117
|
cf_egress_space = module.egress_space.space
|
@@ -139,17 +122,18 @@ EOB
|
|
139
122
|
}
|
140
123
|
|
141
124
|
resource "cloudfoundry_network_policy" "egress_routing" {
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
+
]
|
153
137
|
}
|
154
138
|
|
155
139
|
resource "cloudfoundry_service_instance" "egress_proxy_credentials" {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Rails.application.config.to_prepare do
|
4
|
-
redis_url = CloudGovConfig.dig "aws-elasticache-redis", "credentials", "uri"
|
4
|
+
redis_url = CloudGovConfig.new.dig "aws-elasticache-redis", "credentials", "uri"
|
5
5
|
if redis_url.present?
|
6
6
|
Sidekiq.configure_server do |config|
|
7
7
|
config.redis = {url: redis_url, ssl: true}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
if ! command -v terraform &> /dev/null
|
4
|
+
then
|
5
|
+
echo "terraform must be installed before running this script"
|
6
|
+
exit 1
|
7
|
+
fi
|
8
|
+
|
9
|
+
if [ -z "$GITLAB_PROJECT_ID" ] || [ -z "$GITLAB_HOSTNAME" ]; then
|
10
|
+
echo "GITLAB_PROJECT_ID or GITLAB_HOSTNAME has not been set. Run ./setup_shadowenv.sh first"
|
11
|
+
exit 1
|
12
|
+
fi
|
13
|
+
|
14
|
+
set -e
|
15
|
+
|
16
|
+
# ensure we're logged in via cli
|
17
|
+
cf spaces &> /dev/null || cf login -a api.fr.cloud.gov --sso
|
18
|
+
|
19
|
+
tf_state_address="https://$GITLAB_HOSTNAME/api/v4/projects/$GITLAB_PROJECT_ID/terraform/state/bootstrap"
|
20
|
+
terraform init \
|
21
|
+
-backend-config="address=$tf_state_address" \
|
22
|
+
-backend-config="lock_address=$tf_state_address/lock" \
|
23
|
+
-backend-config="unlock_address=$tf_state_address/lock"
|
24
|
+
|
25
|
+
terraform apply "$@"
|
@@ -0,0 +1,98 @@
|
|
1
|
+
terraform {
|
2
|
+
required_version = "~> 1.10"
|
3
|
+
required_providers {
|
4
|
+
cloudfoundry = {
|
5
|
+
source = "cloudfoundry/cloudfoundry"
|
6
|
+
version = "~> 1.7"
|
7
|
+
}
|
8
|
+
}
|
9
|
+
backend "http" {
|
10
|
+
lock_method = "POST"
|
11
|
+
unlock_method = "DELETE"
|
12
|
+
retry_wait_min = 5
|
13
|
+
}
|
14
|
+
}
|
15
|
+
# empty config will let terraform borrow cf-cli's auth
|
16
|
+
provider "cloudfoundry" {}
|
17
|
+
|
18
|
+
locals {
|
19
|
+
org_name = "<%= cloud_gov_organization %>"
|
20
|
+
space_name = "<%= terraform_manage_spaces? ? "#{ cloud_gov_production_space }-mgmt" : cloud_gov_staging_space %>"
|
21
|
+
}
|
22
|
+
|
23
|
+
data "cloudfoundry_org" "org" {
|
24
|
+
name = local.org_name
|
25
|
+
}
|
26
|
+
<% if terraform_manage_spaces? %>
|
27
|
+
variable "terraform_users" {
|
28
|
+
type = set(string)
|
29
|
+
description = "The list of developer emails and service account usernames who should be granted access to retrieve state bucket credentials"
|
30
|
+
|
31
|
+
validation {
|
32
|
+
condition = length(var.terraform_users) > 0
|
33
|
+
error_message = "terraform_users must include at least the current user calling apply.sh"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
module "mgmt_space" {
|
38
|
+
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
|
39
|
+
|
40
|
+
cf_org_name = local.org_name
|
41
|
+
cf_space_name = local.space_name
|
42
|
+
developers = var.terraform_users
|
43
|
+
}
|
44
|
+
<% else %>
|
45
|
+
data "cloudfoundry_space" "space" {
|
46
|
+
name = local.space_name
|
47
|
+
org = data.cloudfoundry_org.org.id
|
48
|
+
}
|
49
|
+
<% end %>
|
50
|
+
data "cloudfoundry_service_plans" "cg_service_account" {
|
51
|
+
name = "<%= terraform_manage_spaces? ? "space-auditor" : "space-deployer" %>"
|
52
|
+
service_offering_name = "cloud-gov-service-account"
|
53
|
+
}
|
54
|
+
locals {
|
55
|
+
sa_service_name = "<%= app_name %>-cicd-deployer"
|
56
|
+
sa_key_name = "cicd-deployer-access-key"
|
57
|
+
sa_bot_credentials = jsondecode(data.cloudfoundry_service_credential_binding.runner_sa_key.credential_bindings.0.credential_binding).credentials
|
58
|
+
sa_cf_username = nonsensitive(local.sa_bot_credentials.username)
|
59
|
+
sa_cf_password = local.sa_bot_credentials.password
|
60
|
+
}
|
61
|
+
resource "cloudfoundry_service_instance" "runner_service_account" {
|
62
|
+
name = local.sa_service_name
|
63
|
+
type = "managed"
|
64
|
+
service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans.0.id<% if terraform_manage_spaces? %>
|
65
|
+
space = module.mgmt_space.space_id
|
66
|
+
depends_on = [module.mgmt_space]<% else %>
|
67
|
+
space = data.cloudfoundry_space.space.id<% end %>
|
68
|
+
}
|
69
|
+
resource "cloudfoundry_service_credential_binding" "runner_sa_key" {
|
70
|
+
name = local.sa_key_name
|
71
|
+
service_instance = cloudfoundry_service_instance.runner_service_account.id
|
72
|
+
type = "key"
|
73
|
+
}
|
74
|
+
data "cloudfoundry_service_credential_binding" "runner_sa_key" {
|
75
|
+
name = local.sa_key_name
|
76
|
+
service_instance = cloudfoundry_service_instance.runner_service_account.id
|
77
|
+
depends_on = [cloudfoundry_service_credential_binding.runner_sa_key]
|
78
|
+
}<% if terraform_manage_spaces? %>
|
79
|
+
data "cloudfoundry_user" "sa_user" {
|
80
|
+
name = local.sa_cf_username
|
81
|
+
}
|
82
|
+
resource "cloudfoundry_org_role" "sa_org_manager" {
|
83
|
+
user = data.cloudfoundry_user.sa_user.users.0.id
|
84
|
+
type = "organization_manager"
|
85
|
+
org = data.cloudfoundry_org.org.id
|
86
|
+
}<% end %>
|
87
|
+
|
88
|
+
resource "local_sensitive_file" "bot_secrets_file" {
|
89
|
+
filename = "${path.module}/secrets.cicd.tfvars"
|
90
|
+
file_permission = "0600"
|
91
|
+
|
92
|
+
content = templatefile("${path.module}/bot_secrets.tftpl", {
|
93
|
+
service_name = local.sa_service_name,
|
94
|
+
key_name = local.sa_key_name,
|
95
|
+
username = local.sa_cf_username,
|
96
|
+
password = local.sa_cf_password
|
97
|
+
})
|
98
|
+
}
|
@@ -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}")
|
@@ -3,7 +3,7 @@ terraform {
|
|
3
3
|
required_providers {
|
4
4
|
cloudfoundry = {
|
5
5
|
source = "cloudfoundry/cloudfoundry"
|
6
|
-
version = "1.
|
6
|
+
version = "~> 1.7"
|
7
7
|
}
|
8
8
|
}
|
9
9
|
}
|
@@ -36,7 +36,7 @@ locals {
|
|
36
36
|
s3_plan_name = "basic"
|
37
37
|
}
|
38
38
|
module "mgmt_space" {
|
39
|
-
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.
|
39
|
+
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
|
40
40
|
|
41
41
|
cf_org_name = local.org_name
|
42
42
|
cf_space_name = var.mgmt_space_name
|
@@ -44,7 +44,7 @@ module "mgmt_space" {
|
|
44
44
|
}
|
45
45
|
|
46
46
|
module "s3" {
|
47
|
-
source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.
|
47
|
+
source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.3.0"
|
48
48
|
|
49
49
|
cf_space_id = module.mgmt_space.space_id
|
50
50
|
name = "<%= app_name %>-terraform-state"
|
@@ -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}
|
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
|
-
}
|