Skip to content

Commit f1e973e

Browse files
authored
Merge pull request #221 from alexjfisher/compare_values_after_decrypting
Compare decrypted values to see if they are insync
2 parents fa08184 + 24a0da4 commit f1e973e

File tree

6 files changed

+127
-9
lines changed

6 files changed

+127
-9
lines changed

lib/puppet_x/puppetlabs/splunk/type.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require File.join(File.dirname(__FILE__), '..', '..', 'voxpupuli/splunk/util')
2+
13
module PuppetX
24
module Puppetlabs
35
module Splunk
@@ -26,6 +28,15 @@ def self.clone_type(type)
2628
munge do |v|
2729
v.to_s.strip
2830
end
31+
def insync?(is) # rubocop:disable Lint/NestedMethodDefinition
32+
secrets_file_path = File.join(provider.class.file_path, 'auth/splunk.secret')
33+
if File.file?(secrets_file_path)
34+
PuppetX::Voxpupuli::Splunk::Util.decrypt(secrets_file_path, is) == should
35+
else
36+
Puppet.warning('Secrets file NOT found')
37+
is == should
38+
end
39+
end
2940
end
3041
type.newparam(:setting) do
3142
desc 'The setting being defined.'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require 'openssl'
2+
require 'base64'
3+
4+
module PuppetX
5+
module Voxpupuli
6+
module Splunk
7+
class Util
8+
def self.decrypt(secrets_file, value)
9+
return value unless value.start_with?('$7$')
10+
11+
Puppet.debug "Decrypting splunk >= 7.2 data using secret from #{secrets_file}"
12+
value.slice!(0, 3)
13+
data = Base64.strict_decode64(value)
14+
splunk_secret = IO.binread(secrets_file).chomp
15+
16+
iv = data.bytes[0, 16].pack('c*')
17+
tag = data.bytes[-16..-1].pack('c*')
18+
ciphertext = data.bytes[16..-17].pack('c*')
19+
20+
decipher = OpenSSL::Cipher::AES.new(256, :GCM).decrypt
21+
decipher.key = OpenSSL::PKCS5.pbkdf2_hmac(splunk_secret, 'disk-encryption', 1, 32, OpenSSL::Digest::SHA256.new)
22+
decipher.iv_len = 16
23+
decipher.iv = iv
24+
decipher.auth_tag = tag
25+
decipher.auth_data = ''
26+
27+
decipher.update(ciphertext) + decipher.final
28+
end
29+
end
30+
end
31+
end
32+
end

spec/acceptance/splunk_enterprise_spec.rb

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
require 'spec_helper_acceptance'
22

33
describe 'splunk enterprise class' do
4+
init = shell('/bin/readlink /sbin/init', acceptable_exit_codes: [0, 1]).stdout
5+
service_name = if init.include? 'systemd'
6+
'Splunkd'
7+
else
8+
'splunk'
9+
end
10+
411
context 'default parameters' do
512
# Using puppet_apply as a helper
613
it 'works idempotently with no errors' do
@@ -17,13 +24,6 @@ class { '::splunk::enterprise': }
1724
it { is_expected.to be_installed }
1825
end
1926

20-
init = shell('/bin/readlink /sbin/init', acceptable_exit_codes: [0, 1]).stdout
21-
service_name = if init.include? 'systemd'
22-
'Splunkd'
23-
else
24-
'splunk'
25-
end
26-
2727
describe service(service_name) do
2828
it { is_expected.to be_enabled }
2929
it { is_expected.to be_running }
@@ -39,5 +39,21 @@ class { '::splunk::enterprise': }
3939
it { is_expected.to be_grouped_into 'root' }
4040
end
4141
end
42+
43+
# Uninstall so that splunkforwarder tests aren't affected by this set of tests
44+
context 'uninstalling splunk' do
45+
it do
46+
pp = <<-EOS
47+
service { '#{service_name}': ensure => stopped }
48+
package { 'splunk': ensure => purged }
49+
file { '/opt/splunk': ensure => absent, force => true, require => Package['splunk'] }
50+
file { '/etc/init.d/splunk': ensure => absent, require => Package['splunk'] }
51+
EOS
52+
apply_manifest(pp, catch_failures: true)
53+
end
54+
describe package('splunk') do
55+
it { is_expected.not_to be_installed }
56+
end
57+
end
4258
end
4359
end

