puppet-decrypt 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea
19
+ vendor
@@ -1,3 +1,13 @@
1
+ ## 0.2.0 (Aug 07, 2014)
2
+
3
+ Enhancements:
4
+ - Added an encrypt function (thanks @tioteath!)
5
+
6
+ Bugfixes:
7
+ - Fixed handling of absolute paths for to the secret key file (thanks @tioteath!)
8
+ - Removed unnecessary puts (thanks @tioteath!)
9
+ - Improved error handling (thanks @tioteath!)
10
+
1
11
  ## 0.1.1 (Jan 24, 2014)
2
12
 
3
13
  Enhancements:
data/Modulefile CHANGED
@@ -1,5 +1,5 @@
1
1
  name 'devopsy/puppet_decrypt'
2
- version '0.1.0'
2
+ version '0.1.1'
3
3
  source 'https://github.com/maxlinc/puppet-decrypt'
4
4
  author 'Max Lincoln'
5
5
  license 'Apache License, Version 2.0'
data/README.md CHANGED
@@ -65,7 +65,7 @@ $ gem install encryptor
65
65
  Puppet Decrypt can be installed with the puppet module subcommand, which is included in Puppet 2.7.14 and later.
66
66
 
67
67
  ``` shell
68
- $ sudo puppet module install puppet_decrypt
68
+ $ sudo puppet module install devopsy-puppet_decrypt
69
69
  ```
70
70
  The command will tell you where it is installing the module; take note:
71
71
 
@@ -119,6 +119,12 @@ In your puppet code, load the value normally and then pass it to decrypt.
119
119
  decrypt(hiera('database_password'))
