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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +112 -0
- data/Rakefile +27 -0
- data/bin/secrets-manager +5 -0
- data/bin/secrets_manager +5 -0
- data/lib/secrets_manager/cli/base.rb +41 -0
- data/lib/secrets_manager/cli/pull.rb +31 -0
- data/lib/secrets_manager/cli.rb +28 -0
- data/lib/secrets_manager/client.rb +32 -0
- data/lib/secrets_manager/config.rb +64 -0
- data/lib/secrets_manager/helpers.rb +16 -0
- data/lib/secrets_manager/version.rb +3 -0
- data/lib/secrets_manager.rb +5 -0
- data/lib/tasks/productive_secrets_tasks.rake +4 -0
- metadata +117 -0
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
|
data/bin/secrets-manager
ADDED
data/bin/secrets_manager
ADDED
@@ -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
|
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: []
|