@govuk-pay/cli 0.0.15 → 0.0.17

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 (24) hide show
  1. package/package.json +1 -1
  2. package/resources/legacy-ruby-cli/README.md +10 -3
  3. package/resources/legacy-ruby-cli/config/secrets.yml +35 -64
  4. package/resources/legacy-ruby-cli/config/service_secrets.yml +4 -7
  5. package/resources/legacy-ruby-cli/lib/pay_cli/commands/aws.rb +0 -22
  6. package/resources/legacy-ruby-cli/lib/pay_cli/commands/doctor.rb +0 -1
  7. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/config.rb +4 -0
  8. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/config.yaml +2 -0
  9. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/docker.rb +33 -3
  10. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/all.yaml +120 -54
  11. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/card.yaml +25 -42
  12. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/docker-compose.erb +110 -5
  13. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local/files/services/egress/squid.conf +47 -0
  14. package/resources/legacy-ruby-cli/lib/pay_cli/commands/local.rb +40 -9
  15. package/resources/legacy-ruby-cli/lib/pay_cli/commands/ssm.rb +7 -60
  16. package/resources/legacy-ruby-cli/lib/pay_cli/entry_point.rb +0 -11
  17. package/resources/legacy-ruby-cli/lib/pay_cli/environment.rb +1 -1
  18. package/resources/legacy-ruby-cli/lib/pay_cli/secrets.rb +1 -1
  19. package/resources/legacy-ruby-cli/lib/pay_cli/aws/document.rb +0 -23
  20. package/resources/legacy-ruby-cli/lib/pay_cli/ec2.rb +0 -38
  21. package/resources/legacy-ruby-cli/vulnerability_scan/.nvmrc +0 -1
  22. package/resources/legacy-ruby-cli/vulnerability_scan/generate_vulnerability_report.js +0 -88
  23. package/resources/legacy-ruby-cli/vulnerability_scan/package.json +0 -15
  24. package/resources/legacy-ruby-cli/vulnerability_scan/scan.sh +0 -88
@@ -1,9 +1,7 @@
1
- version: '2.1'
2
-
3
1
  services:
4
2
  <% @dbs.each do |db| %>
5
3
  <%= db[:name] %>:
6
- image: postgres:15.2
4
+ image: postgres:15.6
7
5
  environment:
8
6
  - POSTGRES_PASSWORD=mysecretpassword
9
7
  mem_limit: 250M
@@ -11,7 +9,7 @@ services:
11
9
  driver: "json-file"
12
10
  container_name: <%= db[:name] %>
13
11
  healthcheck:
14
- test: ["CMD-SHELL", "pg_isready"]
12
+ test: ["CMD-SHELL", "pg_isready -d postgres -U postgres"]
15
13
  interval: 10s
16
14
  timeout: 5s
17
15
  retries: 5
@@ -19,6 +17,8 @@ services:
19
17
  - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
20
18
  ports:
21
19
  - "<%= db[:port] %>:5432"
20
+ networks:
21
+ - pay_local_mimic_aws_vpc
22
22
  <% end %>
23
23
  <% @remote_java_apps.each do |app| %>
24
24
  <%= app[:name] %>:
@@ -48,6 +48,23 @@ services:
48
48
  - AWS_SECRET_ACCESS_KEY=mockSecretAccessKey
49
49
  <% end %>
50
50
 
51
+ <% if @egress_proxy_required && Config.can_use_egress_proxy(app[:name]) %>
52
+ - http_proxy=http://egress:8080
53
+ - HTTP_PROXY=http://egress:8080
54
+ - https_proxy=http://egress:8080
55
+ - HTTPS_PROXY=http://egress:8080
56
+ - HTTP_PROXY_HOST=egress
57
+ - HTTPS_PROXY_HOST=egress
58
+ - HTTP_PROXY_URI=http://egress:8080
59
+ - HTTPS_PROXY_URI=http://egress:8080
60
+ - HTTP_PROXY_ENABLED=true
61
+ - HTTPS_PROXY_ENABLED=true
62
+ - HTTP_PROXY_PORT=8080
63
+ - HTTPS_PROXY_PORT=8080
64
+ - HTTP_PROXY_SCHEME=http
65
+ - NO_PROXY=<%= @no_proxy_env_var %>
66
+ <% end %>
67
+
51
68
  <% if app[:queues] %>
