autosign 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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)