spec/acceptance/splunk_forwarder_spec.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,27 @@
55
# Using puppet_apply as a helper
66
it 'works idempotently with no errors' do
77
pp = <<-EOS
8-
class { '::splunk::params':
8+
class { 'splunk::params':
99
}
10-
class { '::splunk::forwarder':
10+
class { 'splunk::forwarder':
1111
splunkd_port => 8090,
1212
}
13+
splunkforwarder_output { 'tcpout:splunkcloud/sslPassword':
14+
value => 'super_secure_password',
15+
}
1316
EOS
1417

1518
# Run it twice and test for idempotency
1619
apply_manifest(pp, catch_failures: true)
1720
apply_manifest(pp, catch_changes: true)
1821
end
1922

23+
describe file('/opt/splunkforwarder/etc/system/local/outputs.conf') do
24+
it { is_expected.to be_file }
25+
its(:content) { is_expected.to match %r{^sslPassword} }
26+
its(:content) { is_expected.to match %r{^sslPassword = \$7\$} }
27+
end
28+
2029
describe package('splunkforwarder') do
2130
it { is_expected.to be_installed }
2231
end

spec/unit/puppet/type/splunk_types_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,34 @@
7171
expect(described_class.provider(:ini_setting).file_name).to eq(file_name)
7272
end
7373
end
74+
75+
describe 'value property' do
76+
it 'has a value property' do
77+
expect(described_class.attrtype(:value)).to eq(:property)
78+
end
79+
context 'when testing value is insync' do
80+
let(:resource) { described_class.new(title: 'foo/bar', value: 'value') }
81+
let(:property) { resource.property(:value) }
82+
83+
before do
84+
Puppet::Type.type(:splunk_config).new(
85+
name: 'config',
86+
server_confdir: '/opt/splunk/etc',
87+
forwarder_confdir: '/opt/splunkforwarder/etc'
88+
).generate
89+
end
90+
91+
it 'is insync if unencrypted `is` value matches `should` value' do
92+
property.should = 'value'
93+
expect(property).to be_safe_insync('value')
94+
end
95+
it 'is insync if encrypted `is` value matches `should` value after being decrypted' do
96+
property.should = 'temp1234'
97+
allow(File).to receive(:file?).with(%r{/opt/splunk(forwarder)?/etc/auth/splunk\.secret$}).and_return(true)
98+
allow(IO).to receive(:binread).with(%r{/opt/splunk(forwarder)?/etc/auth/splunk\.secret$}).and_return('JX7cQAnH6Nznmild8MvfN8/BLQnGr8C3UYg3mqvc3ArFkaxj4gUt1RUCaRBD/r0CNn8xOA2oKX8/0uyyChyGRiFKhp6h2FA+ydNIRnN46N8rZov8QGkchmebZa5GAM5U50GbCCgzJFObPyWi5yT8CrSCYmv9cpRtpKyiX+wkhJwltoJzAxWbBERiLp+oXZnN3lsRn6YkljmYBqN9tZLTVVpsLvqvkezPgpv727Fd//5dRoWsWBv2zRp0mwDv3tj')
99+
expect(property).to be_safe_insync('$7$aTVkS01HYVNJUk5wSnR5NIu4GXLhj2Qd49n2B6Y8qmA/u1CdL9JYxQ==')
100+
end
101+
end
102+
end
74103
end
75104
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
require 'spec_helper'
2+
require 'puppet_x/voxpupuli/splunk/util'
3+
4+
describe PuppetX::Voxpupuli::Splunk::Util do
5+
describe '.decrypt' do
6+
context 'when called with an unencrypted value' do
7+
it 'returns the value unmodified' do
8+
expect(described_class.decrypt('secrets_file', 'non_encrypted_value')).to eq 'non_encrypted_value'
9+
end
10+
end
11+
context 'when called with splunk 7.2 encrypted value' do
12+
let(:encrypted_value) { '$7$aTVkS01HYVNJUk5wSnR5NIu4GXLhj2Qd49n2B6Y8qmA/u1CdL9JYxQ==' }
13+
let(:splunk_secret) { 'JX7cQAnH6Nznmild8MvfN8/BLQnGr8C3UYg3mqvc3ArFkaxj4gUt1RUCaRBD/r0CNn8xOA2oKX8/0uyyChyGRiFKhp6h2FA+ydNIRnN46N8rZov8QGkchmebZa5GAM5U50GbCCgzJFObPyWi5yT8CrSCYmv9cpRtpKyiX+wkhJwltoJzAxWbBERiLp+oXZnN3lsRn6YkljmYBqN9tZLTVVpsLvqvkezPgpv727Fd//5dRoWsWBv2zRp0mwDv3tj' }
14+
15+
it 'returns decrypted value' do
16+
allow(IO).to receive(:binread).with('secrets_file').and_return(splunk_secret)
17+
expect(described_class.decrypt('secrets_file', encrypted_value)).to eq 'temp1234'
18+
end
19+
end
20+
end
21+
end

0 commit comments

Comments
 (0)