awshark 1.3.0 → 1.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f014eaddd54562cad6064bc0b28a9fde800b7144f3be26e4af11f02a99d1f13
4
- data.tar.gz: 258b5c71b20180623ca66646d4081c38d8c14e590a1b2a2773193523423dc614
3
+ metadata.gz: 1f20abce36658043c8b046859575b969365fd56528b3a786ca71e3009b078909
4
+ data.tar.gz: 75631cf5ad34c594571a1f46297d3fa23c8da384c4789c43ea857a4ab09b972c
5
5
  SHA512:
6
- metadata.gz: 42970eec188f9fe6a4f561a2d42b01387b08c98f26ee93e0352d83f1fda165f119ae09909fbbb62c80e5380ca259a8d667bb46cf416e742db333051da4891204
7
- data.tar.gz: ecf2602e7bb5cf37ebd508d3bb95d44eff004214f38bb6fa19475ee38d6b094093c6572c17acb3d48ca59d6b018a39129019d450e80aa7a6db4d84d0cc4b7c17
6
+ metadata.gz: e75070ff5ad3295b994b9408edc5e448a205a413278b9dc6d2cae3b891840a976f6f5b0ccd9d8d4b9f6ba85fdf081ad1b3c83727712bea4228cb5248e659019b
7
+ data.tar.gz: aa0feb28170116e34cab5a60ca8e60cfd6a6b76c9def7aaf78709aaa28a3475d2067bc39e76c9303481304ef11a757f69a54ebd4fdb9a0e1ce9cedf84c98d778
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@
4
4
  # See https://docs.rubocop.org/rubocop/configuration
5
5
 
6
6
  AllCops:
7
- TargetRubyVersion: 2.6
7
+ TargetRubyVersion: 2.7
8
8
  Exclude:
9
9
  - 'bin/*'
10
10
  - 'tmp/*'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## Changelog
2
2
 
3
+ #### 1.5.0
4
+ - [new] add `awshark ssm list` to list AWS Parameter Store secrets
5
+ - [new] add `awshark ssm deploy` to update AWS Parameter Store secrets
6
+
7
+ #### 1.4.0
8
+ - [new] add `awshark cf save` to save AWS Cloud Formation templates as file
9
+
3
10
  #### 1.3.0
4
11
  - [new] add `awshark ec2 authorize` and `unauthorize`
5
12
 
data/README.md CHANGED
@@ -18,37 +18,46 @@ Use `AWS_PROFILE=PROFILE` and/or `AWS_REGION=REGION` to configure the internal A
18
18
 
19
19
  #### S3 commands
20
20
 
21
- List all S3 buckets
21
+ List all S3 buckets with number of objects and total size.
22
+ (Data depends on AWS Cloudwatch Metrics so there is a time difference to the actual data.)
22
23
  ```
23
24
  awshark s3 list
24
25
  ```
25
26
 
26
- List all objects in a specific S3 bucket
27
+ List all objects in a specific S3 bucket.
27
28
  ```
28
29
  awshark s3 objects BUCKET_NAME fonts/
29
30
  ```
30
31
 
31
32
  #### EC2 commands
32
33
 
33
- List all EC2 instances in a region
34
+ List all EC2 instances in a region.
34
35
  ```
35
36
  awshark ec2 list
36
37
  ```
37
38
 
38
39
  #### ECS commands
39
40
 
40
- List all EC2 instances in a region
41
+ List all ECS services in a region.
41
42
  ```
42
43
  awshark ecs list
43
44
  ```
44
45
 
45
46
  #### Cloud Formation commands
46
47
 
47
- Update (diff) Cloud Formation stack
48
+ Display changes to AWS Cloud Formation stack.
49
+ ```
50
+ awshark cf diff TEMPLATE_PATH --stage=STAGE --bucket=S3_BUCKET.bundesimmo.de
51
+ ```
52
+
53
+ Update or create AWS Cloud Formation stack.
48
54
  ```
49
55
  awshark cf deploy TEMPLATE_PATH --stage=STAGE --bucket=S3_BUCKET.bundesimmo.de
56
+ ```
50
57
 
51
- awshark cf diff TEMPLATE_PATH --stage=STAGE --bucket=S3_BUCKET.bundesimmo.de
58
+ Save AWS Cloud Formation stack as file `STACK_NAME-STAGE.json`.
59
+ ```
60
+ awshark cf save TEMPLATE_PATH --stage=STAGE
52
61
  ```
53
62
 
