@govuk-pay/cli 0.0.3 → 0.0.4
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.
- package/package.json +1 -1
- package/resources/legacy-ruby-cli/.rspec +1 -0
- package/resources/legacy-ruby-cli/.rubocop.yml +26 -0
- package/resources/legacy-ruby-cli/.ruby-version +1 -0
- package/resources/legacy-ruby-cli/Gemfile +24 -0
- package/resources/legacy-ruby-cli/Gemfile.lock +1431 -0
- package/resources/legacy-ruby-cli/README.md +142 -0
- package/resources/legacy-ruby-cli/bin/pay +31 -0
- package/resources/legacy-ruby-cli/config/generate-secrets.yml +9 -0
- package/resources/legacy-ruby-cli/config/secrets.yml +581 -0
- package/resources/legacy-ruby-cli/config/service_secrets.yml +174 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/aws/document.rb +23 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/aws/services.rb +47 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/aws/tokens.rb +161 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/aws.rb +51 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/browse.rb +31 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/doctor.rb +154 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/app_client.rb +216 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/config.rb +138 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/config.yaml +192 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/docker.rb +36 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/docker-compose.erb +270 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/end-to-end.erb +30 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/localstack/init-aws.sh +70 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/naxsi/readme.md +1 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/postgres/docker-entrypoint-initdb.d/make_payments_databases.sql +26 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/adminusers.env +49 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/cardid.env +2 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/connector.env +70 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/demo-service.env +10 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/frontend.env +12 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/java_app.env +1 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ledger.env +7 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/products-ui.env +14 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/products.env +25 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/publicapi.env +13 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/publicauth.env +13 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/selfservice.env +21 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/frontend-proxy.crt +18 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/products-ui-proxy.crt +20 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/selfservice-proxy.crt +20 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/stubs-proxy.crt +18 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/frontend-proxy.key +28 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/products-ui-proxy.key +28 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/selfservice-proxy.key +28 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/stubs-proxy.key +28 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/make-selfsigned.sh +2 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/stubs.env +12 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/toolbox.env +5 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/webhooks.env +9 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/image_extractor.rb +20 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/local.rb +430 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/schema.rb +36 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/secrets.rb +114 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/ssm.rb +111 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/tf.rb +90 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/commands/tunnel/services.yml +49 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/config.rb +27 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/ec2.rb +38 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/entry_point.rb +52 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/environment.rb +25 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/logger.rb +3 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/logs.rb +248 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/naming.rb +44 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/secrets.rb +276 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/stop_yubico_authenticator.rb +10 -0
- package/resources/legacy-ruby-cli/lib/pay_cli/ykman_oath_credential_config.rb +70 -0
- package/resources/legacy-ruby-cli/lib/zeitwerk_setup.rb +5 -0
- package/resources/legacy-ruby-cli/package-lock.json +6 -0
- package/resources/legacy-ruby-cli/rds_access/connect.sh +149 -0
- package/resources/legacy-ruby-cli/spec/.rubocop.yml +2 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.complex +34 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.complex_differing_froms +33 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.no_from +3 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.simple +5 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.simple_no_tag +5 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.with_sha +5 -0
- package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.with_sha_no_tag +5 -0
- package/resources/legacy-ruby-cli/spec/lib/pay_cli/commands/local/image_extractor_spec.rb +55 -0
- package/resources/legacy-ruby-cli/spec/naming_spec.rb +83 -0
- package/resources/legacy-ruby-cli/spec/spec_helper.rb +106 -0
- package/resources/legacy-ruby-cli/vulnerability_scan/.nvmrc +1 -0
- package/resources/legacy-ruby-cli/vulnerability_scan/generate_vulnerability_report.js +91 -0
- package/resources/legacy-ruby-cli/vulnerability_scan/reports/.gitkeep +0 -0
- package/resources/legacy-ruby-cli/vulnerability_scan/scan.sh +57 -0
- package/src/commands/browse.js +2 -2
- package/src/commands/legacy.js +3 -2
- package/src/core/constants.js +7 -10
- package/src/util/payCliExec.js +18 -1
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
adminusers:
|
|
3
|
+
- DB_USER
|
|
4
|
+
- DB_PASSWORD
|
|
5
|
+
- NOTIFY_API_KEY
|
|
6
|
+
- NOTIFY_SECRET
|
|
7
|
+
- SENTRY_DSN
|
|
8
|
+
alb_and_s3_logging_pipeline:
|
|
9
|
+
- firehose_hec_token
|
|
10
|
+
amazon-managed-prometheus:
|
|
11
|
+
- pager_duty_cloudwatch_integration_url_in_hours_only
|
|
12
|
+
- pager_duty_cloudwatch_integration_url_24_7_p1
|
|
13
|
+
cardid:
|
|
14
|
+
- SENTRY_DSN
|
|
15
|
+
connector:
|
|
16
|
+
- DB_USER
|
|
17
|
+
- DB_PASSWORD
|
|
18
|
+
- NOTIFY_SECRET
|
|
19
|
+
- NOTIFY_API_KEY
|
|
20
|
+
- GDS_CONNECTOR_STRIPE_AUTH_TOKEN
|
|
21
|
+
- GDS_CONNECTOR_STRIPE_AUTH_LIVE_TOKEN
|
|
22
|
+
- GDS_CONNECTOR_STRIPE_WEBHOOK_SIGN_SECRET
|
|
23
|
+
- GDS_CONNECTOR_STRIPE_WEBHOOK_LIVE_SIGN_SECRET
|
|
24
|
+
- GDS_CONNECTOR_STRIPE_CONNECT_APPLICATION_WEBHOOK_LIVE_SIGN_SECRET
|
|
25
|
+
- GDS_CONNECTOR_STRIPE_CONNECT_APPLICATION_WEBHOOK_TEST_SIGN_SECRET
|
|
26
|
+
- WORLDPAY_APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE
|
|
27
|
+
- WORLDPAY_APPLE_PAY_PAYMENT_PROCESSING_PRIVATE_KEY
|
|
28
|
+
- WORLDPAY_APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE_SECONDARY
|
|
29
|
+
- WORLDPAY_APPLE_PAY_PAYMENT_PROCESSING_PRIVATE_KEY_SECONDARY
|
|
30
|
+
- SENTRY_DSN
|
|
31
|
+
- SANDBOX_AUTH_TOKEN
|
|
32
|
+
deploy:
|
|
33
|
+
- PAGER_DUTY_CLOUDWATCH_INTEGRATION_URL
|
|
34
|
+
- PAGER_DUTY_CLOUDWATCH_INTEGRATION_URL_STAGING
|
|
35
|
+
pact-broker:
|
|
36
|
+
- master_db_user
|
|
37
|
+
- master_db_password
|
|
38
|
+
- db_user
|
|
39
|
+
- db_password
|
|
40
|
+
pact-broker-auth:
|
|
41
|
+
- pact-broker-basic-auth-password
|
|
42
|
+
- pact-broker-basic-auth-username
|
|
43
|
+
failwhale:
|
|
44
|
+
- google-analytics-id
|
|
45
|
+
frontend:
|
|
46
|
+
- GOOGLE_PAY_MERCHANT_ID
|
|
47
|
+
- GOOGLE_PAY_MERCHANT_ID_2
|
|
48
|
+
- SESSION_ENCRYPTION_KEY
|
|
49
|
+
- SESSION_ENCRYPTION_KEY_2
|
|
50
|
+
- AB_TEST_THRESHOLD
|
|
51
|
+
- WORLDPAY_APPLE_PAY_MERCHANT_ID
|
|
52
|
+
- WORLDPAY_APPLE_PAY_MERCHANT_ID_CERTIFICATE
|
|
53
|
+
- WORLDPAY_APPLE_PAY_MERCHANT_ID_CERTIFICATE_KEY
|
|
54
|
+
- STRIPE_APPLE_PAY_MERCHANT_ID
|
|
55
|
+
- STRIPE_APPLE_PAY_MERCHANT_ID_CERTIFICATE
|
|
56
|
+
- STRIPE_APPLE_PAY_MERCHANT_ID_CERTIFICATE_KEY
|
|
57
|
+
- STRIPE_TEST_PUBLISHABLE_API_KEY
|
|
58
|
+
- STRIPE_LIVE_PUBLISHABLE_API_KEY
|
|
59
|
+
- SENTRY_DSN
|
|
60
|
+
- SENTRY_CSP_REPORT_URI
|
|
61
|
+
network:
|
|
62
|
+
- PAGER_DUTY_CLOUDWATCH_ALB_INTEGRATION_URL
|
|
63
|
+
publicapi:
|
|
64
|
+
- TOKEN_API_HMAC_SECRET
|
|
65
|
+
- SENTRY_DSN
|
|
66
|
+
publicauth:
|
|
67
|
+
- DB_USER
|
|
68
|
+
- DB_PASSWORD
|
|
69
|
+
- TOKEN_DB_BCRYPT_SALT
|
|
70
|
+
- TOKEN_API_HMAC_SECRET
|
|
71
|
+
- SENTRY_DSN
|
|
72
|
+
product-page:
|
|
73
|
+
- pager_duty_cloudwatch_integration_url
|
|
74
|
+
products:
|
|
75
|
+
- DB_USER
|
|
76
|
+
- DB_PASSWORD
|
|
77
|
+
- SENTRY_DSN
|
|
78
|
+
products-ui:
|
|
79
|
+
- SESSION_ENCRYPTION_KEY
|
|
80
|
+
- SENTRY_DSN
|
|
81
|
+
- GOOGLE_RECAPTCHA_SECRET_KEY
|
|
82
|
+
- GOOGLE_RECAPTCHA_SITE_KEY
|
|
83
|
+
- GOOGLE_RECAPTCHA_ENTERPRISE_PROJECT_ID
|
|
84
|
+
selfservice:
|
|
85
|
+
- SESSION_ENCRYPTION_KEY
|
|
86
|
+
- ZENDESK_API_KEY
|
|
87
|
+
- ZENDESK_USER
|
|
88
|
+
- STRIPE_ACCOUNT_API_KEY
|
|
89
|
+
- SENTRY_DSN
|
|
90
|
+
performance-slack:
|
|
91
|
+
- SLACK_URI
|
|
92
|
+
ledger:
|
|
93
|
+
- DB_PASSWORD
|
|
94
|
+
- DB_USER
|
|
95
|
+
- SENTRY_DSN
|
|
96
|
+
webhooks:
|
|
97
|
+
- DB_PASSWORD
|
|
98
|
+
- DB_USER
|
|
99
|
+
- SENTRY_DSN
|
|
100
|
+
toolbox:
|
|
101
|
+
- AUTH_GITHUB_CLIENT_ID
|
|
102
|
+
- AUTH_GITHUB_CLIENT_SECRET
|
|
103
|
+
- AUTH_GITHUB_VIEW_ONLY_TEAM_ID
|
|
104
|
+
- AUTH_GITHUB_USER_SUPPORT_TEAM_ID
|
|
105
|
+
- AUTH_GITHUB_ADMIN_TEAM_ID
|
|
106
|
+
- STRIPE_ACCOUNT_API_KEY
|
|
107
|
+
- STRIPE_ACCOUNT_TEST_API_KEY
|
|
108
|
+
- SENTRY_DSN
|
|
109
|
+
- ZENDESK_API_KEY
|
|
110
|
+
- ZENDESK_USER
|
|
111
|
+
cd-pay-deploy:
|
|
112
|
+
- cf-password
|
|
113
|
+
- cf-username
|
|
114
|
+
- docker-password
|
|
115
|
+
- docker-username
|
|
116
|
+
- docker-email
|
|
117
|
+
- docker-access-token
|
|
118
|
+
- end-to-end/docker-password
|
|
119
|
+
- end-to-end/docker-username
|
|
120
|
+
- end-to-end/docker-email
|
|
121
|
+
- end-to-end/docker-access-token
|
|
122
|
+
- github-access-token
|
|
123
|
+
- pact-broker-username
|
|
124
|
+
- pact-broker-password
|
|
125
|
+
- pact-broker/cf-password
|
|
126
|
+
- pact-broker/cf-username
|
|
127
|
+
- pact-broker/pact-broker-password
|
|
128
|
+
- pact-broker/pact-broker-username
|
|
129
|
+
- pay_aws_deploy_account_id
|
|
130
|
+
- pay_aws_prod_account_id
|
|
131
|
+
- pay_aws_staging_account_id
|
|
132
|
+
- pay_aws_test_account_id
|
|
133
|
+
- slack-notification-secret
|
|
134
|
+
cd-pay-dev:
|
|
135
|
+
- cf-password
|
|
136
|
+
- cf-username
|
|
137
|
+
- docker-email
|
|
138
|
+
- docker-username
|
|
139
|
+
- docker-password
|
|
140
|
+
- docker-access-token
|
|
141
|
+
- github-access-token
|
|
142
|
+
- pact-broker-username
|
|
143
|
+
- pact-broker-password
|
|
144
|
+
- pay_aws_deploy_account_id
|
|
145
|
+
- pay_aws_staging_account_id
|
|
146
|
+
- pay_aws_test_account_id
|
|
147
|
+
- pay_aws_ci_account_id
|
|
148
|
+
- pay_aws_dev_account_id
|
|
149
|
+
- pay-js-commons/github-access-token
|
|
150
|
+
- pr-ci/github-access-token
|
|
151
|
+
- pr-ci/pact-broker-username
|
|
152
|
+
- pr-ci/pact-broker-password
|
|
153
|
+
- slack-notification-secret
|
|
154
|
+
- smartpay-expected-password
|
|
155
|
+
- smartpay-expected-user
|
|
156
|
+
- worldpay-expected-password
|
|
157
|
+
- worldpay-expected-user
|
|
158
|
+
cd-main:
|
|
159
|
+
- docker-email
|
|
160
|
+
- docker-username
|
|
161
|
+
- docker-password
|
|
162
|
+
- docker-access-token
|
|
163
|
+
- slack-notification-secret
|
|
164
|
+
webhooks_intrusion_monitoring:
|
|
165
|
+
- pager_duty_cloudwatch_integration_url
|
|
166
|
+
stubs:
|
|
167
|
+
- smartpay-expected-password
|
|
168
|
+
- smartpay-expected-user
|
|
169
|
+
- worldpay-expected-password
|
|
170
|
+
- worldpay-expected-user
|
|
171
|
+
codebuild:
|
|
172
|
+
- docker-username
|
|
173
|
+
- docker-access-token
|
|
174
|
+
- github-access-token
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'English'
|
|
3
|
+
require 'aws-sdk-core'
|
|
4
|
+
|
|
5
|
+
module PayCLI::Aws
|
|
6
|
+
class Document
|
|
7
|
+
def self.security_group_rules!(env)
|
|
8
|
+
PayCLI::Environment.setup! env
|
|
9
|
+
ec2 = Aws::EC2::Client.new()
|
|
10
|
+
vpc_options = {
|
|
11
|
+
:filters => [{ name: "tag:Name" , values: ["#{env}-vpc"] } ]
|
|
12
|
+
}
|
|
13
|
+
vpcs = ec2.describe_vpcs(vpc_options)
|
|
14
|
+
vpc_id = vpcs[:vpcs][0][:vpc_id]
|
|
15
|
+
STDERR.puts "Got vpc id #{vpc_id} for #{env}"
|
|
16
|
+
STDERR.puts "Querying aws for security groups and using aws_security_viz to write diagram to security-group-visualisation-latest.svg "
|
|
17
|
+
pid = system "bash", "-c" ,"aws_security_viz -o <(aws ec2 describe-security-groups --filters Name=vpc-id,Values=#{vpc_id}) -f security-group-visualisation-latest.svg --color"
|
|
18
|
+
STDERR.puts "Copy security-group-visualisation-latest.svg in the current directory to https://github.com/alphagov/pay-team-manual/blob/master/images/security-group-visualisation-latest.svg and review"
|
|
19
|
+
exit $CHILD_STATUS.exitstatus
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module PayCLI::Aws::Services
|
|
2
|
+
def self.wait_for(env, service_name, desired_count)
|
|
3
|
+
STDERR.puts "🔵 Waiting until >= #{desired_count} of #{service_name}"
|
|
4
|
+
|
|
5
|
+
service = ::Aws::ECS::Client.new
|
|
6
|
+
.describe_services(services: ["#{service_name}"], cluster: env)
|
|
7
|
+
.services.first
|
|
8
|
+
lb = service.load_balancers.first
|
|
9
|
+
tg_arn = lb.target_group_arn
|
|
10
|
+
|
|
11
|
+
lb_client = ::Aws::ElasticLoadBalancingV2::Client.new
|
|
12
|
+
|
|
13
|
+
(1..).each do |attempt|
|
|
14
|
+
STDERR.print "\r💤 Waiting (attempt #{attempt})"
|
|
15
|
+
|
|
16
|
+
healths = lb_client
|
|
17
|
+
.describe_target_health(target_group_arn: tg_arn)
|
|
18
|
+
.target_health_descriptions
|
|
19
|
+
|
|
20
|
+
healthy_services = healths.select { |h| h.target_health.state == 'healthy' }
|
|
21
|
+
|
|
22
|
+
STDERR.print " | Found #{healthy_services.count} healthy #{service_name}"
|
|
23
|
+
|
|
24
|
+
break if healthy_services.count >= desired_count
|
|
25
|
+
sleep 5
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.scale(env, service_name, desired_count, wait=false)
|
|
30
|
+
ecs_client = Aws::ECS::Client.new
|
|
31
|
+
|
|
32
|
+
STDERR.puts "Scaling desired tasks of #{service_name} in #{env} to #{desired_count}"
|
|
33
|
+
begin
|
|
34
|
+
ecs_client
|
|
35
|
+
.update_service(
|
|
36
|
+
cluster: env,
|
|
37
|
+
service: service_name,
|
|
38
|
+
desired_count: desired_count
|
|
39
|
+
)
|
|
40
|
+
STDERR.puts "✅ Scaled #{service_name} in #{env} to #{desired_count}"
|
|
41
|
+
rescue ::Aws::ECS::Errors::ClientException
|
|
42
|
+
STDERR.puts "❌ Scaled failed for #{service_name} in #{env} to #{desired_count}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
wait_for(env, service_name, desired_count) if wait
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'English'
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
class PayCLI::Aws::Tokens
|
|
6
|
+
attr_reader :account, :logger
|
|
7
|
+
|
|
8
|
+
def initialize(account, logger: PayCLI::Logger)
|
|
9
|
+
@account = account
|
|
10
|
+
@logger = logger
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.setup!(account)
|
|
14
|
+
self.new(account).ensure!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def session_exists_in_env?
|
|
18
|
+
if ENV.has_key?('AWS_VAULT') && env_has_session_expiration_token?
|
|
19
|
+
ENV['AWS_VAULT'] == account && Time.parse(get_session_expiration_timestamp) > Time.now
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def aws_vault_profiles
|
|
24
|
+
@aws_vault_profiles ||= begin
|
|
25
|
+
output, err, status = Open3.capture3("aws-vault list")
|
|
26
|
+
if status.success?
|
|
27
|
+
lines = output.lines[2..-1]
|
|
28
|
+
.map { |l| l.split(/ +/) }
|
|
29
|
+
|
|
30
|
+
lines.inject({}) do |memo, (profile,credentials,sessions)|
|
|
31
|
+
memo.merge(profile => {
|
|
32
|
+
credentials: credentials,
|
|
33
|
+
sessions: sessions
|
|
34
|
+
})
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
logger.error "Unable to invoke aws-vault list due to:\n#{err}"
|
|
38
|
+
abort
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def session_exists_in_aws_vault?
|
|
44
|
+
aws_vault_profiles.fetch(account, {}).fetch(:sessions, '-') != '-'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def ensure!
|
|
48
|
+
if !aws_vault_profiles.has_key?(account)
|
|
49
|
+
help_message_lines = %{
|
|
50
|
+
The '#{account}' profile has not been set up in aws-vault.
|
|
51
|
+
|
|
52
|
+
Ensure that the profile is listed in ~/.aws/config and then add it using `aws-vault add`.
|
|
53
|
+
|
|
54
|
+
You probably want to copy your credentials from ~/.aws/credentials.
|
|
55
|
+
|
|
56
|
+
The first time you use aws-vault you'll be prompted to create a keychain and set a password.
|
|
57
|
+
|
|
58
|
+
After adding each set of credentials to aws-vault, please delete them from the ~/.aws/credentials file
|
|
59
|
+
|
|
60
|
+
For more info on aws-vault see:
|
|
61
|
+
https://github.com/99designs/aws-vault#quick-start
|
|
62
|
+
|
|
63
|
+
Currently configured profiles are:
|
|
64
|
+
}.gsub(/^ /,'').lines[1..-1].map(&:chomp)
|
|
65
|
+
|
|
66
|
+
help_message_lines.each do |line|
|
|
67
|
+
logger.error line.chomp
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
output, err, status = Open3.capture3("aws-vault list")
|
|
71
|
+
output.lines.each do |line|
|
|
72
|
+
logger.error " " + line.chomp
|
|
73
|
+
end
|
|
74
|
+
abort
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if session_exists_in_env?
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if session_exists_in_aws_vault?
|
|
82
|
+
logger.info("Using open aws-vault session for profile '#{account}'")
|
|
83
|
+
else
|
|
84
|
+
logger.info("Opening AWS STS session for profile '#{account}' using aws-vault")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
ENV['YKMAN_OATH_CREDENTIAL_NAME'] ||= get_oath_credential_name(account)
|
|
88
|
+
output, err, status = Open3.capture3(%{aws-vault exec "#{account}" --prompt ykman -- env})
|
|
89
|
+
|
|
90
|
+
if status.success?
|
|
91
|
+
creds = output.lines.map {|l| l.chomp.split("=", 2)}.select {|k,v| k =~ /^AWS/}
|
|
92
|
+
|
|
93
|
+
creds.each do |k,v|
|
|
94
|
+
ENV[k] = v
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
minutes_remaining = ((Time.parse(get_session_expiration_timestamp) - Time.now) / 60).to_i
|
|
98
|
+
logger.info "Got credentials for #{account}, expiring in #{minutes_remaining} minutes"
|
|
99
|
+
if minutes_remaining < 15
|
|
100
|
+
logger.warn "Only #{minutes_remaining} minutes remaining on the session. Type \"yes\" to continue else exit and run \'aws-vault clear #{account}\' to clear and run again"
|
|
101
|
+
unless STDIN.gets.chomp == 'yes'
|
|
102
|
+
logger.info "Exiting"
|
|
103
|
+
exit 0
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
else
|
|
107
|
+
logger.error "Unable to get credentials for #{account} due to:\n#{err}"
|
|
108
|
+
abort
|
|
109
|
+
end
|
|
110
|
+
rescue Errno::ENOENT => e
|
|
111
|
+
if e.message =~ /aws-vault/
|
|
112
|
+
logger.error "It looks like aws-vault is not installed. Please run `pay doctor` for help"
|
|
113
|
+
abort
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def env_has_session_expiration_token?
|
|
118
|
+
ENV.include?("AWS_CREDENTIAL_EXPIRATION") || ENV.include?("AWS_SESSION_EXPIRATION")
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def get_session_expiration_timestamp
|
|
122
|
+
if ENV.include? "AWS_CREDENTIAL_EXPIRATION"
|
|
123
|
+
return ENV["AWS_CREDENTIAL_EXPIRATION"]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if ENV.include? "AWS_SESSION_EXPIRATION"
|
|
127
|
+
return ENV["AWS_SESSION_EXPIRATION"]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
logger.error "Neither an AWS_SESSION_EXPIRATION nor an AWS_CREDENTIAL_EXPIRATION env var set"
|
|
131
|
+
abort
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def get_oath_credential_name(account)
|
|
135
|
+
c = PayCLI::YkmanOathCredentialConfig.new
|
|
136
|
+
c.lookup(account)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def time_distance(from, to)
|
|
140
|
+
distance = (to - from)
|
|
141
|
+
parts = {}
|
|
142
|
+
parts[:second] = (distance % 60).floor
|
|
143
|
+
if distance > 60
|
|
144
|
+
parts[:minute] = (distance / 60).floor
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
if parts.fetch(:minute, 0) > 3
|
|
148
|
+
parts.delete(:second)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
%I{minute second}.select {|k| parts.has_key?(k)}.map {|k| pluralise(parts[k], k.to_s) }.join(" ")
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def pluralise(num, singular)
|
|
155
|
+
if num == 1
|
|
156
|
+
"#{num} #{singular}"
|
|
157
|
+
else
|
|
158
|
+
"#{num} #{singular}s"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'English'
|
|
2
|
+
require 'aws-sdk-route53'
|
|
3
|
+
|
|
4
|
+
class PayCLI::Commands::Aws < Thor
|
|
5
|
+
desc 'token <account>', 'fetches a token for <account>'
|
|
6
|
+
def token(account)
|
|
7
|
+
PayCLI::Aws::Tokens.setup!(account)
|
|
8
|
+
STDERR.puts "Found token for #{account}, printing to STDOUT"
|
|
9
|
+
STDERR.puts "If you aren't already, run this inside $() to set env vars"
|
|
10
|
+
%w{AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN}.each do |varname|
|
|
11
|
+
puts "export #{varname}=#{ENV[varname]}"
|
|
12
|
+
end
|
|
13
|
+
STDERR.puts "Outputted token for #{account} successfully"
|
|
14
|
+
exit 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc 'cli <account>', 'opens aws-shell with credentials for <account>'
|
|
18
|
+
def cli(account)
|
|
19
|
+
PayCLI::Environment.setup! account
|
|
20
|
+
|
|
21
|
+
STDERR.puts
|
|
22
|
+
|
|
23
|
+
pid = spawn(
|
|
24
|
+
'aws-shell',
|
|
25
|
+
in: STDIN, out: STDOUT, err: STDERR
|
|
26
|
+
)
|
|
27
|
+
Process.wait pid
|
|
28
|
+
exit $CHILD_STATUS.exitstatus
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
desc 'cmd <account> <*args>',
|
|
32
|
+
'runs args in aws with credentials for <account>'
|
|
33
|
+
def cmd(account, *args)
|
|
34
|
+
PayCLI::Environment.setup! account
|
|
35
|
+
|
|
36
|
+
pid = spawn(
|
|
37
|
+
"aws #{args.join(' ')}",
|
|
38
|
+
in: STDIN, out: STDOUT, err: STDERR
|
|
39
|
+
)
|
|
40
|
+
Process.wait pid
|
|
41
|
+
exit $CHILD_STATUS.exitstatus
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
desc 'document_security_groups <env>',
|
|
45
|
+
'creates the documentation for the security groups for PCI for <env>'
|
|
46
|
+
def document_security_groups(account)
|
|
47
|
+
PayCLI::Environment.setup! account
|
|
48
|
+
PayCLI::Aws::Document.security_group_rules! account
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'English'
|
|
2
|
+
|
|
3
|
+
class PayCLI::Commands::Browse < Thor
|
|
4
|
+
desc 'manual', 'browses the pay team manual'
|
|
5
|
+
def manual
|
|
6
|
+
STDERR.puts 'Opening the team manual'
|
|
7
|
+
`open https://manual.payments.service.gov.uk`
|
|
8
|
+
exit $CHILD_STATUS.exitstatus
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
desc 'repo', 'browses the pay-infra github repo'
|
|
12
|
+
def repo
|
|
13
|
+
STDERR.puts 'Opening the pay-infra github repository'
|
|
14
|
+
`open https://github.com/alphagov/pay-infra`
|
|
15
|
+
exit $CHILD_STATUS.exitstatus
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
desc 'status', 'browses the pay status page'
|
|
19
|
+
def status
|
|
20
|
+
STDERR.puts 'Opening the status page'
|
|
21
|
+
`open http://payments.statuspage.io`
|
|
22
|
+
exit $CHILD_STATUS.exitstatus
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc 'concourse', 'browses the concourse page'
|
|
26
|
+
def concourse
|
|
27
|
+
STDERR.puts 'Opening the concourse page'
|
|
28
|
+
`open https://pay-cd.deploy.payments.service.gov.uk/`
|
|
29
|
+
exit $CHILD_STATUS.exitstatus
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
class PayCLI::Commands::Doctor
|
|
5
|
+
def start!
|
|
6
|
+
check_ruby_version!
|
|
7
|
+
check_path!
|
|
8
|
+
check_old_pay_config_dir!
|
|
9
|
+
check_secrets_file!
|
|
10
|
+
check_pay_low_pass!
|
|
11
|
+
check_terraform!
|
|
12
|
+
check_aws!
|
|
13
|
+
check_aws_vault!
|
|
14
|
+
ensure_executable!("session-manager-plugin", "Needed for SSM: brew install session-manager-plugin")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def check_ruby_version!
|
|
18
|
+
repo_version = File.read(File.join(
|
|
19
|
+
PayCLI::Config::CLI_PATH, '.ruby-version'
|
|
20
|
+
)).chomp
|
|
21
|
+
|
|
22
|
+
if repo_version == RUBY_VERSION
|
|
23
|
+
STDERR.puts "✅ ruby version is correct"
|
|
24
|
+
else
|
|
25
|
+
STDERR.puts "🔥 ruby version is not correct"
|
|
26
|
+
STDERR.puts "🔥 Repo version: #{repo_version}"
|
|
27
|
+
STDERR.puts "🔥 Ruby version: #{RUBY_VERSION}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def check_secrets_file!
|
|
32
|
+
secrets_template = <<~SECRETS
|
|
33
|
+
---
|
|
34
|
+
test-12:
|
|
35
|
+
terraform: {}
|
|
36
|
+
connector: {}
|
|
37
|
+
...
|
|
38
|
+
SECRETS
|
|
39
|
+
|
|
40
|
+
secrets_explainer = <<~EXPLAIN
|
|
41
|
+
# We want to ensure that the local secrets file looks like
|
|
42
|
+
# Env (map)
|
|
43
|
+
# Service (map)
|
|
44
|
+
# SecretName => SecretValue
|
|
45
|
+
EXPLAIN
|
|
46
|
+
|
|
47
|
+
if File.exist? PayCLI::Config::LOCAL_SECRETS_PATH
|
|
48
|
+
STDERR.puts "✅ Local secrets file already exists"
|
|
49
|
+
else
|
|
50
|
+
STDERR.puts "🔧 Making local secrets file"
|
|
51
|
+
FileUtils.mkdir_p File.dirname(PayCLI::Config::LOCAL_SECRETS_PATH)
|
|
52
|
+
File.write(PayCLI::Config::LOCAL_SECRETS_PATH, secrets_template)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
secrets_content = YAML.load_file(PayCLI::Config::LOCAL_SECRETS_PATH)
|
|
56
|
+
# keys is necessary otherwise yaml gets unwound
|
|
57
|
+
secrets_are_correct = secrets_content.keys.all? do |env|
|
|
58
|
+
secrets = secrets_content[env]
|
|
59
|
+
unless secrets.class == Hash
|
|
60
|
+
false
|
|
61
|
+
else
|
|
62
|
+
if secrets.empty?
|
|
63
|
+
secrets.class == Hash
|
|
64
|
+
else
|
|
65
|
+
# necessary otherwise we get yaml mangling and get the wrong type
|
|
66
|
+
first_value = secrets[secrets.keys.first]
|
|
67
|
+
first_value.class == Hash
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if secrets_are_correct
|
|
73
|
+
STDERR.puts "✅ Local secrets looks okay"
|
|
74
|
+
else
|
|
75
|
+
STDERR.puts "🔥 Local secrets file is most likely out of date"
|
|
76
|
+
STDERR.puts "🔥 Example of a good secrets file:"
|
|
77
|
+
STDERR.puts "# #{PayCLI::Config::LOCAL_SECRETS_PATH}"
|
|
78
|
+
STDERR.puts secrets_template
|
|
79
|
+
STDERR.puts '# end of file'
|
|
80
|
+
STDERR.puts secrets_explainer
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def check_old_pay_config_dir!
|
|
85
|
+
old_secrets_dir = File.dirname(
|
|
86
|
+
PayCLI::Config::LOCAL_SECRETS_PATH.gsub('.govuk-', '.')
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if File.exist? old_secrets_dir
|
|
90
|
+
STDERR.puts "🔥 Old pay config directory still exists (#{old_secrets_dir})"
|
|
91
|
+
else
|
|
92
|
+
STDERR.puts "✅ Old pay config directory deleted"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def check_path!
|
|
97
|
+
if ENV['PATH'] =~ %r{pay-infra/cli}
|
|
98
|
+
STDERR.puts "✅ PATH looks okay"
|
|
99
|
+
else
|
|
100
|
+
STDERR.puts "🔥 PATH does not contain pay-infra/cli"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def check_pay_low_pass!
|
|
105
|
+
pay_low_pass_path = File.expand_path(File.join(
|
|
106
|
+
PayCLI::Config::PROJECT_PATH, '..', 'pay-low-pass'
|
|
107
|
+
))
|
|
108
|
+
if File.exist? pay_low_pass_path
|
|
109
|
+
STDERR.puts "✅ pay-low-pass is in the right place"
|
|
110
|
+
else
|
|
111
|
+
STDERR.puts "🔥 pay-low-pass is not present in #{pay_low_pass_path}"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def check_terraform!
|
|
116
|
+
ensure_executable!("terraform")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def check_aws!
|
|
120
|
+
ensure_executable!("aws")
|
|
121
|
+
ensure_executable!("aws-shell")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def ensure_executable!(executable, instructions_if_missing = nil)
|
|
125
|
+
`which "#{executable}"`.chomp
|
|
126
|
+
if $?.success?
|
|
127
|
+
STDERR.puts "✅ #{executable} is in your path"
|
|
128
|
+
else
|
|
129
|
+
STDERR.puts ["🔥 #{executable} is not in your path", instructions_if_missing].compact.join(". ")
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def check_aws_vault!
|
|
134
|
+
version = `aws-vault --version 2>&1`.chomp
|
|
135
|
+
if !$?.success?
|
|
136
|
+
STDERR.puts "🔥 you need to install aws-vault v6.0.0 or greater: brew install aws-vault"
|
|
137
|
+
return false
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
installed_version = Gem::Version.new(version.gsub(/^v/,""))
|
|
141
|
+
|
|
142
|
+
required_version = Gem::Version.new("6.0.0")
|
|
143
|
+
|
|
144
|
+
if installed_version < required_version
|
|
145
|
+
STDERR.puts "🔥 you need to install aws-vault v#{required_version} or greater, but you have #{installed_version}"
|
|
146
|
+
STDERR.puts "💻 run the following in your terminal:"
|
|
147
|
+
STDERR.puts " brew upgrade aws-vault"
|
|
148
|
+
return false
|
|
149
|
+
else
|
|
150
|
+
STDERR.puts "✅ aws-vault #{required_version} or greater is in your path"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|