52
69
  - AWS_SQS_REGION=eu-west-1
53
70
  - AWS_SQS_MESSAGE_MAXIMUM_WAIT_TIME_IN_SECONDS=20
@@ -83,6 +100,8 @@ services:
83
100
  - "<%= app[:port] %>:<%= app[:port] %>"
84
101
  <% if app[:admin_port] %>- "<%= app[:admin_port] %>:<%= app[:admin_port] %>"<% end %>
85
102
  container_name: <%= app[:name] %>
103
+ networks:
104
+ - pay_local_mimic_aws_vpc
86
105
  <% end %>
87
106
  <% @local_java_apps.each do |app| %>
88
107
  <%= app[:name] %>:
@@ -112,6 +131,23 @@ services:
112
131
  - AWS_SECRET_ACCESS_KEY=mockSecretAccessKey
113
132
  <% end %>
114
133
 
134
+ <% if @egress_proxy_required && Config.can_use_egress_proxy(app[:name]) %>
135
+ - http_proxy=http://egress:8080
136
+ - HTTP_PROXY=http://egress:8080
137
+ - https_proxy=http://egress:8080
138
+ - HTTPS_PROXY=http://egress:8080
139
+ - HTTP_PROXY_HOST=egress
140
+ - HTTPS_PROXY_HOST=egress
141
+ - HTTP_PROXY_URI=http://egress:8080
142
+ - HTTPS_PROXY_URI=http://egress:8080
143
+ - HTTP_PROXY_ENABLED=true
144
+ - HTTPS_PROXY_ENABLED=true
145
+ - HTTP_PROXY_PORT=8080
146
+ - HTTPS_PROXY_PORT=8080
147
+ - HTTP_PROXY_SCHEME=http
148
+ - NO_PROXY=<%= @no_proxy_env_var %>
149
+ <% end %>
150
+
115
151
  <% if app[:queues] %>
116
152
  - AWS_SQS_REGION=eu-west-1
117
153
  - AWS_SQS_MESSAGE_MAXIMUM_WAIT_TIME_IN_SECONDS=20
@@ -149,6 +185,8 @@ services:
149
185
  - "<%= app[:port] %>:<%= app[:port] %>"
150
186
  <% if app[:admin_port] %>- "<%= app[:admin_port] %>:<%= app[:admin_port] %>"<% end %>
151
187
  container_name: <%= app[:name] %>
188
+ networks:
189
+ - pay_local_mimic_aws_vpc
152
190
  <% end %>
153
191
  <% @remote_node_apps.each do |app| %>
154
192
  <%= app[:name] %>:
@@ -161,10 +199,25 @@ services:
161
199
  env_file: services/<%= app[:name] %>.env
162
200
  environment:
163
201
  - SECURE_COOKIE_OFF=true
164
- - NODE_ENV=${NODE_ENV:-production}
165
202
  - RUN_APP=true
166
203
  - DISABLE_INTERNAL_HTTPS=true
167
204
  - PORT=<%= app[:port] %>
205
+ <% if @egress_proxy_required && Config.can_use_egress_proxy(app[:name]) %>
206
+ - http_proxy=http://egress:8080
207
+ - HTTP_PROXY=http://egress:8080
208
+ - https_proxy=http://egress:8080
209
+ - HTTPS_PROXY=http://egress:8080
210
+ - HTTP_PROXY_HOST=egress
211
+ - HTTPS_PROXY_HOST=egress
212
+ - HTTP_PROXY_URI=http://egress:8080
213
+ - HTTPS_PROXY_URI=http://egress:8080
214
+ - HTTP_PROXY_ENABLED=true
215
+ - HTTPS_PROXY_ENABLED=true
216
+ - HTTP_PROXY_PORT=8080
217
+ - HTTPS_PROXY_PORT=8080
218
+ - HTTP_PROXY_SCHEME=http
219
+ - NO_PROXY=<%= @no_proxy_env_var %>
220
+ <% end %>
168
221
  <%- @java_apps.each do |_app| -%>
