autosign 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: df93f6a505859c956b527410ffd01c67f3aad762
4
- data.tar.gz: f9a1c7f7e857e6f596e6a50b4f534b772a1e62af
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZmEzYTA2MWU4NGI4MDVlYTgwZDZkMTFkNWFhM2QwNDhmMGEyZThjZg==
5
+ data.tar.gz: !binary |-
6
+ MDZmNjkzMDM3M2IxY2JjMDY3YzEwZWQ3MjMxNzY5MGY0MGFlZmRlNw==
5
7
  SHA512:
6
- metadata.gz: 86adf30615877ec93e1038b51bf59b73026d01e842c93cdcc7b834965f7de546b8cded69e23d10917a393b0633650899c0460d3b3b60fcd1bb9cf9f5e76e39ff
7
- data.tar.gz: 0d2b232814a18fef940e3605d83148a45d724c22ca3f7e490dbf14550ef4d67fbf0ef6eb3281ef35e9ad9fce8ff429ca88bb9d546071208d54fef405bd72229b
8
+ metadata.gz: !binary |-
9
+ MGJlNDkyMGQxYzViZDgwY2U5ZDcwNjAwMDgxZjVkMDExNjZhZWNiYWJkN2My
10
+ YmFhMjIzZGE2YmUwZDc0MTFhMjM1ZWY1OTVkZGQ3YzlkNTA1ZTVlZmI5NDVm
11
+ MmNjMGI2NjFkMmQ2NTlmNTBjYjJiYmIzMTkzNThjYTU1YmFhNmM=
12
+ data.tar.gz: !binary |-
13
+ YjJiNTYwNGIyNzFkMjRlYjUyZjJiMzZkZjZhNmQ5NDU3OGI2ZTkyNDE5YTU4
14
+ NmY4ZTI3MDVmMWVkYzE4MWRjMGI4ZTVkNjQzNDkzYTBhYzA5NTdlNjQzODFk
15
+ OWI1MTM5YmQ5N2ExNjg4Nzk3YWUxZWQ4MzQyNTM4ZGEwYjJhMTQ=
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ html
2
+ doc
3
+ .vagrant
4
+ .yardoc
5
+ autosign.conf
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
4
+ --backtrace
data/.travis.yml CHANGED
@@ -10,4 +10,10 @@ rvm:
10
10
  - 2.1.5
11
11
  - 2.2.2
12
12
  script:
13
- - bundle exec cucumber
13
+ - bundle exec rake ci
14
+ deploy:
15
+ provider: rubygems
16
+ api_key:
17
+ secure: "ivsiPBTcedPXuQ3hiLhLMDEaM5UUWfNi32Wy/BaDw8qwrUa6+v87IOFzipse4pa7GXzEpZf65o6/5ihxGeSZtw1sf90kwF2tMVWqjp4oFoHqg83Qscsz49X4yE1IkgVj1W/tOg2gJDneCjf250bZ3Wg/3UFSORM/f/3WVQ9vidHzb0JEaPWf4ClSeW7UVZfGz2muc6txKsQJwWgNccuyOnCfc9ElS4Vn130cIMB/t0xumVos2z8CExAFJ2dMfSqHJMc/NtamXT/tED6e2G28wLQGzViO48DuAyG3v+ubrEFpknaLkEzryfvOUPieP/hpCm9yfzbkTnulgFg1qw2QMtkrubECujZ3hg59UNyeKcixrihEWL6oSqCkJKbGyVnNxYpisb08Jdxq2o1xQD5uh1EGmMaewl3NExYdjCTzDmCVgEO7I5ItiKwUCMl9mVAGa2LEiI/SCjFxoEdglJOfCqeGunWXG1QjE2KYaD1qzkR4VCqBEP7v+wgheL0108VILjOQ6SzfMt6aaAjX0nQ2thtMvIeWUVXBlRUOzNVtQaGSyMcABPespDoyrlE5N/6HwVon+OObVKo+0mx9OYrRwxlBkAqp/vV2mXSdlD6ThUYgk7bk5ofpKQuJGTT/sr1Vyulzh2a2B1D2lDCK87mHbqvd5XnxuGCNFA90wxJ5biI="
18
+ on:
19
+ tags: true
data/Gemfile.lock CHANGED
@@ -1,66 +1,119 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- autosign (0.0.1)
5
- deep_merge
4
+ autosign (0.0.3)
5
+ deep_merge (~> 1)
6
6
  gli (~> 2)
