rails_template_18f 2.1.0 → 2.3.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 +12 -0
- data/Gemfile.lock +85 -70
- 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 +6 -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 -15
- 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/dependabot.yml.tt +16 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +4 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +4 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +4 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +4 -1
- data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +9 -18
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/{node.yml.tt → node.yml} +1 -1
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +11 -18
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +80 -152
- 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 +2 -2
- 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 +114 -0
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +61 -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/users.auto.tfvars +5 -0
- data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +7 -27
- data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +6 -19
- data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +41 -29
- data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +7 -6
- data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +16 -14
- data/lib/generators/rails_template18f/terraform/templates/terraform/{production.tfvars.tt → production.env.tfvars.tt} +0 -1
- data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +6 -8
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging.env.tfvars.tt +7 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +52 -18
- data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +15 -11
- data/lib/generators/rails_template18f/terraform/terraform_generator.rb +80 -6
- data/lib/rails_template18f/generators/cloud_gov_parsing.rb +2 -2
- data/lib/rails_template18f/version.rb +1 -1
- data/template.rb +33 -16
- data/templates/README.md.tt +1 -1
- metadata +23 -17
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +0 -28
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +0 -8
- /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 → 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/{terraform/bootstrap → s3_bootstrap/common}/templates/bot_secrets.tftpl +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
|
@@ -49,7 +49,7 @@ module RailsTemplate18f
|
|
|
49
49
|
def update_boundary_diagram
|
|
50
50
|
boundary_filename = "doc/compliance/apps/application.boundary.md"
|
|
51
51
|
insert_into_file boundary_filename, <<EOB, after: "Boundary(cicd, \"CI/CD Pipeline\") {\n"
|
|
52
|
-
System_Ext(gitlabci, "
|
|
52
|
+
System_Ext(gitlabci, "Cloud.gov Workshop", "GSA-run code repository and Continuous Integration Service")
|
|
53
53
|
EOB
|
|
54
54
|
insert_into_file boundary_filename, <<~EOB, before: "@enduml"
|
|
55
55
|
Rel(developer, gitlabci, "Publish code", "git ssh (22)")
|
|
@@ -76,10 +76,9 @@ EOB
|
|
|
76
76
|
|
|
77
77
|
| Secret Name | Description |
|
|
78
78
|
| ----------- | ----------- |
|
|
79
|
-
| `
|
|
80
|
-
| `CF_PASSWORD` | cloud.gov
|
|
79
|
+
| `CF_USER` | cloud.gov OrgManager username |
|
|
80
|
+
| `CF_PASSWORD` | cloud.gov OrgManager password |
|
|
81
81
|
| `RAILS_MASTER_KEY` | `config/master.key` |
|
|
82
|
-
#{terraform_secret_values}
|
|
83
82
|
EOM
|
|
84
83
|
end
|
|
85
84
|
|
|
@@ -87,16 +86,15 @@ EOB
|
|
|
87
86
|
if terraform_manage_spaces?
|
|
88
87
|
<<~EOM
|
|
89
88
|
|
|
90
|
-
Deploys to production happen via terraform on every
|
|
89
|
+
Deploys to production happen via terraform on every tag that is added to the `main` branch.
|
|
91
90
|
|
|
92
|
-
The following secrets must be set within the masked and hidden [CI/CD variables](https://docs.gitlab.com/ci/variables/)
|
|
91
|
+
The following secrets must be set within the masked and hidden [CI/CD variables](https://docs.gitlab.com/ci/variables/) and assigned to the `production` environment.
|
|
93
92
|
|
|
94
93
|
| Secret Name | Description |
|
|
95
94
|
| ----------- | ----------- |
|
|
96
|
-
| `
|
|
97
|
-
| `CF_PASSWORD` | cloud.gov
|
|
98
|
-
| `
|
|
99
|
-
#{terraform_secret_values}
|
|
95
|
+
| `CF_USER` | cloud.gov OrgManager username |
|
|
96
|
+
| `CF_PASSWORD` | cloud.gov OrgManager password |
|
|
97
|
+
| `RAILS_MASTER_KEY` | `config/credentials/production.key`. Should be marked as `Protected`. |
|
|
100
98
|
EOM
|
|
101
99
|
else
|
|
102
100
|
"Production deploys are not supported in the sandbox organization."
|
|
@@ -107,20 +105,13 @@ EOB
|
|
|
107
105
|
<<~EOM
|
|
108
106
|
|
|
109
107
|
1. Store variables that must be secret using masked and hidden [CI/CD variables](https://docs.gitlab.com/ci/variables/) in GitLab
|
|
110
|
-
1. Add the appropriate
|
|
108
|
+
1. Add the appropriate `TF_VAR_` prefixed variables for the `terraform:plan:<env>` and `terraform:apply:<env>` jobs like the existing `TF_VAR_rails_master_key`
|
|
111
109
|
EOM
|
|
112
110
|
end
|
|
113
111
|
end
|
|
114
112
|
|
|
115
113
|
private
|
|
116
114
|
|
|
117
|
-
def terraform_secret_values
|
|
118
|
-
<<~EOM
|
|
119
|
-
| `TERRAFORM_PUBLIC_BACKEND_CONFIG` | File-type variable containing all entries from secrets.backend.tfvars _except_ `secret_key`. Marked as `Visible` |
|
|
120
|
-
| `TERRAFORM_SECRET_BACKEND_CONFIG` | File-type variable containing the `secret_key` line from secrets.backend.tfvars. Masked and hidden. |
|
|
121
|
-
EOM
|
|
122
|
-
end
|
|
123
|
-
|
|
124
115
|
def postgres_version
|
|
125
116
|
options[:postgres_version]
|
|
126
117
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
.setup-node:
|
|
2
|
-
- curl -fsSL https://deb.nodesource.com/setup_
|
|
2
|
+
- curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR_VERSION}.x" -o nodesource_setup.sh
|
|
3
3
|
- bash nodesource_setup.sh
|
|
4
4
|
- apt-get install -y nodejs
|
|
5
5
|
- npm install --global yarn
|
|
@@ -2,6 +2,13 @@ include:
|
|
|
2
2
|
- local: ".gitlab/ruby.yml"
|
|
3
3
|
- local: ".gitlab/node.yml"
|
|
4
4
|
|
|
5
|
+
.base:
|
|
6
|
+
image: "ruby:${RUBY_VERSION}"
|
|
7
|
+
before_script:
|
|
8
|
+
- !reference [.setup-ruby]
|
|
9
|
+
cache:
|
|
10
|
+
- !reference [.cache-dependencies, cache]
|
|
11
|
+
|
|
5
12
|
# Cache Helpers
|
|
6
13
|
.cache-dependencies:
|
|
7
14
|
variables:
|
|
@@ -15,27 +22,28 @@ include:
|
|
|
15
22
|
paths:
|
|
16
23
|
- vendor/ruby
|
|
17
24
|
- node_modules/
|
|
18
|
-
policy: pull
|
|
19
25
|
|
|
20
26
|
# Language Helpers
|
|
21
27
|
.setup-languages:
|
|
28
|
+
extends: .base
|
|
22
29
|
before_script:
|
|
23
30
|
- !reference [.setup-ruby]
|
|
24
31
|
- !reference [.setup-node]
|
|
25
32
|
|
|
26
33
|
# Project Helpers
|
|
27
34
|
.setup-project:
|
|
35
|
+
extends: .base
|
|
28
36
|
services:
|
|
29
37
|
- name: "postgres:${POSTGRES_VERSION}"
|
|
30
38
|
alias: pg
|
|
39
|
+
variables:
|
|
40
|
+
DATABASE_URL: "postgres://postgres:${POSTGRES_PASSWORD}@${WSR_SERVICE_HOST_pg}:5432/${POSTGRES_DB}"
|
|
31
41
|
before_script:
|
|
32
42
|
- !reference [.setup-ruby]
|
|
33
|
-
- export DATABASE_URL="postgres://postgres:${POSTGRES_PASSWORD}@${CI_SERVICE_pg}:5432/${POSTGRES_DB}"
|
|
34
43
|
- bin/rails db:prepare
|
|
35
44
|
|
|
36
45
|
.run-server:
|
|
37
46
|
extends: .setup-project
|
|
38
|
-
dependencies: []
|
|
39
47
|
variables:
|
|
40
48
|
RAILS_ENV: ci
|
|
41
49
|
SECRET_KEY_BASE_DUMMY: 1
|
|
@@ -46,21 +54,6 @@ include:
|
|
|
46
54
|
- PORT=3000 bin/rails server > /dev/null 2>&1 &
|
|
47
55
|
- sleep 5
|
|
48
56
|
|
|
49
|
-
.owasp:setup:
|
|
50
|
-
stage: test
|
|
51
|
-
extends: .run-server
|
|
52
|
-
image: "rcahearngsa/owasp-ruby:${RUBY_VERSION}"
|
|
53
|
-
variables:
|
|
54
|
-
WORKER_MEMORY: 3G
|
|
55
|
-
WORKER_DISK: 6G
|
|
56
|
-
before_script:
|
|
57
|
-
- !reference [.run-server, before_script]
|
|
58
|
-
- ln -s $PWD /zap/wrk
|
|
59
|
-
artifacts:
|
|
60
|
-
expose_as: "OWASP Report"
|
|
61
|
-
paths:
|
|
62
|
-
- zap_report.html
|
|
63
|
-
|
|
64
57
|
.assets:builder:
|
|
65
58
|
stage: deploy
|
|
66
59
|
extends: .setup-languages
|
|
@@ -1,41 +1,94 @@
|
|
|
1
1
|
# Note that environment variables can be set in several places
|
|
2
2
|
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
|
|
3
|
+
spec:
|
|
4
|
+
inputs:
|
|
5
|
+
enable-staging-deploy:
|
|
6
|
+
type: boolean
|
|
7
|
+
default: true
|
|
8
|
+
description: "Set to false for scheduled pipelines"
|
|
9
|
+
disable-tflint:
|
|
10
|
+
type: boolean
|
|
11
|
+
default: false
|
|
12
|
+
description: "Set to true for scheduled pipelines"
|
|
13
|
+
enable-tf-fmt:
|
|
14
|
+
type: boolean
|
|
15
|
+
default: true
|
|
16
|
+
description: "Set to false for scheduled pipelines"
|
|
17
|
+
---
|
|
3
18
|
|
|
4
19
|
workflow:
|
|
5
20
|
rules:
|
|
6
21
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
|
22
|
+
- if: $CI_PIPELINE_SOURCE == 'web'
|
|
7
23
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
8
|
-
- if: $
|
|
24
|
+
- if: $CI_COMMIT_TAG =~ /^v?\d+\.\d+\.\d+$/
|
|
9
25
|
|
|
10
26
|
stages:
|
|
11
27
|
- build
|
|
12
28
|
- test
|
|
13
|
-
-
|
|
29
|
+
- publish
|
|
30
|
+
- infra
|
|
31
|
+
- dast
|
|
32
|
+
- infra-prod
|
|
14
33
|
|
|
15
34
|
variables:
|
|
16
35
|
POSTGRES_DB: <%= app_name %>_test
|
|
17
36
|
POSTGRES_PASSWORD: not-actually-secret
|
|
18
37
|
POSTGRES_VERSION: <%= postgres_version %>
|
|
19
38
|
RUBY_VERSION: <%= RUBY_VERSION %>
|
|
39
|
+
NODE_MAJOR_VERSION: <%= node_major %>
|
|
40
|
+
CF_API_URL: https://api.fr.cloud.gov
|
|
41
|
+
TF_VAR_cf_user: $CF_USER
|
|
42
|
+
TF_VAR_rails_master_key: $RAILS_MASTER_KEY
|
|
20
43
|
|
|
21
44
|
include:
|
|
22
45
|
- local: ".gitlab/ruby.yml"
|
|
23
46
|
- local: ".gitlab/node.yml"
|
|
24
47
|
- local: ".gitlab/rails.yml"
|
|
25
|
-
-
|
|
48
|
+
- template: Jobs/SAST.gitlab-ci.yml
|
|
49
|
+
- template: Jobs/SAST-IaC.gitlab-ci.yml
|
|
50
|
+
- template: Security/DAST.gitlab-ci.yml
|
|
51
|
+
- template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
|
|
52
|
+
- template: Jobs/Secret-Detection.gitlab-ci.yml
|
|
53
|
+
- component: $CI_SERVER_FQDN/components/terraform/gitlab-ci-terraform@8
|
|
54
|
+
inputs:
|
|
55
|
+
project-dir: terraform
|
|
56
|
+
fmt-enabled: $[[ inputs.enable-tf-fmt ]]
|
|
57
|
+
tflint-disabled: $[[ inputs.disable-tflint ]]
|
|
58
|
+
validate-enabled: true
|
|
59
|
+
review-enabled: true
|
|
60
|
+
review-autostop-duration: "1 week"
|
|
61
|
+
staging-enabled: $[[ inputs.enable-staging-deploy ]]
|
|
62
|
+
prod-enabled: false # Switch to true when your project is ready for prod deploys
|
|
63
|
+
prod-plan-enabled: true
|
|
64
|
+
|
|
65
|
+
check-tag-on-main:
|
|
66
|
+
stage: .pre
|
|
67
|
+
variables:
|
|
68
|
+
GIT_STRATEGY: clone
|
|
69
|
+
GIT_DEPTH: 0
|
|
70
|
+
script:
|
|
71
|
+
- git branch -r --contains "$CI_COMMIT_TAG" | grep "^\s*origin/${CI_DEFAULT_BRANCH}\$"
|
|
72
|
+
rules:
|
|
73
|
+
- if: $CI_COMMIT_TAG
|
|
26
74
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
75
|
+
tf-review:
|
|
76
|
+
environment:
|
|
77
|
+
url: "https://<%= app_name.tr("_", "-") %>-${CI_ENVIRONMENT_SLUG}.app.cloud.gov"
|
|
78
|
+
on_stop: tf-destroy-review
|
|
79
|
+
|
|
80
|
+
tf-staging:
|
|
81
|
+
environment:
|
|
82
|
+
url: "https://<%= app_name.tr("_", "-") %>-${CI_ENVIRONMENT_SLUG}.app.cloud.gov"
|
|
83
|
+
on_stop: tf-destroy-staging
|
|
84
|
+
|
|
85
|
+
tf-production:
|
|
86
|
+
environment:
|
|
87
|
+
url: "https://<%= app_name.tr("_", "-") %>-${CI_ENVIRONMENT_SLUG}.app.cloud.gov"
|
|
33
88
|
|
|
34
89
|
build-project:
|
|
35
90
|
stage: build
|
|
36
91
|
extends: [.cache-dependencies, .setup-languages]
|
|
37
|
-
cache:
|
|
38
|
-
policy: pull-push
|
|
39
92
|
script:
|
|
40
93
|
- !reference [.bundle-install]
|
|
41
94
|
- !reference [.yarn-install]
|
|
@@ -48,31 +101,9 @@ build-project:
|
|
|
48
101
|
rules:
|
|
49
102
|
- if: $CI_PIPELINE_SOURCE != "schedule"
|
|
50
103
|
|
|
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
104
|
rspec:
|
|
75
105
|
stage: test
|
|
106
|
+
needs: ["build-project"]
|
|
76
107
|
extends: .setup-project
|
|
77
108
|
script:
|
|
78
109
|
- bundle exec rspec
|
|
@@ -81,6 +112,7 @@ rspec:
|
|
|
81
112
|
|
|
82
113
|
pa11y_scan:
|
|
83
114
|
stage: test
|
|
115
|
+
needs: ["build-project"]
|
|
84
116
|
extends: .run-server
|
|
85
117
|
script:
|
|
86
118
|
- !reference [.install-puppet-deps]
|
|
@@ -88,125 +120,21 @@ pa11y_scan:
|
|
|
88
120
|
rules:
|
|
89
121
|
- if: $CI_PIPELINE_SOURCE != "schedule"
|
|
90
122
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
|
123
|
+
dast:
|
|
124
|
+
environment:
|
|
125
|
+
name: $DAST_ENVIRONMENT_NAME
|
|
126
|
+
action: access
|
|
147
127
|
variables:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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"]
|
|
128
|
+
DAST_TARGET_URL: "https://<%= app_name.tr("_", "-") %>-${CI_ENVIRONMENT_SLUG}.app.cloud.gov"
|
|
129
|
+
DAST_IMAGE_SUFFIX: "-fips"
|
|
130
|
+
tags:
|
|
131
|
+
- unsafe_egress
|
|
162
132
|
script:
|
|
163
|
-
-
|
|
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
|
|
133
|
+
- /browserker/entrypoint.sh /analyze
|
|
180
134
|
rules:
|
|
181
|
-
- if: $CI_PIPELINE_SOURCE == "
|
|
182
|
-
|
|
135
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
136
|
+
variables:
|
|
137
|
+
DAST_ENVIRONMENT_NAME: "review/$CI_COMMIT_REF_NAME"
|
|
183
138
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
184
|
-
|
|
185
|
-
|
|
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 %>
|
|
139
|
+
variables:
|
|
140
|
+
DAST_ENVIRONMENT_NAME: "staging"
|
|
@@ -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"
|
|
@@ -88,7 +88,7 @@ EOB
|
|
|
88
88
|
### Public Egress Proxy
|
|
89
89
|
|
|
90
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
|
|
91
|
-
reach should be added to the `egress_allowlist` terraform variable in `terraform/production.tfvars` and `terraform/staging.tfvars`
|
|
91
|
+
reach should be added to the `egress_allowlist` terraform variable in `terraform/production.env.tfvars` and `terraform/staging.env.tfvars`
|
|
92
92
|
|
|
93
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
94
|
|
|
@@ -103,7 +103,7 @@ EOB
|
|
|
103
103
|
|
|
104
104
|
cf_org_name = local.cf_org_name
|
|
105
105
|
cf_space_name = "${var.cf_space_name}-egress"
|
|
106
|
-
allow_ssh = var.
|
|
106
|
+
allow_ssh = var.allow_ssh
|
|
107
107
|
deployers = local.space_deployers
|
|
108
108
|
developers = var.space_developers
|
|
109
109
|
auditors = var.space_auditors
|
|
@@ -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_BASE_URL" ]; then
|
|
10
|
+
echo "GITLAB_PROJECT_ID or GITLAB_BASE_URL 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="$GITLAB_BASE_URL/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 -var project_id="$GITLAB_PROJECT_ID" "$@"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_version = "~> 1.10"
|
|
3
|
+
required_providers {
|
|
4
|
+
cloudfoundry = {
|
|
5
|
+
source = "cloudfoundry/cloudfoundry"
|
|
6
|
+
version = "~> 1.10"
|
|
7
|
+
}
|
|
8
|
+
gitlab = {
|
|
9
|
+
source = "gitlabhq/gitlab"
|
|
10
|
+
version = "~> 18.5"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
backend "http" {
|
|
14
|
+
lock_method = "POST"
|
|
15
|
+
unlock_method = "DELETE"
|
|
16
|
+
retry_wait_min = 5
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
# empty config will let terraform borrow cf-cli's auth
|
|
20
|
+
provider "cloudfoundry" {}
|
|
21
|
+
provider "gitlab" {}
|
|
22
|
+
|
|
23
|
+
locals {
|
|
24
|
+
org_name = "<%= cloud_gov_organization %>"
|
|
25
|
+
space_name = "<%= terraform_manage_spaces? ? "#{ cloud_gov_production_space }-mgmt" : cloud_gov_staging_space %>"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
data "cloudfoundry_org" "org" {
|
|
29
|
+
name = local.org_name
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
variable "project_id" {
|
|
33
|
+
type = number
|
|
34
|
+
description = "The GitLab project ID for this project"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
<% if terraform_manage_spaces? %>
|
|
38
|
+
variable "terraform_users" {
|
|
39
|
+
type = set(string)
|
|
40
|
+
description = "The list of developer emails and service account usernames who should be able to update the service bot user"
|
|
41
|
+
|
|
42
|
+
validation {
|
|
43
|
+
condition = length(var.terraform_users) > 0
|
|
44
|
+
error_message = "terraform_users must include at least the current user calling apply.sh"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module "mgmt_space" {
|
|
49
|
+
source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
|
|
50
|
+
|
|
51
|
+
cf_org_name = local.org_name
|
|
52
|
+
cf_space_name = local.space_name
|
|
53
|
+
developers = var.terraform_users
|
|
54
|
+
}
|
|
55
|
+
<% else %>
|
|
56
|
+
data "cloudfoundry_space" "space" {
|
|
57
|
+
name = local.space_name
|
|
58
|
+
org = data.cloudfoundry_org.org.id
|
|
59
|
+
}
|
|
60
|
+
<% end %>
|
|
61
|
+
data "cloudfoundry_service_plans" "cg_service_account" {
|
|
62
|
+
name = "<%= terraform_manage_spaces? ? "space-auditor" : "space-deployer" %>"
|
|
63
|
+
service_offering_name = "cloud-gov-service-account"
|
|
64
|
+
}
|
|
65
|
+
resource "cloudfoundry_service_instance" "runner_service_account" {
|
|
66
|
+
name = "<%= app_name %>-cicd-deployer"
|
|
67
|
+
type = "managed"
|
|
68
|
+
service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans[0].id<% if terraform_manage_spaces? %>
|
|
69
|
+
space = module.mgmt_space.space_id
|
|
70
|
+
depends_on = [module.mgmt_space]<% else %>
|
|
71
|
+
space = data.cloudfoundry_space.space.id<% end %>
|
|
72
|
+
}
|
|
73
|
+
resource "cloudfoundry_service_credential_binding" "runner_sa_key" {
|
|
74
|
+
name = "cicd-deployer-access-key"
|
|
75
|
+
service_instance = cloudfoundry_service_instance.runner_service_account.id
|
|
76
|
+
type = "key"
|
|
77
|
+
}
|
|
78
|
+
locals {
|
|
79
|
+
sa_bot_credentials = jsondecode(cloudfoundry_service_credential_binding.runner_sa_key.credential_binding).credentials
|
|
80
|
+
sa_cf_username = nonsensitive(local.sa_bot_credentials.username)
|
|
81
|
+
sa_cf_password = local.sa_bot_credentials.password
|
|
82
|
+
}<% if terraform_manage_spaces? %>
|
|
83
|
+
data "cloudfoundry_user" "sa_user" {
|
|
84
|
+
name = local.sa_cf_username
|
|
85
|
+
}
|
|
86
|
+
resource "cloudfoundry_org_role" "sa_org_manager" {
|
|
87
|
+
user = data.cloudfoundry_user.sa_user.users[0].id
|
|
88
|
+
type = "organization_manager"
|
|
89
|
+
org = data.cloudfoundry_org.org.id
|
|
90
|
+
}<% end %>
|
|
91
|
+
|
|
92
|
+
resource "gitlab_project_variable" "cf_user" {
|
|
93
|
+
project = var.project_id
|
|
94
|
+
key = "CF_USER"
|
|
95
|
+
value = local.sa_cf_username
|
|
96
|
+
protected = false
|
|
97
|
+
masked = false
|
|
98
|
+
hidden = false
|
|
99
|
+
raw = true
|
|
100
|
+
variable_type = "env_var"
|
|
101
|
+
description = "Set by terraform bootstrap module"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
resource "gitlab_project_variable" "cf_password" {
|
|
105
|
+
project = var.project_id
|
|
106
|
+
key = "CF_PASSWORD"
|
|
107
|
+
value = local.sa_cf_password
|
|
108
|
+
protected = false
|
|
109
|
+
masked = true
|
|
110
|
+
hidden = true
|
|
111
|
+
raw = true
|
|
112
|
+
variable_type = "env_var"
|
|
113
|
+
description = "Set by terraform bootstrap module"
|
|
114
|
+
}
|