169
222
  <%- if app[:name] == 'toolbox' && _app[:name] == 'publicauth' %>
170
223
  - PUBLIC_AUTH_URL=http://<%= _app[:name] %>:<%= _app[:port] %>
@@ -186,6 +239,8 @@ services:
186
239
  logging:
187
240
  driver: "json-file"
188
241
  container_name: <%= app[:name] %>
242
+ networks:
243
+ - pay_local_mimic_aws_vpc
189
244
  <% end %>
190
245
  <% @local_node_apps.each do |app| %>
191
246
  <%= app[:name] %>:
@@ -196,12 +251,32 @@ services:
196
251
  condition: service_healthy
197
252
  <% end %>
198
253
  env_file: services/<%= app[:name] %>.env
254
+ <% if @mount_local_node_apps %>
255
+ volumes:
256
+ - "$WORKSPACE/pay-<%= app[:name] %>:/app"
257
+ <% end %>
199
258
  environment:
200
259
  - SECURE_COOKIE_OFF=true
201
260
  - RUN_APP=true
202
261
  - DISABLE_APPMETRICS=true
203
262
  - DISABLE_INTERNAL_HTTPS=true
204
263
  - PORT=<%= app[:port] %>
264
+ <% if @egress_proxy_required && Config.can_use_egress_proxy(app[:name]) %>
265
+ - http_proxy=http://egress:8080
266
+ - HTTP_PROXY=http://egress:8080
267
+ - https_proxy=http://egress:8080
268
+ - HTTPS_PROXY=http://egress:8080
269
+ - HTTP_PROXY_HOST=egress
270
+ - HTTPS_PROXY_HOST=egress
271
+ - HTTP_PROXY_URI=http://egress:8080
272
+ - HTTPS_PROXY_URI=http://egress:8080
273
+ - HTTP_PROXY_ENABLED=true
274
+ - HTTPS_PROXY_ENABLED=true
275
+ - HTTP_PROXY_PORT=8080
276
+ - HTTPS_PROXY_PORT=8080
277
+ - HTTP_PROXY_SCHEME=http
278
+ - NO_PROXY=<%= @no_proxy_env_var %>
279
+ <% end %>
205
280
  <%- @java_apps.each do |_app| -%>
206
281
  <%- if app[:name] == 'toolbox' && _app[:name] == 'publicauth' %>
207
282
  - PUBLIC_AUTH_URL=http://<%= _app[:name] %>:<%= _app[:port] %>
@@ -224,6 +299,8 @@ services:
224
299
  logging:
225
300
  driver: "json-file"
226
301
  container_name: <%= app[:name] %>
302
+ networks:
303
+ - pay_local_mimic_aws_vpc
227
304
  <% end %>
228
305
  <% @proxies.each do |app| %>
229
306
  <%= app[:name] %>:
@@ -248,6 +325,8 @@ services:
248
325
  logging:
249
326
  driver: "json-file"
250
327
  container_name: <%= app[:name] %>
328
+ networks:
329
+ - pay_local_mimic_aws_vpc
251
330
  <% end %>
252
331
  <% if @queue_apps.any? %>
253
332
  localstack:
@@ -260,6 +339,8 @@ services:
260
339
  - "4566:4566" # All AWS services exposed on this port
261
340
  volumes:
262
341
  - <%= @localstack_init_file %>:/etc/localstack/init/ready.d/init-aws.sh