7
7
  iniparse (~> 1)
8
- json
8
+ json (~> 1)
9
9
  jwt (~> 1)
10
- logging
11
- require_all
12
- yard
10
+ logging (~> 2)
11
+ require_all (~> 1)
12
+ yard (~> 0.8)
13
13
 
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- aruba (0.6.2)
18
- childprocess (>= 0.3.6)
19
- cucumber (>= 1.1.1)
20
- rspec-expectations (>= 2.7.0)
17
+ CFPropertyList (2.2.8)
18
+ aruba (0.8.0)
19
+ childprocess (~> 0.5.6)
20
+ contracts (~> 0.9)
21
+ cucumber (>= 1.3.19)
22
+ rspec-expectations (>= 2.99)
21
23
  builder (3.2.2)
22
24
  childprocess (0.5.6)
23
25
  ffi (~> 1.0, >= 1.0.11)
24
- cucumber (2.0.0)
26
+ contracts (0.10)
27
+ coveralls (0.8.2)
28
+ json (~> 1.8)
29
+ rest-client (>= 1.6.8, < 2)
30
+ simplecov (~> 0.10.0)
31
+ term-ansicolor (~> 1.3)
32
+ thor (~> 0.19.1)
33
+ cucumber (2.0.1)
25
34
  builder (>= 2.1.2)
26
- cucumber-core (~> 1.1.3)
35
+ cucumber-core (~> 1.2.0)
27
36
  diff-lcs (>= 1.1.3)
28
37
  gherkin (~> 2.12)
29
38
  multi_json (>= 1.7.5, < 2.0)
30
39
  multi_test (>= 0.1.2)
31
- cucumber-core (1.1.3)
40
+ cucumber-core (1.2.0)
32
41
  gherkin (~> 2.12.0)
33
42
  deep_merge (1.0.1)
34
43
  diff-lcs (1.2.5)
35
- ffi (1.9.9)
44
+ docile (1.1.5)
45
+ domain_name (0.5.24)
46
+ unf (>= 0.0.5, < 1.0.0)
47
+ facter (2.4.4)
48
+ CFPropertyList (~> 2.2.6)
49
+ ffi (1.9.10)
36
50
  gherkin (2.12.2)
37
51
  multi_json (~> 1.3)
38
52
  gli (2.13.1)
53
+ hiera (1.3.4)
54
+ json_pure
55
+ http-cookie (1.0.2)
56
+ domain_name (~> 0.5)
39
57
  iniparse (1.4.0)
40
58
  json (1.8.3)
59
+ json_pure (1.8.2)
41
60
  jwt (1.5.1)
42
61
  little-plugger (1.1.3)
43
62
  logging (2.0.0)
44
63
  little-plugger (~> 1.1)
45
64
  multi_json (~> 1.10)
46
- multi_json (1.11.1)
65
+ mime-types (2.6.1)
66
+ multi_json (1.11.2)
47
67
  multi_test (0.1.2)
68
+ netrc (0.10.3)
69
+ puppet (3.8.1)
70
+ facter (> 1.6, < 3)
71
+ hiera (~> 1.0)
72
+ json_pure
48
73
  rake (10.4.2)
49
74
  rdoc (4.2.0)
50
75
  json (~> 1.4)
51
76
  require_all (1.3.2)
