@govuk-pay/cli 0.0.2 → 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.
Files changed (89) hide show
  1. package/package.json +1 -1
  2. package/resources/legacy-ruby-cli/.rspec +1 -0
  3. package/resources/legacy-ruby-cli/.rubocop.yml +26 -0
  4. package/resources/legacy-ruby-cli/.ruby-version +1 -0
  5. package/resources/legacy-ruby-cli/Gemfile +24 -0
  6. package/resources/legacy-ruby-cli/Gemfile.lock +1431 -0
  7. package/resources/legacy-ruby-cli/README.md +142 -0
  8. package/resources/legacy-ruby-cli/bin/pay +31 -0
  9. package/resources/legacy-ruby-cli/config/generate-secrets.yml +9 -0
  10. package/resources/legacy-ruby-cli/config/secrets.yml +581 -0
  11. package/resources/legacy-ruby-cli/config/service_secrets.yml +174 -0
  12. package/resources/legacy-ruby-cli/lib/pay_cli/aws/document.rb +23 -0
  13. package/resources/legacy-ruby-cli/lib/pay_cli/aws/services.rb +47 -0
  14. package/resources/legacy-ruby-cli/lib/pay_cli/aws/tokens.rb +161 -0
  15. package/resources/legacy-ruby-cli/lib/pay_cli/commands/aws.rb +51 -0
  16. package/resources/legacy-ruby-cli/lib/pay_cli/commands/browse.rb +31 -0
  17. package/resources/legacy-ruby-cli/lib/pay_cli/commands/doctor.rb +154 -0
  18. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/app_client.rb +216 -0
  19. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/config.rb +138 -0
  20. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/config.yaml +192 -0
  21. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/docker.rb +36 -0
  22. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/docker-compose.erb +270 -0
  23. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/end-to-end.erb +30 -0
  24. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/localstack/init-aws.sh +70 -0
  25. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/naxsi/readme.md +1 -0
  26. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/postgres/docker-entrypoint-initdb.d/make_payments_databases.sql +26 -0
  27. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/adminusers.env +49 -0
  28. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/cardid.env +2 -0
  29. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/connector.env +70 -0
  30. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/demo-service.env +10 -0
  31. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/frontend.env +12 -0
  32. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/java_app.env +1 -0
  33. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ledger.env +7 -0
  34. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/products-ui.env +14 -0
  35. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/products.env +25 -0
  36. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/publicapi.env +13 -0
  37. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/publicauth.env +13 -0
  38. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/selfservice.env +21 -0
  39. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/frontend-proxy.crt +18 -0
  40. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/products-ui-proxy.crt +20 -0
  41. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/selfservice-proxy.crt +20 -0
  42. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/certs/stubs-proxy.crt +18 -0
  43. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/frontend-proxy.key +28 -0
  44. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/products-ui-proxy.key +28 -0
  45. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/selfservice-proxy.key +28 -0
  46. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/keys/stubs-proxy.key +28 -0
  47. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/ssl/make-selfsigned.sh +2 -0
  48. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/stubs.env +12 -0
  49. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/toolbox.env +5 -0
  50. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/webhooks.env +9 -0
  51. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/image_extractor.rb +20 -0
  52. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local.rb +430 -0
  53. package/resources/legacy-ruby-cli/lib/pay_cli/commands/schema.rb +36 -0
  54. package/resources/legacy-ruby-cli/lib/pay_cli/commands/secrets.rb +114 -0
  55. package/resources/legacy-ruby-cli/lib/pay_cli/commands/ssm.rb +111 -0
  56. package/resources/legacy-ruby-cli/lib/pay_cli/commands/tf.rb +90 -0
  57. package/resources/legacy-ruby-cli/lib/pay_cli/commands/tunnel/services.yml +49 -0
  58. package/resources/legacy-ruby-cli/lib/pay_cli/config.rb +27 -0
  59. package/resources/legacy-ruby-cli/lib/pay_cli/ec2.rb +38 -0
  60. package/resources/legacy-ruby-cli/lib/pay_cli/entry_point.rb +52 -0
  61. package/resources/legacy-ruby-cli/lib/pay_cli/environment.rb +25 -0
  62. package/resources/legacy-ruby-cli/lib/pay_cli/logger.rb +3 -0
  63. package/resources/legacy-ruby-cli/lib/pay_cli/logs.rb +248 -0
  64. package/resources/legacy-ruby-cli/lib/pay_cli/naming.rb +44 -0
  65. package/resources/legacy-ruby-cli/lib/pay_cli/secrets.rb +276 -0
  66. package/resources/legacy-ruby-cli/lib/pay_cli/stop_yubico_authenticator.rb +10 -0
  67. package/resources/legacy-ruby-cli/lib/pay_cli/ykman_oath_credential_config.rb +70 -0
  68. package/resources/legacy-ruby-cli/lib/zeitwerk_setup.rb +5 -0
  69. package/resources/legacy-ruby-cli/package-lock.json +6 -0
  70. package/resources/legacy-ruby-cli/rds_access/connect.sh +149 -0
  71. package/resources/legacy-ruby-cli/spec/.rubocop.yml +2 -0
  72. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.complex +34 -0
  73. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.complex_differing_froms +33 -0
  74. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.no_from +3 -0
  75. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.simple +5 -0
  76. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.simple_no_tag +5 -0
  77. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.with_sha +5 -0
  78. package/resources/legacy-ruby-cli/spec/fixtures/dockerfile_examples/Dockerfile.with_sha_no_tag +5 -0
  79. package/resources/legacy-ruby-cli/spec/lib/pay_cli/commands/local/image_extractor_spec.rb +55 -0
  80. package/resources/legacy-ruby-cli/spec/naming_spec.rb +83 -0
  81. package/resources/legacy-ruby-cli/spec/spec_helper.rb +106 -0
  82. package/resources/legacy-ruby-cli/vulnerability_scan/.nvmrc +1 -0
  83. package/resources/legacy-ruby-cli/vulnerability_scan/generate_vulnerability_report.js +91 -0
  84. package/resources/legacy-ruby-cli/vulnerability_scan/reports/.gitkeep +0 -0
  85. package/resources/legacy-ruby-cli/vulnerability_scan/scan.sh +57 -0
  86. package/src/commands/browse.js +2 -2
  87. package/src/commands/legacy.js +5 -2
  88. package/src/core/constants.js +7 -10
  89. 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