342
+ networks:
343
+ - pay_local_mimic_aws_vpc
263
344
  <% end %>
264
345
  <% if @java_apps.any? {|app| Config.uses_redis(app[:name])} %>
265
346
  redis:
@@ -267,4 +348,28 @@ services:
267
348
  container_name: localRedis
268
349
  ports:
269
350
  - "6379:6379"
351
+ networks:
352
+ - pay_local_mimic_aws_vpc
270
353
  <% end %>
354
+ <% if @egress_proxy_required %>
355
+ egress:
356
+ image: governmentdigitalservice/pay-egress:latest-master
357
+ container_name: egress
358
+ volumes:
359
+ - "./services/egress/squid.conf:/etc/squid/squid.conf"
360
+ networks:
361
+ pay_local_mimic_aws_vpc:
362
+ ipv4_address: 172.18.0.253
363
+ expose:
364
+ - 8080
365
+ <% end %>
366
+
367
+ networks:
368
+ pay_local_mimic_aws_vpc:
369
+ name: pay_local_mimic_aws_vpc
370
+ driver_opts:
371
+ com.docker.network.bridge.host_binding_ipv4: "127.0.0.1"
372
+ ipam:
373
+ driver: default
374
+ config:
375
+ - subnet: 172.18.0.0/24
@@ -0,0 +1,47 @@
1
+ logformat govuk_datetime %tg %6tr %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt
2
+
3
+ acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
4
+ acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
5
+ acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
6
+ acl localnet src fc00::/7 # RFC4193 local private network range
7
+ acl localnet src fe80::/10 # RFC4291 link-local (directly-plugged) machine
8
+
9
+ acl SSL_ports port 443
10
+ acl Safe_ports port 80
11
+ acl purge method PURGE
12
+ acl CONNECT method CONNECT
13
+
14
+ acl all_sites ssl::server_name_regex .*
15
+
16
+ acl vpc src 172.18.0.0/16
17
+
18
+ http_access allow all_sites vpc SSL_ports
19
+
20
+ http_access allow manager localhost
21
+ http_access deny manager
22
+ http_access allow purge localhost
23
+ http_access deny purge
24
+ http_access deny !Safe_ports
25
+ http_access deny CONNECT !SSL_ports
26
+ http_access allow localhost
27
+
28
+ http_access deny all
29
+ icp_access deny all
30
+
31
+ http_port 0.0.0.0:8080
32
+
33
+ access_log stdio:/dev/stdout govuk_datetime
34
+ cache_log stdio:/dev/stdout govuk_datetime
35
+
36
+ refresh_pattern ^ftp: 1440 20% 10080
37
+ refresh_pattern ^gopher: 1440 0% 1440
38
+ refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
39
+ refresh_pattern (Release|Package(.gz)*)$ 0 20% 2880
40
+
41
+ pid_filename /squid/pid
42
+ visible_hostname squid
43
+ hosts_file /etc/hosts
44
+ maximum_object_size 512 MB
45
+ coredump_dir /squid
46
+ cache_mem 1024 MB
47
+ cache deny all
@@ -14,17 +14,21 @@ require 'pathname'
14
14
  REQUIRES_COMPILATION = %w[frontend products-ui selfservice toolbox].freeze
15
15
 
16
16
  class PayCLI::Commands::Local < Thor
17
+ CLUSTERS=['admin', 'card', 'paymentlinks', 'webhooks', 'endtoend', 'java', 'toolbox']
18
+
17
19
  warn "🏠 Local Pay for local people\n\n"
18
20
  map "up" => :launch
19
- desc 'launch | up [--cluster <cluster>] [--local <app>] [--proxy] [--apps] [--rebuild]',
21
+ desc 'launch | up [--cluster <cluster>] [--local <app>] [--proxy] [--apps] [--rebuild] [--with-egress-proxy]',
20
22
  'Launch a predefined cluster, or a user specified list of apps.' \
21
23
  ' Specify a list of apps that should use your locally checked out code using --local'
