autosign 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YWFiZDhhNDExMzllMTRiNTMxMjYzZjNjNjljYzQ1MjdjNjc3NGM2MQ==
4
+ YTQ1YWExMWZhOTA2OGYzN2NmODBjOGRhNjAxY2NkMTdhZDQ4ZTliNQ==
5
5
  data.tar.gz: !binary |-
6
- Mzk0ZmVhNWNlNDg1Y2FjYmE0N2RjY2EzOTIyOTUyOWYzODk3NTgwOQ==
6
+ ZDNlZmY2YjcxMDY0ODZjMDM0ZDFkNzNhNGI5Zjk0NDMxZDgxMTc3Yw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MmZmZTA5YmE2ZjM4NjY3ZTdlZTNkMjhiMTllNDczNWU4MTYzNWZmMDc4MjI0
10
- ODhlZjE1YjUyZWYxNTU4ZDA1YzQ4Y2EyNGY1OGRiNjVjNzlhOGExN2M1ODZj
11
- Mzk5YzhkZWY2NGNhMTc0M2QwNGU4ZTMwZWIyOGUwMjQyZWVmNWE=
9
+ NTlkZDVhZDY3OWE5Mzk4YmQyMjVjYzg0OTI1Y2U3ZDU3ZjJkYjYzOTIzZDQz
10
+ Mzg2NjI0MGVkNDA2ZTcwMTk3MjNhODIyZjU0NzMxNGU0MDIyY2VmMDkyOWI3
11
+ MDI4OTE2OTg5NWMwYTM2NjdkMTYyN2JlZGRmZDY1YjY4NjY3ZDk=
12
12
  data.tar.gz: !binary |-
13
- MTJhNzI0NzM5NDYwMjVmOWU5MGI0NzIwODI5NDgwMGMwODlkNTY1NzRkZTcz
14
- NWE3ODdiNjY5NzdlYzU4MzVmNDg1YzgyODc3MzA4NTBkMjVmMmYwZGRlOGRh
15
- ZDQzYjYxZTFjMjY1NzViMmM5YmQ4YTBhYzViZTExMzA2YWY3YWM=
13
+ YWI5ZTQzNzljNGU3NWUzMjJmMmU2ZTM1OTlkNWEwZjhjNzBjYTI5MWExZmIx
14
+ NWUxNjg0N2ZjMTE2ZTIxNTM5ZDBlNGQxOTkxYjZlMWVhYjQ2YjcyOGFlNjBj
15
+ MThhYmY2MmVjYWE0ZmNkMDJiMDM2ZTlkNzQxNTYyNzcxYmE3M2U=
data/.gitignore CHANGED
@@ -3,3 +3,5 @@ doc
3
3
  .vagrant
4
4
  .yardoc
5
5
  autosign.conf
6
+ results.html
7
+ coverage/
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- autosign (0.0.7)
4
+ autosign (0.0.8)
5
5
  deep_merge (~> 1)
6
6
  gli (~> 2)
7
7
  iniparse (~> 1)
@@ -9,6 +9,7 @@ PATH
9
9
  jwt (~> 1)
10
10
  logging (~> 2)
11
11
  require_all (~> 1)
12
+ safe_yaml (~> 1)
12
13
  yard (~> 0.8)
13
14
 
14
15
  GEM
@@ -91,6 +92,7 @@ GEM
91
92
  diff-lcs (>= 1.2.0, < 2.0)
92
93
  rspec-support (~> 3.3.0)
93
94
  rspec-support (3.3.0)
95
+ safe_yaml (1.0.4)
94
96
  simplecov (0.10.0)
95
97
  docile (~> 1.1.0)
96
98
  json (~> 1.8)
data/README.md CHANGED
@@ -6,3 +6,93 @@ Tooling to make puppet autosigning easy, secure, and extensible
6
6
  ### Introduction
7
7
 
8
8
  This tool provides a CLI for performing puppet policy-based autosigning using JWT tokens. Read more at https://danieldreier.github.io/autosign.