120
120
  ```
121
121
 
122
+ Or encrypt a secret passing it to encrypt, if you need to save the secret to
123
+ external storage, for example.
124
+ ``` ruby
125
+ $encrypted_secret_to_save = encrypt($data)
126
+ ```
127
+
122
128
  ### Overriding the secret key
123
129
 
124
130
  Puppet Decrypt now supports using more than just the default secret key location. You can easily use multiple secret keys for the same project.
@@ -12,8 +12,16 @@ module Puppet
12
12
  end
13
13
 
14
14
  def decrypt_hash(hash)
15
- puts "Decrypting value: #{hash['value']}, secretkey: #{hash['secretkey']}"
16
- decrypt(hash['value'], hash['secretkey'])
15
+ decrypt(hash['value'], hash['secretkey'] || hash['secret_key'])
16
+ end
17
+
18
+ def encrypt_hash(hash)
19
+ secret_key = hash['secretkey'] || hash['secret_key'] ||
20
+ File.join(KEY_DIR, DEFAULT_KEY)
21
+ salt = hash['salt'] || SecureRandom.base64
22
+ iv = hash['iv'] || OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv
23
+
24
+ encrypt(hash['value'], secret_key, salt, iv)
17
25
  end
18
26
 
19
27
  def decrypt(value, secret_key_file)
@@ -1,9 +1,27 @@
1
+ require 'pathname'
1
2
  module Puppet
2
3
  module Decrypt
3
4
  class KeyLoader
4
5
  def load_key(secret_key_file)
5
- raise "Secret key file: #{secret_key_file} is not readable!" unless File.readable?(secret_key_file)
6
- secret_key = File.open(secret_key_file, &:readline).chomp
6
+
7
+ # Dot not add directory if absolute path provided
8
+ if Pathname.new(secret_key_file).absolute?
9
+ full_path = secret_key_file
10
+ else
11
+ full_path = File.join(ENV['PUPPET_DECRYPT_KEYDIR'] ||
12
+ Puppet::Decrypt::Decryptor::KEY_DIR, secret_key_file)
13
+ end
14
+
15
+ # Assume key file is specified as basename
16
+ if File.readable? full_path
17
+ secret_key_file = full_path
18
+ else
19
+ # Assume key file is specifed as full path
20
+ raise "Secret key file: #{secret_key_file} is not readable!" unless
21
+ File.readable? secret_key_file
22
+ end
23
+
24
+ File.open(secret_key_file, &:readline).chomp
7
25
  end
8
26
  end
9
27
  end
@@ -1,5 +1,5 @@
1
1
  module Puppet
2
2
  module Decrypt
3
- VERSION = "0.1.1"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -41,6 +41,10 @@ Puppet::Face.define(:crypt, Puppet::Decrypt::VERSION) do
41
41
  iv = options.delete(:iv) || OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv
42
42
  salt = options.delete(:salt) || SecureRandom.base64
43
43
  secretkey = options[:secretkey]
44
+ unless secretkey.nil?
45
+ secretkey = File.expand_path(secretkey) if secretkey.start_with? '.'
46
+ end
47
+
44
48
  Puppet::Decrypt::Decryptor.new(options).encrypt(plaintext_secret, secretkey, salt, iv)
45
49
  end
46
50
  end
@@ -56,4 +60,4 @@ Puppet::Face.define(:crypt, Puppet::Decrypt::VERSION) do
56
60
  Puppet::Decrypt::Decryptor.new(options).decrypt(encrypted_secret, secretkey)
57
61
  end
58
62
  end
59
- end
63
+ end
@@ -4,12 +4,15 @@ module Puppet::Parser::Functions
4
4
  newfunction(:decrypt, :type => :rvalue) do |args|
5
5
  options = {}
6
6
  decrypt_args = {}
7
- if args[0].is_a? String
8
- decrypt_args['value'] = args[0]
7
+
8
+ if args.first.is_a? String
9
+ decrypt_args['value'], decrypt_args['secret_key'] = args
10
+ elsif args.first.is_a? Hash
11
+ decrypt_args = args.first
9
12
  else
10
- decrypt_args = args[0]
11
- puts "Using hash: #{decrypt_args}"
13
+ raise TypeError, "Expected String or Hash, given #{args.first.class}"
12
14
  end
15
+
13
16
  Puppet::Decrypt::Decryptor.new(options).decrypt_hash(decrypt_args)
14
17
  end
15
18
  end
@@ -0,0 +1,31 @@
1
+ require 'puppet-decrypt'
2
+
3
+ module Puppet::Parser::Functions
4
+ newfunction(:encrypt, :type => :rvalue, :doc => <<-'DOC' ) do |args|
5
+ Encrypt data, using Decryptor.
6
+
7
+ This function expects four arguments:
8
+ - Data to encrypt.
9
+ - Secret key file path,
10
+ Puppet::Decrypt::Decryptor::DEFAULT_KEY by default.
11
+ Can be specified as basename in Puppet::Decrypt::Decryptor::KEY_DIR.
12
+ - Salt (optional), randomly generated by default.
13
+ - Initialization vector (optional), randomly generated by default,
14
+ mainly useful for tests.
15
+ DOC
16
+
17
+ encrypt_args = {}
18
+
19
+ if args.first.is_a? String
20
+ encrypt_args['value'], encrypt_args['secret_key'], encrypt_args['salt'],
21
+ encrypt_args['iv'] = args
22
+ elsif args.first.is_a? Hash
23
+ encrypt_args = args.first
24
+ else
25
+ raise TypeError, "Expected String or Hash, given #{args.first.class}"
26
+ end
27
+
28
+ Puppet::Decrypt::Decryptor.new.encrypt_hash(encrypt_args)
29
+
30
+ end
31
+ end
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
11
11
  gem.description = %q{A gem for encrypting/decrypting secret values for use with Puppet}
12
12
  gem.summary = %q{A shared secret strategy that works with any data source}
13
13
  gem.homepage = "https://github.com/maxlinc/puppet-decrypt"
14
- gem.required_ruby_version = '>= 1.9.0'
14
+ gem.required_ruby_version = '>= 1.8.7'
15
15
  notice = """
16
16
 
17
17
  Notice: The default master key location is now /etc/puppet-decrypt/encryptor_secret_key
@@ -30,7 +30,7 @@ This was done to more easily support multiple keys. If you are upgrading from a
30
30
  gem.add_dependency('encryptor', '~> 1.3')
31
31
  gem.add_development_dependency('rake')
32
32
  gem.add_development_dependency('cucumber')
33
- gem.add_development_dependency('rspec')
33
+ gem.add_development_dependency('rspec', '~> 2.14.1')
34
34
  gem.add_development_dependency('rspec-puppet')
35
35
  gem.add_development_dependency('puppetlabs_spec_helper')
36
36
  end
@@ -0,0 +1,63 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe 'encrypt' do
5
+ before(:all) do
6
+ mock_secret_key(Puppet::Decrypt::Decryptor::DEFAULT_FILE, 'masterkey')
7
+ end
8
+
9
+ let(:node) { 'testhost.example.com' }
10
+ extdata_path = File.expand_path(File.join(File.dirname(__FILE__),
11
+ '../../puppet/manifests/extdata'))
12
+
13
+ let :pre_condition do
14
+ "$extlookup_datadir = '#{extdata_path}' $extlookup_precedence = ['common', 'env_vagrant']"
15
+ end
16
+
17
+ let :salt do
18
+ 'test_salt'
19
+ end
20
+
21
+ let :iv do
22
+ "YS7nvbPsLP+pIJQ0waxV0w=="
23
+ end
24
+
25
+ context "unencrypted key" do
26
+ it "should encrypt plain string" do
27
+ subject.call(['blah']).should =~
28
+ Puppet::Decrypt::Decryptor::ENCRYPTED_PATTERN
29
+ end
30
+ end
31
+
32
+ context "encrypted key" do
33
+ it "should encrypt exact matches" do
34
+ subject.call(["flabberghaster", nil, salt, iv]).should ==
35
+ 'ENC[WnA7ezNPSZx2S01T67TCfA==:WVM3bnZiUHNMUCtwSUpRMHdheFYwdz09:dGVzdF9zYWx0]'
36
+ end
37
+ end
38
+
39
+ context "with secret key file" do
40
+ it "should encrypt exact matches" do
41
+ mock_secret_key('/etc/another_key', 'anotherkey')
42
+ subject.call(['value' => 'flabberghaster', 'secretkey' =>
43
+ '/etc/another_key', 'iv' => iv, 'salt' => salt]) =~
44
+ Puppet::Decrypt::Decryptor::ENCRYPTED_PATTERN
45
+
46
+ _, iv_hash, salt_hash = Regexp.last_match[2].split(':')
47
+ strict_decode64(iv_hash).should == iv
48
+ strict_decode64(salt_hash).should == salt
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ # Backported for ruby 1.8.7
55
+ def strict_decode64(str)
56
+ return Base64.strict_decode64(str) if Base64.respond_to? :strict_decode64
57
+
58
+ if str.include?("\n")
59
+ raise(ArgumentError,"invalid base64")
60
+ else
61
+ Base64.decode64(str)
62
+ end
63
+ end
metadata CHANGED
@@ -1,110 +1,124 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: puppet-decrypt
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
5
11
  platform: ruby
6
- authors:
12
+ authors:
7
13
  - mlincoln
8
14
  autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
- date: 2014-03-09 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: encryptor
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.3'
17
+
18
+ date: 2014-08-07 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ hash: 9
28
+ segments:
29
+ - 1
30
+ - 3
31
+ version: "1.3"
20
32
  type: :runtime
33
+ version_requirements: *id001
21
34
  prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
35
+ name: encryptor
36
+ - !ruby/object:Gem::Dependency
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
31
40
  - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
34
46
  type: :development
47
+ version_requirements: *id002
35
48
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
49
+ name: rake
50
+ - !ruby/object:Gem::Dependency
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
38
54
  - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id003
62
+ prerelease: false
42
63
  name: cucumber
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
64
+ - !ruby/object:Gem::Dependency
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ hash: 53
71
+ segments:
72
+ - 2
73
+ - 14
74
+ - 1
75
+ version: 2.14.1
48
76
  type: :development
77
+ version_requirements: *id004
49
78
  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
79
  name: rspec
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
80
+ - !ruby/object:Gem::Dependency
81
+ requirement: &id005 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
59
84
  - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
62
90
  type: :development
91
+ version_requirements: *id005
63
92
  prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
93
  name: rspec-puppet
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
94
+ - !ruby/object:Gem::Dependency
95
+ requirement: &id006 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
73
98
  - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
99
+ - !ruby/object:Gem::Version
100
+ hash: 3
101
+ segments:
102
+ - 0
103
+ version: "0"
76
104
  type: :development
105
+ version_requirements: *id006
77
106
  prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
107
  name: puppetlabs_spec_helper
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
108
  description: A gem for encrypting/decrypting secret values for use with Puppet
98
- email:
109
+ email:
99
110
  - max@devopsy.com
100
111
  executables: []
112
+
101
113
  extensions: []
114
+
102
115
  extra_rdoc_files: []
103
- files:
104
- - ".gitignore"
105
- - ".rspec"
106
- - ".rvmrc"
107
- - ".travis.yml"
116
+
117
+ files:
118
+ - .gitignore
119
+ - .rspec
120
+ - .rvmrc
121
+ - .travis.yml
108
122
  - ChangeLog.md
109
123
  - Gemfile
110
124
  - LICENSE.txt
@@ -132,42 +146,57 @@ files:
132
146
  - lib/puppet/application/crypt.rb
133
147
  - lib/puppet/face/crypt.rb
134
148
  - lib/puppet/parser/functions/decrypt.rb
149
+ - lib/puppet/parser/functions/encrypt.rb
135
150
  - puppet-decrypt.gemspec
136
151
  - spec/faces/crypt_spec.rb
137
152
  - spec/functions/decrypt_spec.rb
153
+ - spec/functions/encrypt_spec.rb
138
154
  - spec/puppet-decrypt/fake_key_loader.rb
139
155
  - spec/spec_helper.rb
156
+ has_rdoc: true
140
157
  homepage: https://github.com/maxlinc/puppet-decrypt
141
158
  licenses: []
142
- metadata: {}
143
- post_install_message: |2+
144
-
145
159
 
160
+ post_install_message: |+
161
+
162
+
146
163
  Notice: The default master key location is now /etc/puppet-decrypt/encryptor_secret_key
147
-
164
+
148
165
  This was done to more easily support multiple keys. If you are upgrading from a version older than
149
166
  0.1.0 you should move /etc/encryptor_secret_key to /etc/puppet-decrypt/encryptor_secret_key.
150
-
167
+
151
168
  rdoc_options: []
152
- require_paths:
169
+
170
+ require_paths:
153
171
  - lib
154
- required_ruby_version: !ruby/object:Gem::Requirement
155
- requirements:
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ none: false
174
+ requirements:
156
175
  - - ">="
157
- - !ruby/object:Gem::Version
158
- version: 1.9.0
159
- required_rubygems_version: !ruby/object:Gem::Requirement
160
- requirements:
176
+ - !ruby/object:Gem::Version
177
+ hash: 57
178
+ segments:
179
+ - 1
180
+ - 8
181
+ - 7
182
+ version: 1.8.7
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
184
+ none: false
185
+ requirements:
161
186
  - - ">="
162
- - !ruby/object:Gem::Version
163
- version: '0'
187
+ - !ruby/object:Gem::Version
188
+ hash: 3
189
+ segments:
190
+ - 0
191
+ version: "0"
164
192
  requirements: []
193
+
165
194
  rubyforge_project:
166
- rubygems_version: 2.2.0
195
+ rubygems_version: 1.6.2
167
196
  signing_key:
168
- specification_version: 4
197
+ specification_version: 3
169
198
  summary: A shared secret strategy that works with any data source
170
- test_files:
199
+ test_files:
171
200
  - features/fixtures/data/overridden_secret_key.yaml
172
201
  - features/fixtures/data/simple.yaml
173
202
  - features/fixtures/hiera.yaml
@@ -181,5 +210,6 @@ test_files:
181
210
  - features/support/env.rb
182
211
  - spec/faces/crypt_spec.rb
183
212
  - spec/functions/decrypt_spec.rb
213
+ - spec/functions/encrypt_spec.rb
184
214
  - spec/puppet-decrypt/fake_key_loader.rb
185
215
  - spec/spec_helper.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 4c098cca8fcd1228c7d2e82d7b8615f7189e77e8
4
- data.tar.gz: b2ddb9f7aaa99af9d68812a7d86a95c7d04da32e
5
- SHA512:
6
- metadata.gz: b19f454ff00dd36f2f83848c1a4be5df1ec6065b6dcd487364da4c981cce7350c6789862092df40681bcefaa2363e46ee8d4735cb751abec3b6e7400d4a6b0c2
7
- data.tar.gz: 45b6964e742c45152804e4d6eac02324702515dcefc49ce87cf7a0eeb0268b744229ae2aec6f99b0a84ac5146de98da15519d6edb31e94c282b4af7c162f4be7