22
24
  option :local, :type => :array, :default => []
23
25
  option :proxy, :type => :boolean, :default => false
24
- option :cluster, :enum => ['admin', 'card', 'paymentlinks', 'webhooks', 'endtoend', 'java', 'toolbox']
26
+ option :cluster, :enum => CLUSTERS
25
27
  option :apps, :type => :array
26
28
  option :rebuild, :type => :boolean, :default => true
27
29
  option :experimental, :type => :boolean, :default => false
30
+ option :with_egress_proxy, :type => :boolean, :default => false
31
+ option :mount_local_node_apps, :type => :boolean, :default => false, :desc => "Mount your apps directory in your \$WORKSPACE folder into the container, this makes local changes take effect immedaitely in the container via nodemon"
28
32
  option :pull, :type => :boolean, :default => true, :desc => "Pull the latest versions of containers prior to launching, override with --no-pull"
29
33
 
30
34
  def launch()
@@ -42,6 +46,8 @@ class PayCLI::Commands::Local < Thor
42
46
  apps = all
43
47
  end
44
48
 
49
+ @egress_proxy_required = options[:with_egress_proxy]
50
+
45
51
  @node_apps = Config::node apps
46
52
  @java_apps = Config::java apps
47
53
 
@@ -51,6 +57,8 @@ class PayCLI::Commands::Local < Thor
51
57
  @remote_node_apps = Config.remote local_app_names, @node_apps
52
58
  @remote_java_apps = Config.remote local_app_names, @java_apps
53
59
 
60
+ @mount_local_node_apps = options[:mount_local_node_apps]
61
+
54
62
  @dbs = Config.db_configs Config.has_db apps
55
63
  @queue_apps = Config.has_queue apps
56
64
  @sns_topic_apps = Config.has_sns_topics apps
@@ -60,6 +68,17 @@ class PayCLI::Commands::Local < Thor
60
68
 
61
69
  @proxies = if options[:proxy] then Config::proxy_configs Config::has_proxy apps else [] end
62
70
 
71
+ @no_proxy_env_var = [
72
+ "localhost",
73
+ "127.0.0.1",
74
+ "172.18.0.253",
75
+ "localstack",
76
+ "redis",
77
+ Config.all.map { |app| app[:name] },
78
+ @dbs.map { |app| app[:name] },
79
+ @proxies.map { |app| app[:name] },
80
+ ].flatten!.join(",")
81
+
63
82
  @localstack_init_file = File.realpath(
64
83
  File.join(__dir__, 'local', 'files', 'localstack', 'init-aws.sh')
65
84
  )
@@ -106,13 +125,19 @@ class PayCLI::Commands::Local < Thor
106
125
  AppClient::report_state apps
107
126
  end
108
127
 
109
- desc 'down --cluster <cluster>',
128
+ desc 'down [--cluster <cluster>]',
110
129
  'Bring down a cluster'
111
- option :cluster, :enum => ['admin', 'card', 'paymentlinks', 'webhooks', 'endtoend']
130
+ option :cluster, :enum => CLUSTERS
112
131
  def down()
113
- cluster = options[:cluster]
132
+ cluster = options.fetch(:cluster, 'all')
133
+ unless Docker::compose_file_exists_for_cluster?(cluster)
134
+ $stderr.puts "Error: cluster #{cluster} has not been launched, its docker-compose file was not found"
135
+ return
136
+ end
137
+
114
138
  warn "🛬 bringing down #{cluster} cluster"
115
139
  puts Docker::down cluster
140
+ puts Docker::cleanup_old_network
116
141
  end
117
142
 
118
143
  desc 'healthcheck <cluster>',
@@ -136,15 +161,21 @@ class PayCLI::Commands::Local < Thor
136
161
  end
137
162
  Docker::remove('localstack')
138
163
  Docker::remove('localRedis')
164
+ Docker::remove('egress')
165
+ Docker::remove_network
139
166
  end
