Skip to content

Commit 67644cd

Browse files
committed
Merge remote-tracking branch 'JohnLyman/issue-156-pe-token-for-puppetdb' into kpaulisse-release-branch
2 parents 153cea5 + d0d6615 commit 67644cd

File tree

9 files changed

+140
-2
lines changed

9 files changed

+140
-2
lines changed

doc/configuration-puppetdb.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ The following settings can be used in a [configuration file](/doc/configuration.
3636
| `settings[:puppetdb_ssl_client_key]` | TEXT of the private key of the client SSL keypair used to authenticate to PuppetDB. Note: This variable is not set to a file path, which means you will likely want to use means you will likely want to use `File.read(...)` if you are configuring this to be read from a file. |
3737
| `settings[:puppetdb_ssl_client_pem]` | Concatenation of the text of `puppetdb_ssl_client_key` and `puppetdb_ssl_client_cert` as previously described. This is a good alternative if your certificate chain is complex and it's easier just to put everything in a single place. Note: this option is second in precedence; if `settings[:puppetdb_ssl_client_cert]` and `settings[:puppetdb_ssl_client_key]` are both set, this will be ignored. |
3838
| `settings[:puppetdb_ssl_client_password]` | Plain text string containing the password to unlock the private key. For keys generated by the Puppet Master CA, this is not required and should be left undefined. |
39+
| `settings[:puppetdb_token]` | TEXT containing the PE RBAC token used to authenticate to PuppetDB. Note: This variable is not set to a file path, which means you will likely want to use `File.read(...)` if you are configuring this to be read from a file. |
3940

4041
## Supplying necessary information via the command line
4142

@@ -48,6 +49,8 @@ The following arguments can be used on the command line.
4849
| --puppetdb-ssl-client-cert FILENAME | Path to the certificate of the client SSL keypair. |
4950
| --puppetdb-ssl-client-key FILENAME | Path to the private key of the client SSL keypair. |
5051
| --puppetdb-ssl-client-password PASSWORD_STRING | Plain text string containing the password to unlock the private key. For keys generated by the Puppet Master CA, this is not required. |
52+
| --puppetdb-token STRING | String containing the PE RBAC token used to authenticate to PuppetDB. |
53+
| --puppetdb-token-file FILENAME | Path to the PE RBAC token file used to authenticate to PuppetDB. |
5154

5255
## Supplying necessary information via the environment
5356

lib/octocatalog-diff/cli/options/pe_enc_token_file.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
def parse(parser, options)
1313
parser.on('--pe-enc-token-file PATH', 'Path containing token for PE node classifier, relative or absolute') do |x|
1414
proposed_token_path = x.start_with?('/') ? x : File.join(options[:basedir], x)
15-
raise Errno::ENOENT, "Provided token (#{proposed_token_path}) does not exist" unless File.file?(proposed_token_path)
15+
raise Errno::ENOENT, "Provided PE ENC token (#{proposed_token_path}) does not exist" unless File.file?(proposed_token_path)
1616
options[:pe_enc_token] = File.read(proposed_token_path)
1717
end
1818
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
# Specify the PE RBAC token to access the PuppetDB API. Refer to
4+
# https://puppet.com/docs/pe/latest/rbac/rbac_token_auth_intro.html#generate-a-token-using-puppet-access
5+
# for details on generating and obtaining a token. Use this option to specify the text
6+
# of the token. (Use --puppetdb-token-file to read the content of the token from a file.)
7+
# @param parser [OptionParser object] The OptionParser argument
8+
# @param options [Hash] Options hash being constructed; this is modified in this method.
9+
OctocatalogDiff::Cli::Options::Option.newoption(:puppetdb_token) do
10+
has_weight 310
11+
12+
def parse(parser, options)
13+
parser.on('--puppetdb-token TOKEN', 'Token to access the PuppetDB API') do |token|
14+
options[:puppetdb_token] = token
15+
end
16+
end
17+
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
# Specify the PE RBAC token to access the PuppetDB API. Refer to
4+
# https://puppet.com/docs/pe/latest/rbac/rbac_token_auth_intro.html#generate-a-token-using-puppet-access
5+
# for details on generating and obtaining a token. Use this option to specify the text
6+
# in a file, to read the content of the token from the file.
7+
# @param parser [OptionParser object] The OptionParser argument
8+
# @param options [Hash] Options hash being constructed; this is modified in this method.
9+
OctocatalogDiff::Cli::Options::Option.newoption(:puppetdb_token_file) do
10+
has_weight 310
11+
12+
def parse(parser, options)
13+
parser.on('--puppetdb-token-file PATH', 'Path containing token for PuppetDB API, relative or absolute') do |x|
14+
proposed_token_path = x.start_with?('/') ? x : File.join(options[:basedir], x)
15+
unless File.file?(proposed_token_path)
16+
raise Errno::ENOENT, "Provided PuppetDB API token (#{proposed_token_path}) does not exist"
17+
end
18+
options[:puppetdb_token] = File.read(proposed_token_path)
19+
end
20+
end
21+
end

lib/octocatalog-diff/puppetdb.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class PuppetDB
4242
# @param :puppetdb_ssl_client_p12 [String] pkcs12-encoded client key and certificate
4343
# @param :puppetdb_ssl_client_password [String] Path to file containing password for SSL client key (any format)
4444
# @param :puppetdb_ssl_client_auth [Boolean] Override the client-auth that is guessed from parameters
45+
# @param :puppetdb_token [String] PE RBAC token to authenticate to PuppetDB API
4546
# @param :timeout [Integer] Connection timeout for PuppetDB (default=10)
4647
def initialize(options = {})
4748
@connections =
@@ -107,7 +108,10 @@ def _get(path)
107108
].join('')
108109