54
63
  For a further information visit the [Wiki](https://github.com/jdahlke/awshark/wiki).
data/awshark.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.bindir = 'exe'
28
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
- spec.required_ruby_version = '>= 2.6'
30
+ spec.required_ruby_version = '>= 2.7'
31
31
 
32
32
  spec.add_dependency 'activesupport'
33
33
  spec.add_dependency 'aws-sdk-cloudformation'
@@ -11,7 +11,7 @@ module Awshark
11
11
  exit(0)
12
12
  end
13
13
 
14
- setup_aws_credentials(options)
14
+ setup_aws_credentials(cli_options)
15
15
  end
16
16
 
17
17
  private
data/lib/awshark/cli.rb CHANGED
@@ -7,6 +7,7 @@ require 'awshark/ec2/subcommand'
7
7
  require 'awshark/ecs/subcommand'
8
8
  require 'awshark/rds/subcommand'
9
9
  require 'awshark/s3/subcommand'
10
+ require 'awshark/ssm/subcommand'
10
11
 
11
12
  module Awshark
12
13
  class Cli < Thor
@@ -15,6 +16,7 @@ module Awshark
15
16
  map '-v' => :version
16
17
 
17
18
  class_option :help, type: :boolean, desc: 'Prints this help'
19
+ class_option :region, type: :string, desc: 'AWS region'
18
20
 
19
21
  desc 'cf COMMAND', 'Run CloudFormation command'
20
22
  subcommand 'cf', Awshark::CloudFormation::Subcommand
@@ -31,6 +33,9 @@ module Awshark
31
33
  desc 's3 COMMAND', 'Run CloudFormation command'
32
34
  subcommand 's3', Awshark::S3::Subcommand
33
35
 
36
+ desc 'ssm COMMAND', 'Run SSM command'
37
+ subcommand 'ssm', Awshark::Ssm::Subcommand
38
+
34
39
  desc 'version', 'Displays current version of AwsShark'
35
40
  long_desc <<-LONGDESC
36
41
  Displays current version of AwsShark.
@@ -46,6 +46,12 @@ module Awshark
46
46
  raise e
47
47
  end
48
48
 
49
+ def save_stack_template
50
+ filename = "#{stack.name}.json"
51
+ File.open(filename, 'w') { |f| f.write(template.body) }
52
+ filename
53
+ end
54
+
49
55
  def tail_stack_events
50
56
  stack.reload
51
57
  stack_events = StackEvents.new(stack)
@@ -63,6 +63,22 @@ module Awshark
63
63
  puts diff
64
64
  end
65
65
 
66
+ desc 'save', 'Save AWS CloudFormation JSON template as file'
67
+ long_desc <<-LONGDESC
68
+ Save AWS CloudFormation JSON template as file TEMPLATE_PATH/cloudformation-stage.json
69
+
70
+ Example: `awshark cf save TEMPLATE_PATH`
71
+ LONGDESC
72
+ def save(template_path)
73
+ process_class_options
74
+
75
+ manager = create_manager(template_path)
76
+ print_stack_information(manager.stack)
77
+
78
+ filename = manager.save_stack_template
79
+ printf "Written CloudFormation JSON template to: %<name>s\n\n", name: filename
80
+ end
81
+
66
82
  private
67
83
 
68
84
  def create_manager(template_path)
@@ -50,7 +50,7 @@ module Awshark
50
50
  desc: 'Security group to allow access to.'
51
51
  option :username,
52
52
  type: :string,
53
- desc: 'Ports to register. Only uses ports from 1 to 65535.'
53
+ desc: 'Optional user name (defaults to whoami).'
54
54
  def authorize
55
55
  process_class_options
56
56
 
@@ -72,7 +72,7 @@ module Awshark
72
72
  desc: 'Security group to remove access from.'
73
73
  option :username,
74
74
  type: :string,
75
- desc: 'Ports to register. Only uses ports from 1 to 65535.'
75
+ desc: 'Optional user name (defaults to whoami).'
76
76
  def unauthorize
77
77
  process_class_options
78
78
 
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Awshark
4
+ module Ssm
5
+ class Client
6
+ def list_secrets(application:)
7
+ response = client.get_parameters_by_path({
8
+ path: application,
9
+ recursive: true,
10
+ with_decryption: true
11
+ })
12
+ response.parameters
13
+ end
14
+
15
+ def update_secrets(application:, secrets:)
16
+ flat_secrets = flatten_hash(secrets)
17
+
18
+ flat_secrets.each_pair do |key, value|
19
+ params = {
20
+ name: "/#{application}/#{key.downcase}",
21
+ value: value,
22
+ type: 'SecureString', # accepts String, StringList, SecureString
23
+ tier: 'Standard' # accepts Standard, Advanced, Intelligent-Tiering
24
+ }
25
+
26
+ loop do
27
+ client.put_parameter(params.merge(overwrite: true))
28
+ puts "Updated secrets for: #{params[:name]}"
29
+
30
+ break
31
+ rescue Aws::SSM::Errors::ThrottlingException
32
+ puts 'Aws::SSM::Errors::ThrottlingException... retrying'
33
+ sleep 1
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def client
41
+ @client ||= Aws::SSM::Client.new
42
+ end
43
+
44
+ # helper function
45
+ def flatten_hash(hash, prefix = nil)
46
+ hash.each_with_object({}) do |(key, value), rslt|
47
+ if value.is_a?(Hash)
48
+ rslt.merge!(flatten_hash(value, "#{prefix}#{key}_"))
49
+ else
50
+ rslt["#{prefix}#{key}"] = value
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-ssm'
4
+
5
+ require 'awshark/ssm/client'
6
+
7
+ module Awshark
8
+ module Ssm
9
+ class Subcommand < Thor
10
+ include Awshark::ClassOptions
11
+
12
+ class_option :stage, type: :string, desc: 'Stage of the configuration'
13
+
14
+ desc 'list', 'Lists Parameter Store secrets'
15
+ long_desc <<-LONGDESC
16
+ List AWS Parameter Store secrets of specific path.
17
+
18
+ awshark ssm list PARAMETER_PATH
19
+
20
+ Examples:
21
+
22
+ awshark ssm list /ticketing-api
23
+ LONGDESC
24
+ def list(parameter_path)
25
+ process_class_options
26
+
27
+ raise GracefulFail, 'PARAMETER_PATH must begin with a "/"' if parameter_path[0] != '/'
28
+
29
+ puts "Parameter Store #{parameter_path.inspect} in #{::Aws.config[:region]}:"
30
+
31
+ parameters = ssm_client.list_secrets(application: parameter_path)
32
+
33
+ parameters.each do |param|
34
+ printf " %-60<name>s %<value>s\n", { name: param.name, value: param.value }
35
+ end
36
+ rescue GracefulFail => e
37
+ puts e.message
38
+ end
39
+
40
+ desc 'deploy', 'Updates Parameter Store secrets'
41
+ long_desc <<-LONGDESC
42
+ Updates AWS Parameter Store secrets from a file "secrets.yml".
43
+ It assumes the directory is the name of the application.
44
+
45
+ awshark ssm deploy DIRECTORY --stage=STAGE
46
+
47
+ Examples:
48
+
49
+ awshark ssm deploy aws/ticketing-api --stage=staging
50
+ LONGDESC
51
+ def deploy(directory)
52
+ process_class_options
53
+
54
+ secrets_path = File.join(directory, 'secrets.yml')
55
+ raise GracefulFail, "File #{secrets_path} does not exist." unless File.exist?(secrets_path)
56
+
57
+ app_name = directory.split('/').last
58
+ stage = options['stage']
59
+
60
+ secrets = YAML.load_file(secrets_path)[stage]
61
+ raise GracefulFail, "No secrets found for stage '#{stage}' in #{secrets_path}." if secrets.nil?
62
+
63
+ ssm_client.update_secrets(application: "#{app_name}-#{stage}", secrets: secrets)
64
+ rescue GracefulFail => e
65
+ puts e.message
66
+ end
67
+
68
+ private
69
+
70
+ def ssm_client
71
+ @ssm_client ||= Awshark::Ssm::Client.new
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Awshark
4
- VERSION = '1.3.0'
4
+ VERSION = '1.5.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awshark
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joergen Dahlke
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-10 00:00:00.000000000 Z
11
+ date: 2023-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -283,6 +283,8 @@ files:
283
283
  - lib/awshark/s3/configuration.rb
284
284
  - lib/awshark/s3/manager.rb
285
285
  - lib/awshark/s3/subcommand.rb
286
+ - lib/awshark/ssm/client.rb
287
+ - lib/awshark/ssm/subcommand.rb
286
288
  - lib/awshark/sts/configuration.rb
287
289
  - lib/awshark/version.rb
288
290
  homepage: https://github.com/jdahlke/awshark
@@ -300,14 +302,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
300
302
  requirements:
301
303
  - - ">="
302
304
  - !ruby/object:Gem::Version
303
- version: '2.6'
305
+ version: '2.7'
304
306
  required_rubygems_version: !ruby/object:Gem::Requirement
305
307
  requirements:
306
308
  - - ">="
307
309
  - !ruby/object:Gem::Version
308
310
  version: '0'
309
311
  requirements: []
310
- rubygems_version: 3.0.3.1
312
+ rubygems_version: 3.3.26
311
313
  signing_key:
312
314
  specification_version: 4
313
315
  summary: Custom CLI for for AWS related tasks