140
167
 
141
- desc 'restart',
168
+ desc 'restart [--cluster <cluster>] <app>',
142
169
  'Restart a container and waits for it to be healthy.'
143
-
170
+ option :cluster, :enum => CLUSTERS
144
171
  def restart(app_name)
145
- warn "😅 restarting #{app_name}"
172
+ cluster = options.fetch(:cluster, 'all')
173
+ unless Docker::compose_file_exists_for_cluster?(cluster)
174
+ $stderr.puts "error: cluster #{cluster} has not been launched, its docker-compose file was not found"
175
+ return
176
+ end
146
177
 
147
- puts `docker restart #{app_name}`
178
+ Docker::restart(cluster, app_name)
148
179
  app = Config::app_by_name(app_name)
149
180
  AppClient::wait_for_apps(app)
150
181
  AppClient::report_state(app)
@@ -6,11 +6,10 @@ module PayCLI::Commands::Ssm
6
6
 
7
7
  def self.usage!
8
8
  STDERR.puts <<~USAGE
9
- pay ssm ...
9
+ pay ssm <environment> <instance_id>
10
10
 
11
- - `pay ssm ci-5 build` - connect to build (jenkins) in ci-5
12
- - `pay ssm test-12 i-123456` - connect to instance i-123456 in test-12
13
- - `pay ssm staging-2 asg toolbox` - connect to a box in the toolbox asg
11
+ example:
12
+ pay ssm test-12 i-1c472d8c2ffd826d7
14
13
 
15
14
  USAGE
16
15
  exit
@@ -18,36 +17,15 @@ module PayCLI::Commands::Ssm
18
17
 
19
18
  def self.start!
20
19
  args = ARGV[1..-1] || []
21
- usage! if args.empty?
20
+ usage! if args.length != 2
22
21
 
23
22
  PayCLI::StopYubicoAuthenticator.stop_yubico_authenticator!
24
23
 
25
- env, *args = args
26
- usage! if args.length < 1
27
- PayCLI::Environment.setup! env
28
-
29
- resource, resource_name, *args = args
30
- server_roles = ['build', 'deploy', 'admin', 'bastion']
31
-
32
- instance_id = case
33
- when resource.match(/^i-/)
34
- resource
35
- when server_roles.include?(resource)
36
- get_instance_id env, resource
37
- when resource == 'asg'
38
- get_asg_instance_id env, resource_name
39
- when resource == 'app'
40
- warn <<~WARN
41
-
42
- `pay ssm app ...` no longer works since the move to fargate.
24
+ env, instance_id = args
43
25
 
44
- Please see usage below for other examples
26
+ usage! unless instance_id.match(/^i-/)
45
27
 
46
- WARN
47
- usage!
48
- else
49
- abort "Unknown resource type #{resource}"
50
- end
28
+ PayCLI::Environment.setup! env
51
29
 
52
30
  warn <<~WARN