109110
begin
110-
more_options = { headers: { 'Accept' => 'application/json' }, timeout: @timeout }
111+
headers = { 'Accept' => 'application/json' }
112+
headers['X-Authentication'] = @options[:puppetdb_token] if @options[:puppetdb_token]
113+
more_options = { headers: headers, timeout: @timeout }
114+
111115
if connection[:username] || connection[:password]
112116
more_options[:basic_auth] = { username: connection[:username], password: connection[:password] }
113117
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
bxejuxstqwhmbrwskpfokcukvjlzmzwlouvpdcnwfypsrefnqycxezwzjiccnpnmherjhxgvrdjdhgzeaoxkjekfluyrlhxkkvllvzaunlmcqfrdnmqlovdensweblnfrgslaxcwurxeadofxlquqeercnypbuypsgnxastvuhqgxnlotrkghcvkkoyzrwmmzxocnftthosfeenxzijfnzciuukeqhmwqxnwbncxttadyrdcapokhcwykcliuhmbejdulkvxixxbcxljdvvtlbqmfqgoisadvhduoskedbykwgzfcdmfytcwkakuliytrtjpiqxaathxutizixtgbkncizjcpqiibvkjgdvblzcekqvsbyzkeaycydhxbbgmevkxzuexwdawsvanchjwzcxrrpuvwtxcsdkraluzbmozaunnfvyjoezvawxfoelmduzaqkffetecdchotxpumoxyrxeuxhxugckrfkzvapkhiniersercnemnkgspdxspfktdqrrxfpiooinqtdzvwwwyrpkzlvvxxkajgshacadawgkzpdbfarhqcflbbqtzwfshnfmpxrsuljxkdzrtxtulwoomwvykauxzxzgxqdqrbksirroxwqcveryrwfswqjmsqlddjdgvzhnsftinetaxvhfzgylxhmtammzfephrwftmudbtdkfscpxxzfudjbfzjkaozgxbxhhplddsbyhafmmvfdhqoozozwnrtjtwicxpvwdrvozrwiecxresxbuzpovfdeuxdgzqoyjzscfxrrzsvtrbtobqkscvujeqiqgiwbgjrpwslavvfldzpblhagpltlxpxwsqvgabemwfocnsugajffjtaxehaxwti