77
+ rest-client (1.8.0)
78
+ http-cookie (>= 1.0.2, < 2.0)
79
+ mime-types (>= 1.16, < 3.0)
80
+ netrc (~> 0.7)
81
+ rspec (3.3.0)
82
+ rspec-core (~> 3.3.0)
83
+ rspec-expectations (~> 3.3.0)
84
+ rspec-mocks (~> 3.3.0)
85
+ rspec-core (3.3.1)
86
+ rspec-support (~> 3.3.0)
52
87
  rspec-expectations (3.3.0)
53
88
  diff-lcs (>= 1.2.0, < 2.0)
54
89
  rspec-support (~> 3.3.0)
90
+ rspec-mocks (3.3.1)
91
+ diff-lcs (>= 1.2.0, < 2.0)
92
+ rspec-support (~> 3.3.0)
55
93
  rspec-support (3.3.0)
94
+ simplecov (0.10.0)
95
+ docile (~> 1.1.0)
96
+ json (~> 1.8)
97
+ simplecov-html (~> 0.10.0)
98
+ simplecov-html (0.10.0)
99
+ term-ansicolor (1.3.2)
100
+ tins (~> 1.0)
101
+ thor (0.19.1)
102
+ tins (1.5.4)
103
+ unf (0.1.4)
104
+ unf_ext
105
+ unf_ext (0.0.7.1)
56
106
  yard (0.8.7.6)
57
107
 
58
108
  PLATFORMS
59
109
  ruby
60
110
 
61
111
  DEPENDENCIES
62
- aruba
112
+ aruba (~> 0.6)
63
113
  autosign!