53
31
  \e[33m
@@ -67,37 +45,6 @@ module PayCLI::Commands::Ssm
67
45
  start_ssm_session(instance_id, env)
68
46
  end
69
47
 
70
- def self.get_instance_id(env, resource)
71
- ec2_client = Aws::EC2::Client.new
72
- instances = ec2_client.describe_instances({
73
- filters: [
74
- {name: 'tag:Environment', values: [env]},
75
- {name: 'tag:Role', values: [resource == 'admin' ? 'bastion' : resource]}
76
- ]
77
- }).reservations.first.instances
78
-
79
- abort "No healthy admin instances found" if instances.empty?
80
-
81
- instances.first.instance_id
82
- end
83
-
84
- def self.get_asg_instance_id(env, service)
85
- STDERR.puts "Getting instance_id from asg #{service} in #{env}"
86
-
87
- asg_name = PayCLI::Naming.asg_name(env, service)
88
- asg_client = Aws::AutoScaling::Client.new
89
-
90
- asgs = asg_client.describe_auto_scaling_groups({
91
- auto_scaling_group_names: [asg_name],
92
- }).auto_scaling_groups
93
- abort "No ASGs found for #{service} -> #{asg_name}" if asgs.empty?
94
-
95
- instances = asgs.first.instances
96
- abort "No instances found for #{service} -> #{asg_name}" if instances.empty?
97
-
98
- instances.first.instance_id
99
- end
100
-
101
48
  def self.start_ssm_session(instance_id, env)
102
49
  STDERR.puts "SSM to instance #{instance_id} in #{env}"
103
50
 
@@ -15,18 +15,9 @@ class PayCLI::EntryPoint < Thor
15
15
  PayCLI::Commands::Doctor.new.start!
16
16
  end
17
17
 
18
- desc 'deployment_status <env>', 'Describe whats deployed'
19
- def deployment_status(env, regex = '')
20
- PayCLI::Commands::Healthcheck.deployment_status!(env)
21
- end
22
-
23
- desc 'scale', 'Quick way to scale microservices (dangerous)'
24
-
25
18
  desc 'secrets', 'Manage secrets in and between environments'
26
19
  subcommand 'secrets', PayCLI::Commands::Secrets
27
20
 
28
- desc 'ssh', 'DEPRECATED: SSH to boxes in environments'
29
-
30
21
  desc 'ssm', 'Start an SSM session to boxes in environments'
31
22
 
32
23
  def ssm(*_args)
@@ -39,8 +30,6 @@ class PayCLI::EntryPoint < Thor
39
30
  PayCLI::Commands::Tf.start!
40
31
  end
41
32
 
42
- desc 'tunnel', 'DEPRECATED: Opens tunnels to microservice(s).'
43
-
44
33
  desc 'local', 'Sets up local Pay development environment'
45
34
  subcommand 'local', PayCLI::Commands::Local
46
35
 
@@ -10,7 +10,7 @@ module PayCLI::Environment
10
10
  end
11
11
 
12
12
  def self.setup_each!(env_filter, &block)
13
- all_envs = %w{dev ci deploy test staging production}
13
+ all_envs = %w{dev deploy test staging production}
14
14
  if env_filter.any?
15
15
  envs = env_filter & all_envs
16
16
  else
@@ -118,7 +118,7 @@ module PayCLI::Secrets
118
118
  env['PASSWORD_STORE_DIR'] = path if path
119
119
 
120
120
  stdin, stdout, wait_thr = Open3.popen2(env, "pass #{pass_path}")
121
- password = stdout.readline.chomp
121
+ password = stdout.readlines.map(&:chomp).join("\n")
122
122
  stdin.close
123
123
  stdout.close
124
124
  pass_status = wait_thr.value
@@ -1,23 +0,0 @@
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
@@ -1,38 +0,0 @@
1
- require 'aws-sdk-ec2'
2
-
3
- class PayCLI::Ec2
4
-
5
- attr_reader :ec2, :logger
6
-
7
- def initialize(region: default_region, logger: Logger.new(STDERR))
8
- @ec2 = ::Aws::EC2::Client.new(region: region)
9
- @logger = logger
10
- end
11
-
12
- def all_instances
13
- @instances ||= fetch_all_instances
14
- end
15
-
16
- private
17
- def default_region
18
- ENV['AWS_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'eu-west-1'
19
- end
20
-
21
- def fetch_all_instances
22
- next_token = nil
23
- instances = []
24
-
25
- begin
26
- response = ec2.describe_instances(next_token: next_token)
27
-
28
- if response
29
- instances += response.reservations.flat_map { |r| r.instances }
30
- next_token = response.next_token
31
- else
32
- break
33
- end
34
- end while next_token
35
-
36
- return instances
37
- end
38
- end
@@ -1,88 +0,0 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
- const stringify = require('csv-stringify/sync').stringify
4
-
5
- const INPUT_PATH = `${path.resolve(path.dirname(__filename))}/reports`
6
- const OUTPUT_PATH = `${path.resolve(path.dirname(__filename))}/reports`
7
-
8
- const HEADERS = ["App name", "Release", "Vulnerability", "Severity", "Status", "Package", "Fixed version"]
9
- const NODE_MAJOR_VERSION = process.versions.node.split('.')[0];
10
-
11
- if (NODE_MAJOR_VERSION < 16) {
12
- console.warn('⛔️ requires >= Node 16')
13
- process.exit(1)
14
- } else {
15
- generate()
16
- }
17
-
18
- function generate() {
19
- const date = new Date().toJSON().slice(0, 10);
20
- const jsonFiles = fs.readdirSync(INPUT_PATH).filter(file => path.extname(file) === '.json')
21
- const reportFilePath = `${OUTPUT_PATH}/vulnerability_scan_report-${date}.csv`
22
- const violatedRules = new Map()
23
- let parseCount = 0
24
- let rowCount = 0
25
- try {
26
- jsonFiles.forEach(file => {
27
- const appInfo = extractAppAndReleaseFromFilename(file)
28
- const filePath = path.join(INPUT_PATH, file)
29
- const data = fs.readFileSync(filePath, 'utf8')
30
- const parsedData = JSON.parse(data)
31
-
32
- const appViolations = [];
33
- violatedRules.set(`${appInfo.name}:${appInfo.release}`, appViolations)
34
-
35
- parsedData["runs"][0]["tool"]["driver"]["rules"].forEach(
36
- (violatedRule) => appViolations.push({
37
- "App name": appInfo.name,
38
- "Release": appInfo.release,
39
- "Vulnerability": violatedRule.id,
40
- "Severity": violatedRule.properties.cvssV3_severity,
41
- "Status": "",
42
- "Package": violatedRule.properties.purls.join("\n"),
43
- "Fixed version": violatedRule.properties.fixed_version,
44
- })
45
- )
46
-
47
- parseCount++
48
- })
49
- } catch (err) {
50
- console.error(`Error: Failed parsing source json after successfully parsing ${parseCount} of ${jsonFiles.length} source files: `, err)
51
- process.exit(1)
52
- }
53
-
54
- const csv_rows = [HEADERS];
55
- try {
56
- violatedRules.forEach((violations) => {
57
- violations.forEach((violation) => {
58
- const row = HEADERS.map(key => violation[key])
59
- csv_rows.push(row)
60
- rowCount++
61
- })
62
- })
63
- } catch (err) {
64
- console.error("Error collating results for writing to CSV: ", err)
65
- process.exit(1)
66
- }
67
-
68
- try {
69
- fs.writeFileSync(reportFilePath, stringify(csv_rows))
70
- } catch (err) {
71
- console.error("Error writing CSV file: ", err.message)
72
- process.exit(1)
73
- }
74
-
75
- console.log(`Parsed ${parseCount} of ${jsonFiles.length} JSON files, wrote ${rowCount} row(s) to ${reportFilePath}`)
76
- }
77
-
78
- function extractAppAndReleaseFromFilename(fileName) {
79
- const regex = /^.*?(?=-\d+)/ // matches any characters at the beginning of the string that are followed by a dash and one or more digits
80
- const match = fileName.match(regex)
81
- if (match && match[0]) {
82
- const release = fileName.replace(`${match[0]}-`, "").replace(".json", "")
83
- return { name: match[0], release }
84
- } else {
85
- const fallback = fileName.replace(".json", "")
86
- return { name: fallback, release: fallback}
87
- }
88
- }
@@ -1,15 +0,0 @@
1
- {
2
- "name": "vulnerability_scan",
3
- "version": "1.0.0",
4
- "description": "",
5
- "main": "generate_vulnerability_report.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
- },
9
- "keywords": [],
10
- "author": "",
11
- "license": "MIT",
12
- "dependencies": {
13
- "csv-stringify": "^6"
14
- }
15
- }