hiera-eyaml-gpg_ruby 0.4
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/.gitignore +7 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +72 -0
- data/Rakefile +1 -0
- data/hiera-eyaml-gpg_ruby.gemspec +22 -0
- data/lib/hiera/backend/eyaml/encryptors/gpg.rb +177 -0
- data/lib/hiera/backend/eyaml/encryptors/gpg/eyaml_init.rb +3 -0
- data/lib/hiera/backend/eyaml/encryptors/gpg/version.rb +11 -0
- data/tools/regem.sh +6 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5b28ae68e2c44ec9d0affeb33fbd80c20b4c8c91
|
4
|
+
data.tar.gz: f51e6e955b0945a892b16a02c380208de56565a3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b604dca4f51feb1e09d9bff6a4fd8f611eb49945bd64438103d89f607c927e8ffa056b08ab50a0e7e838e1099e75739f285a0226fb8096c1d8b862f1a11b2c44
|
7
|
+
data.tar.gz: 6e9f289d7b9c55b61ee644e527a7ebee2afe6e0c1143e400511c5e106fda6c70a9359f966cb5039a944da3164e0cc0636c2e0397e51615e5a1095d2feaafe924
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Simon Hildrew
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
hiera-eyaml-gpg
|
2
|
+
===============
|
3
|
+
|
4
|
+
GPG encryption backend for the [hiera-eyaml](https://github.com/TomPoulton/hiera-eyaml) module.
|
5
|
+
|
6
|
+
Motivation
|
7
|
+
----------
|
8
|
+
|
9
|
+
The default PKCS#7 encryption scheme used by hiera-eyaml is perfect if only simple
|
10
|
+
encryption and decryption is needed.
|
11
|
+
|
12
|
+
However, if you are in a sizable team it helps to encrypt and decrypt data with multiple
|
13
|
+
keys. This means that each team member can hold their own private key and so can the puppetmaster.
|
14
|
+
Equally, each puppet master can have their own key if desired and when you need to rotate
|
15
|
+
keys for either users or puppet masters, re-encrypting your files and changing the key everywhere
|
16
|
+
does not need to be done in lockstep.
|
17
|
+
|
18
|
+
Requirements
|
19
|
+
------------
|
20
|
+
|
21
|
+
You'll need a working GPG setup with your own keypair and a public keyring containing any other
|
22
|
+
keys that you want to work
|
23
|
+
|
24
|
+
To get started, install the hiera-eyaml-gpg gem.
|
25
|
+
|
26
|
+
$ gem install hiera-eyaml-gpg
|
27
|
+
|
28
|
+
If you haven't already installed it, this requires and will install the hiera-eyaml gem, which you
|
29
|
+
should probably acquint yourself with at https://github.com/TomPoulton/hiera-eyaml.
|
30
|
+
|
31
|
+
Note that in order to install the gpgme gem you'll need to have the ruby development package installed
|
32
|
+
for your distribution.
|
33
|
+
|
34
|
+
How to use
|
35
|
+
----------
|
36
|
+
|
37
|
+
### Encrypting and editing encrypted data
|
38
|
+
|
39
|
+
Once installed you can create encrypted hiera-eyaml blocks that are encrypted using GPG.
|
40
|
+
|
41
|
+
$ eyaml encrypt -n gpg -s "A secret string to encrypt" --gpg-recipients bob@example.com,hiera@example.com
|
42
|
+
|
43
|
+
If you do not have a web of trust (i.e. you normally use --always-trust for gpg signing) then you'll need
|
44
|
+
to use the `--gpg-always-trust` option on the command line.
|
45
|
+
|
46
|
+
It gets pretty dull to keep on remembering which recipients you should use, so you can put them in a file
|
47
|
+
and specify that instead.
|
48
|
+
|
49
|
+
$ eyaml encrypt -n gpg -s "A secret string to encrypt" --gpg-recipients-file hiera-eyaml-gpg.recipients
|
50
|
+
|
51
|
+
In fact, when editing a file on disk and neither of the --gpg-recipient options are provided it will
|
52
|
+
automatically look for a `hiera-eyaml-gpg.recipients` file in the same directory as the file being edited
|
53
|
+
(or any parent in the tree). The first file discovered will be used allowing different parts of a hiera
|
54
|
+
tree to have different recipients if so desired.
|
55
|
+
|
56
|
+
Use `eyaml --help` for more details or look at the hiera-eyaml docs.
|
57
|
+
|
58
|
+
### Configuring hiera
|
59
|
+
|
60
|
+
Assuming you have a working `hiera` and `hiera-eyaml` then the only option you need to add is to
|
61
|
+
configure `:gpg_gnupghome:` in your hiera.yaml (under the `:eyaml:` section). This should be the
|
62
|
+
directory that contains the keyring etc for the user that can to decrypt the hiera data. Please note
|
63
|
+
that the private GPG key must not have a passphrase.
|
64
|
+
|
65
|
+
Authors
|
66
|
+
-------
|
67
|
+
|
68
|
+
- Simon Hildrew - Initial code
|
69
|
+
- Geoff Meakins - Created hiera-eyaml plugin framework that made this possible
|
70
|
+
|
71
|
+
### Contributors
|
72
|
+
- Walt Javins - Bug fixes
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hiera/backend/eyaml/encryptors/gpg/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "hiera-eyaml-gpg_ruby"
|
8
|
+
gem.version = Hiera::Backend::Eyaml::Encryptors::Gpg::VERSION
|
9
|
+
gem.description = "GPG encryptor for use with hiera-eyaml, in pure Ruby"
|
10
|
+
gem.summary = "Encryption plugin for hiera-eyaml backend for Hiera, in pure Ruby"
|
11
|
+
gem.author = "Raphaël Pinson"
|
12
|
+
gem.license = "MIT"
|
13
|
+
|
14
|
+
gem.homepage = "http://github.com/raphink/hiera-eyaml-gpg_ruby"
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency('hiera-eyaml', '>=1.3.8')
|
21
|
+
gem.add_dependency('ruby_gpg', '>=0.3.0')
|
22
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'gpgme'
|
2
|
+
require 'base64'
|
3
|
+
require 'pathname'
|
4
|
+
require 'hiera/backend/eyaml/encryptor'
|
5
|
+
require 'hiera/backend/eyaml/utils'
|
6
|
+
require 'hiera/backend/eyaml/options'
|
7
|
+
|
8
|
+
class Hiera
|
9
|
+
module Backend
|
10
|
+
module Eyaml
|
11
|
+
module Encryptors
|
12
|
+
|
13
|
+
class Gpg < Encryptor
|
14
|
+
|
15
|
+
self.tag = "GPG"
|
16
|
+
|
17
|
+
self.options = {
|
18
|
+
:gnupghome => { :desc => "Location of your GNUPGHOME directory",
|
19
|
+
:type => :string,
|
20
|
+
:default => "#{ENV[["HOME", "HOMEPATH"].detect { |h| ENV[h] != nil }]}/.gnupg" },
|
21
|
+
:always_trust => { :desc => "Assume that used keys are fully trusted",
|
22
|
+
:type => :boolean,
|
23
|
+
:default => false },
|
24
|
+
:recipients => { :desc => "List of recipients (comma separated)",
|
25
|
+
:type => :string },
|
26
|
+
:recipients_file => { :desc => "File containing a list of recipients (one on each line)",
|
27
|
+
:type => :string }
|
28
|
+
}
|
29
|
+
|
30
|
+
@@passphrase_cache = Hash.new
|
31
|
+
|
32
|
+
def self.passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
|
33
|
+
begin
|
34
|
+
system('stty -echo')
|
35
|
+
|
36
|
+
unless @@passphrase_cache.has_key?(uid_hint)
|
37
|
+
@@passphrase_cache[uid_hint] = ask("Enter passphrase for #{uid_hint}: ") { |q| q.echo = '' }
|
38
|
+
$stderr.puts
|
39
|
+
end
|
40
|
+
passphrase = @@passphrase_cache[uid_hint]
|
41
|
+
|
42
|
+
io = IO.for_fd(fd, 'w')
|
43
|
+
io.puts(passphrase)
|
44
|
+
io.flush
|
45
|
+
ensure
|
46
|
+
(0 ... $_.length).each do |i| $_[i] = ?0 end if $_
|
47
|
+
system('stty echo')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.find_recipients
|
52
|
+
recipient_option = self.option :recipients
|
53
|
+
recipients = if !recipient_option.nil?
|
54
|
+
debug("Using --recipients option")
|
55
|
+
recipient_option.split(",")
|
56
|
+
else
|
57
|
+
recipient_file_option = self.option :recipients_file
|
58
|
+
recipient_file = if !recipient_file_option.nil?
|
59
|
+
debug("Using --recipients-file option")
|
60
|
+
Pathname.new(recipient_file_option)
|
61
|
+
else
|
62
|
+
debug("Searching for any hiera-eyaml-gpg.recipients files in path")
|
63
|
+
# if we are editing a file, look for a hiera-eyaml-gpg.recipients file
|
64
|
+
filename = case Eyaml::Options[:source]
|
65
|
+
when :file
|
66
|
+
Eyaml::Options[:file]
|
67
|
+
when :eyaml
|
68
|
+
Eyaml::Options[:eyaml]
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
if filename.nil?
|
74
|
+
nil
|
75
|
+
else
|
76
|
+
path = Pathname.new(filename).realpath.dirname
|
77
|
+
selected_file = nil
|
78
|
+
path.descend{|path| path
|
79
|
+
potential_file = path.join('hiera-eyaml-gpg.recipients')
|
80
|
+
selected_file = potential_file if potential_file.exist?
|
81
|
+
}
|
82
|
+
debug("Using file at #{selected_file}")
|
83
|
+
selected_file
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
unless recipient_file.nil?
|
88
|
+
recipient_file.readlines.map{ |line| line.strip }
|
89
|
+
else
|
90
|
+
[]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.encrypt plaintext
|
96
|
+
gnupghome = self.option :gnupghome
|
97
|
+
GPGME::Engine.home_dir = gnupghome
|
98
|
+
debug("GNUPGHOME is #{gnupghome}")
|
99
|
+
|
100
|
+
ctx = GPGME::Ctx.new
|
101
|
+
|
102
|
+
recipients = self.find_recipients
|
103
|
+
debug("Recipents are #{recipients}")
|
104
|
+
|
105
|
+
raise RecoverableError, 'No recipients provided, don\'t know who to encrypt to' if recipients.empty?
|
106
|
+
|
107
|
+
keys = recipients.map {|r|
|
108
|
+
key_to_use = ctx.keys(r).first
|
109
|
+
if key_to_use.nil?
|
110
|
+
raise RecoverableError, "No key found on keyring for #{r}"
|
111
|
+
end
|
112
|
+
key_to_use
|
113
|
+
}
|
114
|
+
debug("Keys: #{keys}")
|
115
|
+
|
116
|
+
always_trust = self.option(:always_trust)
|
117
|
+
unless always_trust
|
118
|
+
# check validity of recipients (this is possibly naive, but better than the unhelpful
|
119
|
+
# error that it would spit out otherwise)
|
120
|
+
keys.each do |key|
|
121
|
+
unless key.primary_uid.validity >= GPGME::VALIDITY_FULL
|
122
|
+
raise RecoverableError, "Key #{key.sha} (#{key.email}) not trusted (if key trust is established by another means then specify always-trust)"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
data = GPGME::Data.from_str(plaintext)
|
128
|
+
crypto = GPGME::Crypto.new(:always_trust => always_trust)
|
129
|
+
|
130
|
+
ciphertext = crypto.encrypt(data, :recipients => keys)
|
131
|
+
ciphertext.seek 0
|
132
|
+
ciphertext.read
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.decrypt ciphertext
|
136
|
+
gnupghome = self.option :gnupghome
|
137
|
+
GPGME::Engine.home_dir = gnupghome
|
138
|
+
debug("GNUPGHOME is #{gnupghome}")
|
139
|
+
|
140
|
+
ctx = if hiera?
|
141
|
+
GPGME::Ctx.new
|
142
|
+
else
|
143
|
+
GPGME::Ctx.new(:passphrase_callback => method(:passfunc))
|
144
|
+
end
|
145
|
+
|
146
|
+
if !ctx.keys.empty?
|
147
|
+
raw = GPGME::Data.new(ciphertext)
|
148
|
+
txt = GPGME::Data.new
|
149
|
+
|
150
|
+
begin
|
151
|
+
txt = ctx.decrypt(raw)
|
152
|
+
rescue GPGME::Error::DecryptFailed => e
|
153
|
+
warn("Fatal: Failed to decrypt ciphertext (check settings and that you are a recipient)")
|
154
|
+
raise e
|
155
|
+
rescue Exception => e
|
156
|
+
warn("Warning: General exception decrypting GPG file")
|
157
|
+
raise e
|
158
|
+
end
|
159
|
+
|
160
|
+
txt.seek 0
|
161
|
+
txt.read
|
162
|
+
else
|
163
|
+
warn("No usable keys found in #{gnupghome}. Check :gpg_gnupghome value in hiera.yaml is correct")
|
164
|
+
raise ArgumentError, "No usable keys found in #{gnupghome}. Check :gpg_gnupghome value in hiera.yaml is correct"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.create_keys
|
169
|
+
STDERR.puts "The GPG encryptor does not support creation of keys, use the GPG command lines tools instead"
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/tools/regem.sh
ADDED
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hiera-eyaml-gpg_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.4'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Raphaël Pinson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hiera-eyaml
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.3.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.8
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ruby_gpg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.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.3.0
|
41
|
+
description: GPG encryptor for use with hiera-eyaml, in pure Ruby
|
42
|
+
email:
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- ".gitignore"
|
48
|
+
- Gemfile
|
49
|
+
- LICENSE
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- hiera-eyaml-gpg_ruby.gemspec
|
53
|
+
- lib/hiera/backend/eyaml/encryptors/gpg.rb
|
54
|
+
- lib/hiera/backend/eyaml/encryptors/gpg/eyaml_init.rb
|
55
|
+
- lib/hiera/backend/eyaml/encryptors/gpg/version.rb
|
56
|
+
- tools/regem.sh
|
57
|
+
homepage: http://github.com/raphink/hiera-eyaml-gpg_ruby
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.2.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Encryption plugin for hiera-eyaml backend for Hiera, in pure Ruby
|
81
|
+
test_files: []
|