secrets_parser 0.1.0 → 0.2.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: 482b595adb191ed6b889340e239cdcc376e84a3ee3e0e0e15a4df745ee28009f
4
- data.tar.gz: 3e077fcda36d288afaebac53430bc567aae58b50e936e66cad5464e3dd4c1e9e
3
+ metadata.gz: bebee18f1aec76f28803a0e6d930d45db6100a76c67b1310681b30b93b8594cb
4
+ data.tar.gz: d6fa1b8673811b3eaf2174241774e7a9525d3f679968f5fabd6b3be3185921b3
5
5
  SHA512:
6
- metadata.gz: 48775396ba15fa9ff16ec517d13ee4e53a8349072ed9704c455c24cb42c53f5c627b1f00cbfc7e6b070ce5db96ed6044aa1822299fc46656c9b6e092bb8bb851
7
- data.tar.gz: eb1f9e854bb59043f2f9bc50f190b03e4177fbe76d7f110302bdd470cf769a9f449e25b64c5b1cae909a897f737aa89ade8e8420365f24e67bc7af0f65410949
6
+ metadata.gz: d75d57d335287068bd8f57bd15e4d1c95f60e6302062eda46e187c4cf4e70c7b05f49c9e62f1b030a3d3bc5b5320960422cb44e78c195e62f184e971feca748f
7
+ data.tar.gz: 947134c3cf57df1e0e902c87c304c902fe58d575f219d36b91699ebd1cb3bc299be75377f31cbf122da2675421867d2b19dac05d9c8c84169d922a67afc42222
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Secrets Parser
2
2
 
3
+ [![Build Status](https://travis-ci.org/peertransfer/secrets_parser.svg?branch=master)](https://travis-ci.org/peertransfer/secrets_parser)
4
+
3
5
  This gem parse the secrets reading a field in a JSON file, download the encrypted secrets file from S3 and change the values for the encrypted ones.
4
6
 
5
7
  ## Usage
@@ -1,32 +1,45 @@
1
- require 'json'
2
1
  require 'aws-sdk-s3'
2
+ require 'json'
3
+ require 'logger'
3
4
  require_relative 'helpers'
5
+ require_relative 's3'
4
6
 
5
7
  module Secrets
8
+ module Errors
9
+ class NoSuchKey < StandardError; end
10
+ end
11
+
6
12
  class Parser
7
13
  SECRETS_FILE_SUFFIX = '.json.encrypted'.freeze
8
14
 
15
+ class Configuration
16
+ SETTINGS = %i[s3_client kms_client logger s3].freeze
17
+
18
+ attr_accessor(*SETTINGS)
19
+
20
+ def []=(key, value)
21
+ public_send("#{key}=", value)
22
+ end
23
+ end
24
+
9
25
  def initialize
10
- @config = {
11
- s3_client: nil,
12
- kms_client: nil,
13
- logger: nil
14
- }
26
+ @config = Configuration.new
27
+ @secret_variables = {}
15
28
  end
16
29
 
17
30
  def set_config
18
- yield @config
31
+ yield(@config)
32
+ @config.logger ||= Logger.new(File::NULL)
33
+ self
19
34
  end
20
35
 
21
36
  def parse(file_to_parse, field_to_parse)
22
- Aws.config.update(
23
- region: ENV['AWS_DEFAULT_REGION']
24
- )
37
+ @config.s3 = S3.new(@config.s3_client, @config.kms_client, @config.logger)
25
38
 
26
39
  app_json = JSON.parse(IO.read(file_to_parse))
27
40
  app_variables = app_json[field_to_parse]
28
41
 
29
- logger.info "Parsing #{field_to_parse} section of #{file_to_parse}" if logger?
42
+ logger.info "Parsing #{field_to_parse} section of #{file_to_parse}"
30
43
 
31
44
  app_json[field_to_parse] = parse_secrets_from app_variables
32
45
 
@@ -36,80 +49,60 @@ module Secrets
36
49
  private
37
50
 
38
51
  def secret?(string)
39
- if string.is_a? String
40
- string.start_with? 'secret:'
41
- else
42
- false
43
- end
52
+ string.is_a?(String) && string.start_with?('secret:')
44
53
  end
45
54
 
46
- def secret_file_path_from(secret)
47
- secret_file_path = secret[secret.index(':') + 1..secret.rindex(':') - 1]
48
- Helpers.expand_param_from_env secret_file_path
49
- end
55
+ def secrets_from(secret_file)
56
+ return @secret_variables[secret_file] if already_decrypted?(secret_file)
50
57
 
51
- def secret_key_from(secret)
52
- secret[secret.rindex(':') + 1..secret.length]
58
+ encrypted_secrets_io = @config.s3.download(secret_file + SECRETS_FILE_SUFFIX)
59
+ decrypted_secrets = @config.s3.decrypt(encrypted_secrets_io)
60
+
61
+ JSON.parse(decrypted_secrets)
53
62
  end
54
63
 
55
- def download(file)
56
- bucket_name = file[0, file.index('/')]
57
- file = file[file.index('/') + 1..file.length] + SECRETS_FILE_SUFFIX
58
- tmp_file = "/tmp/secrets#{SECRETS_FILE_SUFFIX}"
64
+ def parse_secrets_from(variables)
65
+ variables.each_pair do |key, value|
66
+ next unless secret?(value)
59
67
 
60
- logger.info "Downloading #{file} from #{bucket_name}" if logger?
68
+ secret_file = secret_file_from(value)
69
+ secret_key = secret_key_from(value)
61
70
 
62
- File.open(tmp_file, 'wb') do |secret_file|
63
- @config[:s3_client].get_object({ bucket: bucket_name, key: file }, target: secret_file)
71
+ @secret_variables[secret_file] = secrets_from(secret_file)
72
+
73
+ logger.info "Updating #{key} value"
74
+ variables[key] = secret_value_from(secret_file, secret_key)
64
75
  end
65
76
 
66
- tmp_file
77
+ variables
67
78
  end
68
79
 
69
- def decrypt(file)
70
- kms = @config[:kms_client]
71
-
72
- kms.decrypt(
73
- ciphertext_blob: IO.read(file)
74
- )
80
+ def already_decrypted?(secret_file)
81
+ @secret_variables.key?(secret_file)
75
82
  end
76
83
 
77
- def extract_secrets_from(secret_file)
78
- encrypted_secrets_file = download secret_file
79
- decrypted_secrets_file = decrypt encrypted_secrets_file
80
-
81
- JSON.parse(decrypted_secrets_file.plaintext)
84
+ def secret_file_from(secret)
85
+ Helpers.expand_param_from_env(secret).split(':')[1]
82
86
  end
83
87
 
84
- def parse_secrets_from(variables)
85
- secret_variables = {}
86
-
87
- variables.each_pair do |key, value|
88
- next unless secret?(value)
89
-
90
- secret = value
91
-
92
- secret_file = secret_file_path_from(secret)
93
- secret_key = secret_key_from(secret)
94
-
95
- unless secret_variables.key?(secret_file)
96
- secret_variables[secret_file] = extract_secrets_from secret_file
97
- end
98
-
99
- logger.info "Updating #{key} value" if logger?
88
+ def secret_key_from(secret)
89
+ Helpers.expand_param_from_env(secret).split(':')[2]
90
+ end
100
91
 
101
- variables[key] = secret_variables[secret_file][secret_key]
92
+ def secret_value_from(secret_file, secret_key)
93
+ unless secret_key_exists?(secret_file, secret_key)
94
+ raise Secrets::Errors::NoSuchKey, "Secret key #{secret_key} does not exist in #{secret_file}"
102
95
  end
103
96
 
104
- variables
97
+ @secret_variables[secret_file][secret_key]
105
98
  end
106
99
 
107
- def logger?
108
- !logger.nil?
100
+ def secret_key_exists?(secret_file, secret_key)
101
+ !@secret_variables[secret_file][secret_key].nil?
109
102
  end
110
103
 
111
104
  def logger
112
- @config[:logger]
105
+ @config.logger
113
106
  end
114
107
  end
115
108
  end
@@ -0,0 +1,38 @@
1
+ require 'aws-sdk-s3'
2
+ require 'json'
3
+ require 'logger'
4
+ require_relative 'helpers'
5
+
6
+ module Secrets
7
+ module Errors
8
+ class NoSuchFile < StandardError; end
9
+ end
10
+
11
+ class S3
12
+ def initialize(s3_client, kms_client, logger)
13
+ @s3_client = s3_client
14
+ @kms_client = kms_client
15
+ @logger = logger
16
+ end
17
+
18
+ def download(filename)
19
+ bucket_name, file = filename.split('/', 2)
20
+
21
+ @logger.info "Downloading #{file} from #{bucket_name}"
22
+ begin
23
+ resp = @s3_client.get_object(bucket: bucket_name, key: file)
24
+ resp.body
25
+ rescue Aws::S3::Errors::NoSuchKey
26
+ raise Secrets::Errors::NoSuchFile, "Secret file #{file} does not exist in #{bucket_name}"
27
+ end
28
+ end
29
+
30
+ def decrypt(io)
31
+ @kms_client.decrypt(ciphertext_blob: io.read).plaintext
32
+ end
33
+
34
+ def logger
35
+ @config.logger
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module SecretsParser
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secrets_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paco Sanchez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-10 00:00:00.000000000 Z
11
+ date: 2019-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,7 @@ files:
66
66
  - lib/secrets_parser.rb
67
67
  - lib/secrets_parser/helpers.rb
68
68
  - lib/secrets_parser/parser.rb
69
+ - lib/secrets_parser/s3.rb
69
70
  - lib/secrets_parser/version.rb
70
71
  - secrets_parser.gemspec
71
72
  homepage: https://github.com/peertransfer/secrets_parser
@@ -88,8 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
89
  - !ruby/object:Gem::Version
89
90
  version: '0'
90
91
  requirements: []
91
- rubyforge_project:
92
- rubygems_version: 2.7.7
92
+ rubygems_version: 3.0.3
93
93
  signing_key:
94
94
  specification_version: 4
95
95
  summary: Write a short summary, because RubyGems requires one.