9
+
10
+ ### Quick Start: How to Generate Tokens
11
+
12
+ ##### 1. Install Gem on Puppet Master
13
+ ```shell
14
+ gem install autosign
15
+ ```
16
+
17
+ ##### 2. Generate default configuration
18
+
19
+ ```shell
20
+ autosign config setup
21
+ ```
22
+
23
+ ##### 3. Generate your first autosign token on the puppet master
24
+ ```shell
25
+ autosign generate foo.example.com
26
+ ```
27
+
28
+ The output will look something like
29
+ ```
30
+ Autosign token for: foo.example.com, valid until: 2015-07-16 16:25:50 -0700
31
+ To use the token, put the following in ${puppet_confdir}/csr_attributes.yaml prior to running puppet agent for the first time:
32
+
33
+ custom_attributes:
34
+ challengePassword: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJkYXRhIjoie1wiY2VydG5hbWVcIjpcImZvby5leGFtcGxlLmNvbVwiLFwicmVxdWVzdGVyXCI6XCJEYW5pZWxzLU1hY0Jvb2stUHJvLTIubG9jYWxcIixcInJldXNhYmxlXCI6ZmFsc2UsXCJ2YWxpZGZvclwiOjcyMDAsXCJ1dWlkXCI6XCJkM2YyNzI0OC1jZDFmLTRhZmItYjI0MC02ZjBjMDU4NWJiZDNcIn0iLCJleHAiOiIxNDM3MDg5MTUwIn0.lC-EzWaV2dL81aLL7P-9mGwNbiOQDJWcoYjuSHVOqmaLtc7Wis5OZvHFOLln2Fn9qv98oSTnZsIkjmFpbI5dvA"
35
+ ```
36
+
37
+ The resulting output can be copied to `/etc/puppet/csr_attributes.yaml` on an agent machine prior to running puppet for the first time to add the token to the CSR as the `challengePassword` OID. (just copy-paste from one terminal to another to copy the text)
38
+
39
+ ### Quick Start: Puppet Master Configuration
40
+
41
+ Run through the previous quick start steps to get the gem installed, then configure puppet to use the `autosign-validator` executable as the policy autosign command:
42
+
43
+ ##### 1. Prerequisities
44
+ Note that these settings will be slightly different if you're running Puppet Enterprise, because you'll need to use the `pe-puppet` user instead of `puppet`.
45
+
46
+ ```shell
47
+ mkdir /var/autosign
48
+ chown puppet:puppet /var/autosign
49
+ chmod 750 /var/autosign
50
+ touch /var/log/autosign.log
51
+ chown puppet:puppet /var/log/autosign.log
52
+ ```
53
+
54
+
55
+ ##### 2. Configure master
56
+ ```shell
57
+ puppet config set autosign $(which autosign-validator) --section master
58
+ ```
59
+
60
+ Your master is now configured to autosign using the autosign gem.
61
+
62
+
63
+ ##### 3. Using Legacy Autosign Scripts
64
+
65
+ If you already had an autosign script you want to continue using, add a setting to your `autosign.conf` like:
66
+
67
+ ```yaml
68
+ multiplexer:
69
+ external_policy_executable: "/path/to/autosign/executable"
70
+ ```
71
+
72
+ The master will validate the certificate if either the token validator or the external validator succeeds.
73
+
74
+ If the autosign script was just validating simple strings, you can use the `password_list` validator instead. For example, to configure the master to sign any CSR that includes the challenge passwords of "hunter2" or "CPE1704TKS" you would add:
75
+
76
+ ```ini
77
+ password_list:
78
+ password: "hunter2"
79
+ password: "CPE1704TKS"
80
+ ```
81
+
82
+ Note that this is a relatively insecure way to do certificate autosigning. Using one-time tokens via the `autosign generate` command is more secure. This functionality is provided to grandfather in existing use cases to ease the transition.
83
+
84
+
85
+ ### Troubleshooting
86
+ If you're having problems, try the following:
87
+
88
+ - Set `loglevel: "debug"` in `/etc/autosign.conf`
89
+ - Check the `journalfile`, in `/var/autosign/autosign.journal` by default, to see if the one-time token's UUID has already been recorded. It's just YAML, so you can either delete it or remove the offending entry if you actually want to re-use a token.
90
+ - you can manually trigger the autosigning script with something like `cat the_csr.csr | autosign-validator certname.example.com`
91
+ - If you run the puppet master foregrounded, you'll see quite a bit of autosign script output if autosign loglevel is set to debug.
92
+
93
+
94
+ ### Further Reading
95
+
96
+ - [https://danieldreier.github.io/autosign](https://danieldreier.github.io/autosign) has background on why this exists.
97
+ - Automatically generated code documentation in YARDOC format is [available on rubydoc.info](http://rubydoc.info/github/danieldreier/autosign).
98
+ - Look at the [puppet-autosign](https://travis-ci.org/danieldreier/puppet-autosign) puppet module to automate setup of this tool, and for a puppet function to generate tokens inside of Puppet, for example when provisioning systems in AWS.
data/autosign.gemspec CHANGED
@@ -31,4 +31,5 @@ spec = Gem::Specification.new do |s|
31
31
  s.add_runtime_dependency('deep_merge', '~> 1')
32
32
  s.add_runtime_dependency('require_all', '~> 1')
33
33
  s.add_runtime_dependency('yard', '~> 0.8')
34
+ s.add_runtime_dependency('safe_yaml', '~> 1')
34
35
  end
@@ -8,9 +8,10 @@ Feature: Generate autosign key
8
8
  And a hostname of "foo.example.com"
9
9
  And a file named "autosign.conf" with:
10
10
  """
11
- [jwt_token]
12
- validity = 7200
13
- secret = secret
11
+ ---
12
+ jwt_token:
13
+ validity: '7200'
14
+ secret: 'secret'
14
15
  """
15
16
  When I run `chmod 600 autosign.conf`
16
17
  And I run `autosign --config autosign.conf generate foo.example.com`
@@ -23,9 +24,10 @@ Feature: Generate autosign key
23
24
  And a hostname of "foo.example.com"
24
25
  And a file named "autosign.conf" with:
25
26
  """
26
- [jwt_token]
27
- secret = secret
28
- validity = 7200
27
+ ---
28
+ jwt_token:
29
+ validity: '7200'
30
+ secret: 'secret'
29
31
  """
30
32
  When I run `chmod 600 autosign.conf`
31
33
  When I run `autosign --config autosign.conf generate foo.example.com --reusable`
@@ -38,8 +40,9 @@ Feature: Generate autosign key
38
40
  And a hostname of "foo.example.com"
39
41
  And a file named "autosign.conf" with:
40
42
  """
41
- [jwt_token]
42
- secret = secret
43
+ ---
44
+ jwt_token:
45
+ secret: 'secret'
43
46
  """
44
47
  When I run `chmod 600 autosign.conf`
45
48
  When I run `autosign --config autosign.conf validate --certname "foo.example.com" "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJkYXRhIjoie1wiY2VydG5hbWVcIjpcImZvby5leGFtcGxlLmNvbVwiLFwicmVxdWVzdGVyXCI6XCJEYW5pZWxzLU1hY0Jvb2stUHJvLTIubG9jYWxcIixcInJldXNhYmxlXCI6ZmFsc2UsXCJ2YWxpZGZvclwiOjI5OTk5OTk5OSxcInV1aWRcIjpcIjlkYTA0Yzc4LWQ5NjUtNDk2OC04MWNjLWVhM2RjZDllZjVjMFwifSIsImV4cCI6IjE3MzY0NjYxMzAifQ.PJwY8rIunVyWi_lw0ypFclME0jx3Vd9xJIQSyhN3VUmul3V8u4Tp9XwDgoAu9DVV0-WEG2Tfxs6F8R6Fn71Ndg"`
@@ -51,8 +54,9 @@ Feature: Generate autosign key
51
54
  And a hostname of "foo.example.com"
52
55
  And a file named "autosign.conf" with:
53
56
  """
54
- [jwt_token]
55
- secret = secret
57
+ ---
58
+ jwt_token:
59
+ secret: 'secret'
56
60
  """
57
61
  When I run `chmod 600 autosign.conf`
58
62
  When I run `autosign --config autosign.conf validate --certname "foo.example.com" "invalid_token"`
@@ -63,8 +67,9 @@ Feature: Generate autosign key
63
67
  And a hostname of "foo.example.com"
64
68
  And a file named "autosign.conf" with:
65
69
  """
66
- [jwt_token]
67
- secret = secret
70
+ ---
71
+ jwt_token:
72
+ secret: 'secret'
68
73
  """
69
74
  When I run `chmod 600 autosign.conf`
70
75
  When I run `autosign --config autosign.conf validate --certname "foo.example.com" "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJkYXRhIjoie1wiY2VydG5hbWVcIjpcImZvby5leGFtcGxlLmNvbVwiLFwicmVxdWVzdGVyXCI6XCJEYW5pZWxzLU1hY0Jvb2stUHJvLTIubG9jYWxcIixcInJldXNhYmxlXCI6ZmFsc2UsXCJ2YWxpZGZvclwiOjEsXCJ1dWlkXCI6XCJlNjI1Y2I1Ny02NzY5LTQwMzQtODNiZS0zNzkxNmQ5YmMxMDRcIn0iLCJleHAiOiIxNDM2NDY2MzAyIn0.UXEDEbRqEWx5SdSpQjfowU56JubY5Yz2QN6cckby2es-g2P_n2lyAS6AwFeliBXyCDyVUelIT3g1QP4TdB9EEA"`
@@ -1,7 +1,8 @@
1
- require 'iniparse'
2
1
  require 'rbconfig'
3
2
  require 'securerandom'
4
3
  require 'deep_merge'
4
+ require 'yaml'
5
+ require 'safe_yaml'
5
6
 
6
7
  module Autosign
7
8
  # Exceptions namespace for Autosign class
@@ -38,7 +39,7 @@ module Autosign
38
39
  # set up logging
39
40
  @log = Logging.logger['Autosign::Config']
40
41
  @log.debug "initializing Autosign::Config"
41
-
42
+ SafeYAML::OPTIONS[:default_mode] = :safe
42
43
  # validate parameter
43
44
  raise 'settings is not a hash' unless settings_param.is_a?(Hash)
44
45
 
@@ -101,7 +102,8 @@ module Autosign
101
102
  if File.file?(file)
102
103
  @log.debug "Reading config file from: " + file
103
104
  config_file = File.read(file)
104
- parsed_config_file = IniParse.parse(config_file).to_hash
105
+ parsed_config_file = YAML.safe_load(config_file)
106
+ #parsed_config_file = IniParse.parse(config_file).to_hash
105
107
  @log.debug "configuration read from config file: " + parsed_config_file.to_s
106
108
  return parsed_config_file if parsed_config_file.is_a?(Hash)
107
109
  else
@@ -161,27 +163,39 @@ module Autosign
161
163
  end
162
164
  )
163
165
 
164
- config = IniParse.gen do |doc|
165
- doc.section("general") do |general|
166
- general.option("loglevel", "warn")
167
- general.option("logfile", os_defaults['logpath'])
168
- end
169
- doc.section("jwt_token") do |jwt_token|
170
- jwt_token.option("secret", SecureRandom.base64(15))
171
- jwt_token.option("validity", 7200)
172
- jwt_token.option("journalfile", os_defaults['journalfile'])
173
- end
174
- doc.section("multiplexer") do |jwt_token|
175
- jwt_token.option(";external_policy_executable", '/usr/local/bin/some_autosign_executable')
176
- jwt_token.option(";external_policy_executable", '/usr/local/bin/another_autosign_executable')
177
- end
178
- doc.section("password_list") do |jwt_token|
179
- jwt_token.option(";password", 'static_autosign_password_here')
180
- jwt_token.option(";password", 'another_static_autosign_password')
181
- end
182
- end.to_ini
166
+ config = {
167
+ 'general' => {
168
+ 'loglevel' => 'warn',
169
+ 'logfile' => os_defaults['logpath']
170
+ },
171
+ 'jwt_token' => {
172
+ 'secret' => SecureRandom.base64(20),
173
+ 'validity' => '7200',
174
+ 'journalfile' => os_defaults['journalfile']
175
+ }
176
+ }
177
+
178
+ # config = IniParse.gen do |doc|
179
+ # doc.section("general") do |general|
180
+ # general.option("loglevel", "warn")
181
+ # general.option("logfile", os_defaults['logpath'])
182
+ # end
183
+ # doc.section("jwt_token") do |jwt_token|
184
+ # jwt_token.option("secret", SecureRandom.base64(15))
185
+ # jwt_token.option("validity", 7200)
186
+ # jwt_token.option("journalfile", os_defaults['journalfile'])
187
+ # end
188
+ # doc.section("multiplexer") do |jwt_token|
189
+ # jwt_token.option(";external_policy_executable", '/usr/local/bin/some_autosign_executable')
190
+ # jwt_token.option(";external_policy_executable", '/usr/local/bin/another_autosign_executable')
191
+ # end
192
+ # doc.section("password_list") do |jwt_token|
193
+ # jwt_token.option(";password", 'static_autosign_password_here')
194
+ # jwt_token.option(";password", 'another_static_autosign_password')
195
+ # end
196
+ # end.to_ini
183
197
  raise Autosign::Exceptions::Error, "file #{os_defaults['confpath']} already exists, aborting" if File.file?(os_defaults['confpath'])
184
- return os_defaults['confpath'] if File.write(os_defaults['confpath'], config)
198
+ return os_defaults['confpath'] if File.write(os_defaults['confpath'], config.to_yaml)
185
199
  end
186
200
  end
187
201
  end
@@ -23,7 +23,7 @@ module Autosign
23
23
  end
24
24
 
25
25
  # extract challenge password
26
- challenge_password = csr.attributes.select { |a| a.oid == 'challengePassword' }.first.value.value.first.value
26
+ challenge_password = csr.attributes.select { |a| a.oid == 'challengePassword' }.first.value.value.first.value.to_s
27
27
 
28
28
  # extract common name
29
29
  common_name = /^\/CN=(\S*)$/.match(csr.subject.to_s)[1]
@@ -106,7 +106,7 @@ module Autosign
106
106
 
107
107
  # check if the token is reusable or a one-time use token
108
108
  # @return [True, False] return true if the token can be used multiple times, false if the token can only be used once
109
- def reusable
109
+ def reusable?
110
110
  !!@reusable
111
111
  end
112
112
 
@@ -116,7 +116,7 @@ module Autosign
116
116
  {
117
117
  "certname" => certname,
118
118
  "requester" => requester,
119
- "reusable" => reusable,
119
+ "reusable" => reusable?,
120
120
  "validfor" => validfor,
121
121
  "uuid" => uuid
122
122
  }
@@ -132,6 +132,10 @@ module Autosign
132
132
  true
133
133
  end
134
134
 
135
+ # Find other classes that inherit from this class.
136
+ # Used to discover autosign validators. There is probably no reason to use
137
+ # this directly.
138
+ # @return [Array] of classes inheriting from Autosign::Validator
135
139
  def self.descendants
136
140
  ObjectSpace.each_object(Class).select { |klass| klass < self }
137
141
  end
@@ -38,7 +38,7 @@ module Autosign
38
38
  end
39
39
 
40
40
  def is_reusable?(token)
41
- Autosign::Token.from_token(token, settings['secret']).reusable
41
+ Autosign::Token.from_token(token, settings['secret']).reusable?
42
42
  end
43
43
 
44
44
  # Attempt to add a token to the one-time token journal.
@@ -1,3 +1,3 @@
1
1
  module Autosign
2
- VERSION = '0.0.7'
2
+ VERSION = '0.0.8'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: autosign
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Your Name Here
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-16 00:00:00.000000000 Z
11
+ date: 2015-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -220,6 +220,20 @@ dependencies:
220
220
  - - ~>
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0.8'
223
+ - !ruby/object:Gem::Dependency
224
+ name: safe_yaml
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ~>
228
+ - !ruby/object:Gem::Version
229
+ version: '1'
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ~>
235
+ - !ruby/object:Gem::Version
236
+ version: '1'
223
237
  description:
224
238
  email: your@email.address.com
225
239
  executables: