secrets_manager 0.1.0.rc1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 591fa8a47b755504c95eaa952c9b5fbe1242c1f22d32258846b57b2bd02a922e
4
+ data.tar.gz: 8412a6e7b76eb42744ad8f5506f003cbc71081de6f653190cb12f8793527bb5f
5
+ SHA512:
6
+ metadata.gz: e50276d674daca2c4c399f7a1437fcdf41b6dfc1dee7cd0047957b8fc5d7323188bad374fa6e7dd0338b50f9bff3c7ea522770be9acdd4cf0809c4cb011f5977
7
+ data.tar.gz: bdfb15987e387471426c3abbcd05d843afbdce137f0e52135876a6c2f6ebfdcce58a1e9dc2f3416092d408c14ebc487c00549e06ac70ea601b30125564a9a9fd
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 hmatic
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Secrets Manager gem
2
+ Easy secrets management for AWS Secret Manager service.
3
+ This gem provides:
4
+ - Rails hook (injects secrets directly into ENV when booting Rails)
5
+ - CLI (pull, read, delete, update secrets using simple CLI interface)
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'secrets_manager'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install secrets_manager
22
+ ```
23
+
24
+ ## Configure
25
+ Secret_manager uses `secrets.json` to configure how it handles secrets. Here is example of secrets.json file together with explaination of each option:
26
+
27
+ ```json
28
+ {
29
+ "app": {
30
+ "id": "$environment/app",
31
+ "input": "json",
32
+ "type": "env",
33
+ "path": "config/application.yml"
34
+ },
35
+ "tmp_file_secret": {
36
+ "id": "production/tmp_secret",
37
+ "input": "plaintext",
38
+ "type": "file",
39
+ "path": "tmp/tmp_secret.txt"
40
+ }
41
+ }
42
+ ```
43
+ ID is obligatory, other options can be left out and default will be used.
44
+
45
+ #### ID
46
+ Represents secret_id used to retrieve secret from AWS Secret Manager.
47
+
48
+ It is possible to provide `$environment` which will be interpolated to:
49
+ - value provided in `--environment` or `-e` option when using CLI commands
50
+ - `Rails.env` when using Rails hook
51
+
52
+ #### INPUT
53
+ Defines format of secret coming from AWS Secret Manager. Two possible values: `json` and `plaintext`.
54
+
55
+ If specified as `json`, secret will be parsed in KEY-VALUE format.
56
+
57
+ If specified as `plaintext`, secret will be treated as string.
58
+
59
+ Defaults to `json`.
60
+
61
+ #### TYPE
62
+ Defines type of injection during boot. Two possible values: `env` and `file`.
63
+
64
+ If specified as `env`, secret will be injected into ENV variables during Rails boot.
65
+
66
+ If specified as `file`, file containing secret will be created during Rails boot.
67
+
68
+ Defaults to `env`.
69
+
70
+ #### PATH
71
+ Defines path where secrets will be pulled when using CLI.
72
+
73
+ Rails hook will check if this file exists. If it exists, Rails hook will ignore secrets which have this path specified in configuration.
74
+
75
+ Defaults to `config/application.yml`.
76
+
77
+ ## Authorization
78
+ Use same authorization process as AWS-CLI:
79
+ https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
80
+
81
+ ## Rails usage
82
+ In order to use Rails hook, it's enough to define this gem in Gemfile.
83
+
84
+ ## CLI usage
85
+ Secrets Manager CLI provides several commands:
86
+
87
+ ### HELP
88
+ List all commands and their descriptions:
89
+ ```
90
+ secrets-manager help
91
+ ```
92
+ You can use it with specific command:
93
+ ```
94
+ secrets-manager help <command>
95
+ ```
96
+
97
+ ### PULL
98
+ Pull secrets locally:
99
+ ```
100
+ secrets-manager pull
101
+ ```
102
+ Options:
103
+ - `--environment` (`-e`) - interpolate $environment variable in configuration (defaults to **development**)
104
+ - `--path` (`-p`) - path to configuration file (defaults to **secrets.json**)
105
+
106
+ ### More commands coming soon :)
107
+
108
+ ## Contributing
109
+ Contributing is possible once v1.0 is released. Feel free to open PRs/issues.
110
+
111
+ ## License
112
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SecretsManager'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "secrets_manager/cli"
4
+
5
+ SecretsManager::CLI.start
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "secrets_manager/cli"
4
+
5
+ SecretsManager::CLI.start
@@ -0,0 +1,41 @@
1
+ require 'secrets_manager/config'
2
+ require 'secrets_manager/client'
3
+ require 'secrets_manager/helpers'
4
+
5
+ module SecretsManager
6
+ module Cli
7
+ class Base
8
+ include SecretsManager::Helpers
9
+
10
+ attr_reader :client
11
+
12
+ def initialize(options)
13
+ @options = options
14
+ @client = SecretsManager::Client.new
15
+ end
16
+
17
+ def run
18
+ config.init
19
+ execute
20
+ end
21
+
22
+ private
23
+
24
+ def execute
25
+ raise NotImplementedError
26
+ end
27
+
28
+ def config_path
29
+ File.join(Dir.pwd, @options['path'])
30
+ end
31
+
32
+ def environment
33
+ @options['environment']
34
+ end
35
+
36
+ def config
37
+ @config ||= SecretsManager::Config.new(config_path, environment)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ require 'secrets_manager/cli/base'
2
+ require 'yaml'
3
+
4
+ module SecretsManager
5
+ module Cli
6
+ class Pull < Base
7
+
8
+ private
9
+
10
+ def execute
11
+ config.secrets.each do |secret|
12
+ write_to_file(output(secret), secret.path) && sucess_msg(secret)
13
+ end
14
+ end
15
+
16
+ def output(secret)
17
+ return client.get_secret_string(secret.id) if secret.plaintext?
18
+
19
+ secret_hash = client.get_secret_hash(secret.id)
20
+
21
+ return if secret_hash.nil?
22
+ return secret_hash.to_yaml[4..-1] if secret.yaml_output?
23
+ return JSON.pretty_generate secret_hash if secret.json_output?
24
+ end
25
+
26
+ def sucess_msg(secret)
27
+ puts "Pulled \"#{secret.id}\" secret to \"#{secret.path}\"."
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ require 'thor'
2
+
3
+ module SecretsManager
4
+ class CLI < Thor
5
+ # secrets-manager pull
6
+ desc "pull", "Pull secrets"
7
+
8
+ method_option 'path',
9
+ aliases: ['-p'],
10
+ default: 'secrets.json',
11
+ desc: 'Specify a json configuration file path'
12
+ method_option 'environment',
13
+ aliases: ['-e'],
14
+ default: 'development',
15
+ desc: 'Specify current environment'
16
+
17
+ def pull
18
+ require 'secrets_manager/cli/pull'
19
+ SecretsManager::Cli::Pull.new(options).run
20
+ end
21
+
22
+ # TODO: secrets-manager read
23
+ # TODO: secrets-manager delete
24
+ # TODO: secrets-manager update
25
+ # TODO: secrets-manager update-value
26
+ # TODO: secrets-manager create
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ require 'aws-sdk-secretsmanager'
2
+
3
+ module SecretsManager
4
+ class Client
5
+ def initialize
6
+ @client = Aws::SecretsManager::Client.new
7
+ end
8
+
9
+ def get_secret_string(secret_id)
10
+ @client.get_secret_value(secret_id: secret_id).secret_string
11
+ rescue Aws::SecretsManager::Errors::ServiceError
12
+ aws_error(secret_id)
13
+ end
14
+
15
+ def get_secret_hash(secret_id)
16
+ return if (secret_string = get_secret_string(secret_id)).nil?
17
+
18
+ JSON.parse(secret_string)
19
+ rescue JSON::ParserError
20
+ json_parsing_error(secret_id)
21
+ end
22
+
23
+ def json_parsing_error(secret_id)
24
+ puts "Could not parse JSON in \"#{secret_id}\" secret. Please check your secret contents."
25
+ puts 'You can also define your secret type as "plaintext".'
26
+ end
27
+
28
+ def aws_error(secret_id)
29
+ puts "Could not retrieve \"#{secret_id}\" secret from AWS. Please check you configured everything correctly."
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,64 @@
1
+ require 'json'
2
+
3
+ module SecretsManager
4
+ class Config
5
+ attr_reader :secrets
6
+
7
+ def initialize(config_path, environment)
8
+ @config_path = config_path
9
+ @environment = environment
10
+ @secrets = []
11
+ end
12
+
13
+ def init
14
+ return unless File.file?(@config_path)
15
+
16
+ configuration = JSON.parse(config_string, symbolize_names: true)
17
+ configuration.each do |k, v|
18
+ @secrets << SecretConfig.new(k, v[:id], v[:input], v[:type], v[:path])
19
+ end
20
+
21
+ self
22
+ end
23
+
24
+ def config_string
25
+ File.read(@config_path).gsub('$environment', @environment)
26
+ end
27
+
28
+ class SecretConfig
29
+ attr_reader :name, :id, :input, :type, :path
30
+
31
+ def initialize(name, id, input, type, path)
32
+ @name = name
33
+ @id = id
34
+ @input = input || 'json'
35
+ @type = type || 'env'
36
+ @path = path || 'config/application.yml'
37
+ end
38
+
39
+ def plaintext?
40
+ input == 'plaintext'
41
+ end
42
+
43
+ def json?
44
+ input == 'json'
45
+ end
46
+
47
+ def to_env?
48
+ type == 'env'
49
+ end
50
+
51
+ def to_file?
52
+ type == 'file'
53
+ end
54
+
55
+ def yaml_output?
56
+ path.strip.end_with? '.yml'
57
+ end
58
+
59
+ def json_output?
60
+ path.strip.end_with? '.json'
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,16 @@
1
+ require 'pathname'
2
+
3
+ module SecretsManager
4
+ module Helpers
5
+ def write_to_file(content, file_path)
6
+ return false if content.nil? || content.empty?
7
+
8
+ Pathname(file_path).dirname.mkpath
9
+ File.open(File.join(Dir.pwd, file_path), 'w') do |f|
10
+ f.puts content
11
+ end
12
+
13
+ true
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module SecretsManager
2
+ VERSION = '0.1.0.rc1'.freeze
3
+ end
@@ -0,0 +1,5 @@
1
+ require "secrets_manager/railtie"
2
+
3
+ module SecretsManager
4
+
5
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :productive_secrets do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: secrets_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.rc1
5
+ platform: ruby
6
+ authors:
7
+ - hmatic
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-12-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-secretsmanager
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.20.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.20.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Gem provides CLI for secrets manipulation and Rails hook which injects
70
+ secrets into ENV upon booting.
71
+ email:
72
+ - web.hmatic@gmail.com
73
+ executables:
74
+ - secrets_manager
75
+ - secrets-manager
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - MIT-LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - bin/secrets-manager
83
+ - bin/secrets_manager
84
+ - lib/secrets_manager.rb
85
+ - lib/secrets_manager/cli.rb
86
+ - lib/secrets_manager/cli/base.rb
87
+ - lib/secrets_manager/cli/pull.rb
88
+ - lib/secrets_manager/client.rb
89
+ - lib/secrets_manager/config.rb
90
+ - lib/secrets_manager/helpers.rb
91
+ - lib/secrets_manager/version.rb
92
+ - lib/tasks/productive_secrets_tasks.rake
93
+ homepage: http://hrvojematic.com
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.3.1
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.7.8
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Easy secret management for AWS Secret Manager
117
+ test_files: []