64
- cucumber
65
- rake
66
- rdoc
114
+ coveralls
115
+ cucumber (~> 2)
116
+ puppet (~> 3)
117
+ rake (~> 10)
118
+ rdoc (~> 4)
119
+ rspec (~> 3)
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # autosign
2
- [![Build Status](https://travis-ci.org/danieldreier/autosign.svg?branch=master)](https://travis-ci.org/danieldreier/autosign) [![Code Climate](https://codeclimate.com/github/danieldreier/autosign/badges/gpa.svg)](https://codeclimate.com/github/danieldreier/autosign) [![Dependency Status](https://gemnasium.com/danieldreier/autosign.svg)](https://gemnasium.com/danieldreier/autosign) [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/danieldreier/autosign) [![Inline docs](http://inch-ci.org/github/danieldreier/autosign.png)](http://inch-ci.org/github/danieldreier/autosign)
2
+ [![Build Status](https://travis-ci.org/danieldreier/autosign.svg?branch=master)](https://travis-ci.org/danieldreier/autosign) [![Code Climate](https://codeclimate.com/github/danieldreier/autosign/badges/gpa.svg)](https://codeclimate.com/github/danieldreier/autosign) [![Dependency Status](https://gemnasium.com/danieldreier/autosign.svg)](https://gemnasium.com/danieldreier/autosign) [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/danieldreier/autosign) [![Inline docs](http://inch-ci.org/github/danieldreier/autosign.png)](http://inch-ci.org/github/danieldreier/autosign) [![Coverage Status](https://coveralls.io/repos/danieldreier/autosign/badge.svg?branch=master&service=github)](https://coveralls.io/github/danieldreier/autosign?branch=master) [![Gem Version](https://badge.fury.io/rb/autosign.svg)](http://badge.fury.io/rb/autosign)
3
3
 
4
4
  Tooling to make puppet autosigning easy, secure, and extensible
5
5
 
data/Rakefile CHANGED
@@ -1,9 +1,16 @@
1
- require 'rake/clean'
2
1
  require 'rubygems'
2
+ begin
3
+ require 'rspec/core/rake_task'
4
+ require 'cucumber'
5
+ require 'cucumber/rake/task'
6
+ require 'rdoc/task'
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_opts = '--format documentation'
9
+ end
10
+ rescue LoadError
11
+ end
12
+ require 'rake/clean'
3
13
  require 'rubygems/package_task'
4
- require 'rdoc/task'
5
- require 'cucumber'
6
- require 'cucumber/rake/task'
7
14
  Rake::RDocTask.new do |rd|
8
15
  rd.main = "README.rdoc"
9
16
  rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
@@ -17,11 +24,9 @@ end
17
24
  CUKE_RESULTS = 'results.html'
18
25
  CLEAN << CUKE_RESULTS
19
26
  desc 'Run features'
27
+
20
28
  Cucumber::Rake::Task.new(:features) do |t|
21
- opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
22
- opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
23
- t.cucumber_opts = opts
24
- t.fork = false
29
+ t.cucumber_opts = "features --format pretty"
25
30
  end
26
31
 
27
32
  desc 'Run features tagged as work-in-progress (@wip)'
@@ -32,7 +37,6 @@ Cucumber::Rake::Task.new('features:wip') do |t|
32
37
  t.fork = false
33
38
  end
34
39
 
35
- task :cucumber => :features
36
40
  task 'cucumber:wip' => 'features:wip'
37
41
  task :wip => 'features:wip'
38
42
  require 'rake/testtask'
@@ -41,4 +45,6 @@ Rake::TestTask.new do |t|
41
45
  t.test_files = FileList['test/*_test.rb']
42
46
  end
43
47
 
48
+ task :ci => [:spec, :features]
49
+
44
50
  task :default => [:test,:features]
data/autosign.gemspec CHANGED
@@ -11,22 +11,23 @@ spec = Gem::Specification.new do |s|
11
11
  s.files = `git ls-files`.split("
12
12
  ")
13
13
  s.require_paths << 'lib'
14
- s.has_rdoc = true
15
- s.extra_rdoc_files = ['README.rdoc','autosign.rdoc']
14
+ s.has_rdoc = false
16
15
  s.rdoc_options << '--title' << 'autosign' << '--main' << 'README.rdoc' << '-ri'
17
16
  s.bindir = 'bin'
18
17
  s.executables << 'autosign'
19
- s.add_development_dependency('rake')
20
- s.add_development_dependency('rdoc')
21
- s.add_development_dependency('aruba')
22
- s.add_development_dependency('cucumber')
23
- s.add_development_dependency('puppet')
18
+ s.add_development_dependency('rake', '~> 10')
19
+ s.add_development_dependency('rdoc', '~> 4')
20
+ s.add_development_dependency('aruba', '~> 0.6')
21
+ s.add_development_dependency('cucumber', '~> 2')
22
+ s.add_development_dependency('puppet', '~> 3')
23
+ s.add_development_dependency('rspec', '~> 3')
24
+ s.add_development_dependency('coveralls')
24
25
  s.add_runtime_dependency('gli','~> 2')
25
26
  s.add_runtime_dependency('jwt','~> 1')
26
27
  s.add_runtime_dependency('iniparse','~> 1')
27
- s.add_runtime_dependency('logging')
28
- s.add_runtime_dependency('json')
29
- s.add_runtime_dependency('deep_merge')
30
- s.add_runtime_dependency('require_all')
31
- s.add_runtime_dependency('yard')
28
+ s.add_runtime_dependency('logging', '~> 2')
29
+ s.add_runtime_dependency('json', '~> 1')
30
+ s.add_runtime_dependency('deep_merge', '~> 1')
31
+ s.add_runtime_dependency('require_all', '~> 1')
32
+ s.add_runtime_dependency('yard', '~> 0.8')
32
33
  end
data/lib/autosign.rb CHANGED
@@ -9,3 +9,18 @@ require 'autosign/validator.rb'
9
9
 
10
10
  # Add requires for other files you add to your project here, so
11
11
  # you just need to require this one file in your bin file
12
+
13
+ # Autosign facilitates SSL certificate autosigning in Puppet.
14
+ # The overall flow of data is:
15
+ #
16
+ # When executed by puppet to validate certificate signing requests:
17
+ #
18
+ # 1. Puppet runs bin/autosign-validator with the requested certname as the parameter and the X509 CSR in STDIN
19
+ # 2. bin/autosign-validator uses Autosign::Decoder to extract key data from the CSR, then
20
+ # 3. Uses Autosign::Validator.any_validator to send the CSR to each available validator.
21
+ # 4. Autosign::Validator.any_validator calls each of its' child classes, and returns true if any validator succeeds.
22
+ # 5. bin/autosign-validator exits with exit code 0 if validation succeeded, or exit code 1 if validation failed.
23
+ #
24
+ module Autosign
25
+ # this section is only here as a stub to allow documentation of the overall module/gem in yardoc format.
26
+ end
@@ -20,6 +20,11 @@ module Autosign
20
20
  end
21
21
  end
22
22
 
23
+ # Class to manage configuration settings.
24
+ # The purpose of this class is to interact with the configuration file,
25
+ # merge defaults and user-provided settings, and present a configuration hash
26
+ # so that validators and other components do not have to re-implement config
27
+ # file handling.
23
28
  class Config
24
29
  # Create a config instance to interact with configuration settings
25
30
  # To specify a configuration file, settings_param should include something like:
@@ -1,4 +1,8 @@
1
1
  module Autosign
2
+ # Class to abstract X509 certificate signing request decoding.
3
+ # This class is only expected to be used for class methods.
4
+ # The purpose is to extract common fields from CSRs so that individual
5
+ # validators don't have to re-implement that logic.
2
6
  class Decoder
3
7
  # Extract common name and challenge_password OID from X509 SSL Certificate signing requests
4
8
  #
@@ -13,6 +17,9 @@ module Autosign
13
17
  rescue OpenSSL::X509::RequestError
14
18
  @log.error "Rescued OpenSSL::X509::RequestError; unable to decode CSR"
15
19
  return nil
20
+ rescue
21
+ @log.error "Rescued an OpenSSL error. Unable to decode CSR."
22
+ return nil
16
23
  end
17
24
 
18
25
  # extract challenge password
@@ -37,7 +37,7 @@ module Autosign
37
37
  # This is the primary way this class is expected to be used
38
38
  def add(uuid, validto, data = {})
39
39
  @log.debug "attempting to add UUID: '#{uuid.to_s}' which is valid to '#{Time.at(validto.to_i)}' with data #{data.to_s}"
40
- puts validate_uuid(uuid).to_s
40
+ return false unless validate_uuid(uuid)
41
41
 
42
42
  store = setup
43
43
  # wrap the change in a transaction because multiple autosign instances
@@ -71,6 +71,12 @@ module Autosign
71
71
  errors << "Invalid Token"
72
72
  end
73
73
  @log.warn "validation failed with: #{errors.join(', ')}" unless errors.count == 0
74
+
75
+ if data.nil?
76
+ @log.error "token is nil; this probably means the token failed to validate"
77
+ return false
78
+ end
79
+
74
80
  certname_is_regex = (data["certname"] =~ /\/[^\/].*\//) ? true : false
75
81
 
76
82
  if certname_is_regex
@@ -117,12 +123,17 @@ module Autosign
117
123
  end
118
124
 
119
125
  # Sign the token with HMAC using a SHA-512 hash
120
- # @return [String] signed, serialized JSON web token
121
126
  def sign()
122
127
  exp_payload = { :data => to_json, :exp => validto.to_s}
123
128
  JWT.encode exp_payload, secret, 'HS512'
124
129
  end
125
130
 
131
+ # Create an Autosign::Token object from a serialized token after validating
132
+ # the signature and expiration time validity.
133
+ #
134
+ # @param token [String] JSON Web Token coming from the certificate signing request
135
+ # @param secret [String] shared HMAC secret used to sign or validate tokens
136
+ # @return [Autosign::Token] instance of Autosign::Token with the settings from the serialized token
126
137
  def self.from_token(token, hmac_secret)
127
138
  begin
128
139
  decoded = JWT.decode(token, hmac_secret)[0]
@@ -1,16 +1,35 @@
1
1
  module Autosign
2
2
  module Validators
3
+ # Validate certificate signing requests using JSON Web Tokens (JWT).
4
+ # This is the expected primary validator when using the autosign gem.
5
+ # Validation requires that the shared secret used to generate the JWT is
6
+ # the same as on the validating system. The validator also checks that the
7
+ # token has not expired, and that one-time (non-reusable) tokens have not
8
+ # been previously used.
3
9
  class JWT < Autosign::Validator
10
+
11
+ # set the user-friendly name of the JWT validator.
12
+ # This name is used to specify that configuration should come from the
13
+ # [jwt_token] section of the autosign.conf file.
14
+ # @return [String] name of the validator
4
15
  def name
5
16
  "jwt_token"
6
17
  end
7
18
 
8
19
  private
9
20
 
21
+ # Validate a JWT token.
22
+ # Validation relies on the Autosign::Token class, then additionally
23
+ # confirms that one-time tokens have not already been used by adding them
24
+ # to the journal.
25
+ # @param token [String] Base64 encoded JSON web token
26
+ # @param certname [String] the certname being requested in the certificate signing request
27
+ # @param raw_csr [String] Raw CSR; not used in this validator.
28
+ # @return [True, False] returns true to indicate successful validation, and false to indicate failure to validate
10
29
  def perform_validation(token, certname, raw_csr)
11
- puts "attempting to validate JWT token"
30
+ @log.info "attempting to validate JWT token"
12
31
  return false unless Autosign::Token.validate(certname, token, settings['secret'])
13
- puts "validated JWT token"
32
+ @log.info "validated JWT token"
14
33
  @log.debug "validated JWT token, checking reusability"
15
34
 
16
35
  return true if is_reusable?(token)
@@ -22,6 +41,11 @@ module Autosign
22
41
  Autosign::Token.from_token(token, settings['secret']).reusable
23
42
  end
24
43
 
44
+ # Attempt to add a token to the one-time token journal.
45
+ # The journal lists previously used non-reusable tokens, indexed by UUID.
46
+ #
47
+ # @param token [String] Base64 encoded JSON web token
48
+ # @return [True, False] returns true if the token was successfully added to the journal, or false if the token was previously used and is already in the journal
25
49
  def add_to_journal(token)
26
50
  validated_token = Autosign::Token.from_token(token, settings['secret'])
27
51
  @log.debug 'add_to_journal settings: ' + settings.to_s
@@ -44,8 +68,13 @@ module Autosign
44
68
  }
45
69
  end
46
70
 
71
+ # Override some configuration settings using environment variables to
72
+ # simplify testing. This is a hack to make testing easier.
73
+ # Cucumber sets environment variables because it's easier than templating
74
+ # out config files.
75
+ #
76
+ # This should probably be done differently at some point.
47
77
  def get_override_settings
48
- # this is a hack to make testing easier
49
78
  if (ENV["AUTOSIGN_TESTMODE"] == "true" and
50
79
  !ENV["AUTOSIGN_TEST_SECRET"].nil? and
51
80
  !ENV["AUTOSIGN_TEST_JOURNALFILE"].nil? )
@@ -58,6 +87,11 @@ module Autosign
58
87
  end
59
88
  end
60
89
 
90
+ # Validate that the settings hash contains a secret.
91
+ # The validator cannot function without a secret, so there's no point
92
+ # in continuing to run if it was configured without a secret.
93
+ # @param settings [Hash] settings hash
94
+ # @return [True, False] return true if settings are valid, false if config is unusable
61
95
  def validate_settings(settings)
62
96
  @log.debug "validating settings: " + settings.to_s
63
97
  if settings['secret'].is_a?(String)