spec/octocatalog-diff/integration/puppetdb_spec.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,43 @@
139139
expect(result[:exception].class.to_s).to eq('OpenSSL::PKey::RSAError')
140140
end
141141
end
142+
143+
context 'token-based authentication' do
144+
let(:s_opts) do
145+
{
146+
ca_file: OctocatalogDiff::Spec.fixture_path('ssl/generated/ca.crt'),
147+
client_verify: false,
148+
url_map: url_map,
149+
require_header: { 'X-Authentication' => 'my-pdb-token-would-go-here' }
150+
}
151+
end
152+
153+
it 'should fail to connect to authenticated puppetdb with no token', retry: 3 do
154+
opts = { argv: ['-n', 'rspec-node.github.net'], spec_repo: 'tiny-repo' }
155+
result = OctocatalogDiff::Integration.integration_with_puppetdb(s_opts, opts)
156+
expect(result[:exception].message).to match(/Fact retrieval failed .* from PuppetDB \(403/)
157+
end
158+
159+
it 'should fail to connect to authenticated puppetdb with an invalid token', retry: 3 do
160+
args = [
161+
'-n', 'rspec-node.github.net',
162+
'--puppetdb-token', 'my-bogus-token-here',
163+
'--puppetdb-ssl-ca', OctocatalogDiff::Spec.fixture_path('ssl/generated/ca.crt')
164+
]
165+
opts = { argv: args, spec_repo: 'tiny-repo' }
166+
result = OctocatalogDiff::Integration.integration_with_puppetdb(s_opts, opts)
167+
expect(result[:exception].message).to match(/Fact retrieval failed .* from PuppetDB \(403/)
168+
end
169+
170+
it 'should connect to authenticated puppetdb with a token', retry: 3 do
171+
args = [
172+
'-n', 'rspec-node.github.net',
173+
'--puppetdb-token', 'my-pdb-token-would-go-here',
174+
'--puppetdb-ssl-ca', OctocatalogDiff::Spec.fixture_path('ssl/generated/ca.crt')
175+
]
176+
opts = { argv: args, spec_repo: 'tiny-repo' }
177+
result = OctocatalogDiff::Integration.integration_with_puppetdb(s_opts, opts)
178+
expect(result[:exitcode]).to eq(0), OctocatalogDiff::Integration.format_exception(result)
179+
end
180+
end
142181
end
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# frozen_string_literal: true
2+
3+
require_relative '../options_helper'
4+
5+
describe OctocatalogDiff::Cli::Options do
6+
context 'with a relative path' do
7+
describe '#opt_puppetdb_token_file' do
8+
let(:basedir) { OctocatalogDiff::Spec.fixture_path('configs') }
9+
10+
it 'should handle --puppetdb-token-file with valid path' do
11+
result = run_optparse(['--basedir', basedir, '--puppetdb-token-file', 'puppetdb-token.txt'])
12+
expect(result[:puppetdb_token]).to eq(OctocatalogDiff::Spec.fixture_read('configs/puppetdb-token.txt'))
13+
end
14+
15+
it 'should error if --puppetdb-token-file points to non-existing file' do
16+
expect do
17+
run_optparse(['--basedir', basedir, '--puppetdb-token-file', 'sdafjfkjlafjadsasf'])
18+
end.to raise_error(Errno::ENOENT)
19+
end
20+
21+
it 'should error if --puppetdb-token-file is not passed an argument' do
22+
expect { run_optparse(['--basedir', basedir, '--puppetdb-token-file']) }.to raise_error(OptionParser::MissingArgument)
23+
end
24+
end
25+
end
26+
27+
context 'with an absolute path' do
28+
describe '#opt_puppetdb_token_file' do
29+
it 'should handle --puppetdb-token-file with valid path' do
30+
result = run_optparse(['--puppetdb-token-file', OctocatalogDiff::Spec.fixture_path('configs/puppetdb-token.txt')])
31+
expect(result[:puppetdb_token]).to eq(OctocatalogDiff::Spec.fixture_read('configs/puppetdb-token.txt'))
32+
end
33+
34+
it 'should error if --puppetdb-token-file points to non-existing file' do
35+
expect do
36+
run_optparse(['--puppetdb-token-file', OctocatalogDiff::Spec.fixture_path('configs/alsdkfalfdkjasdf')])
37+
end.to raise_error(Errno::ENOENT)
38+
end
39+
end
40+
end
41+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# frozen_string_literal: true
2+
3+
require_relative '../options_helper'
4+
5+
describe OctocatalogDiff::Cli::Options do
6+
describe '#opt_puppetdb_token' do
7+
it 'should handle --puppetdb-token with a string arg' do
8+
result = run_optparse(['--puppetdb-token', 'foobar'])
9+
expect(result[:puppetdb_token]).to eq('foobar')
10+
end
11+
end
12+
end

0 commit comments

Comments
 (0)