leap_cli 1.2.5

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.
Files changed (72) hide show
  1. data/bin/leap +81 -0
  2. data/lib/core_ext/boolean.rb +14 -0
  3. data/lib/core_ext/hash.rb +35 -0
  4. data/lib/core_ext/json.rb +42 -0
  5. data/lib/core_ext/nil.rb +5 -0
  6. data/lib/core_ext/string.rb +14 -0
  7. data/lib/leap/platform.rb +52 -0
  8. data/lib/leap_cli/commands/ca.rb +430 -0
  9. data/lib/leap_cli/commands/clean.rb +16 -0
  10. data/lib/leap_cli/commands/compile.rb +134 -0
  11. data/lib/leap_cli/commands/deploy.rb +172 -0
  12. data/lib/leap_cli/commands/facts.rb +93 -0
  13. data/lib/leap_cli/commands/inspect.rb +140 -0
  14. data/lib/leap_cli/commands/list.rb +122 -0
  15. data/lib/leap_cli/commands/new.rb +126 -0
  16. data/lib/leap_cli/commands/node.rb +272 -0
  17. data/lib/leap_cli/commands/pre.rb +99 -0
  18. data/lib/leap_cli/commands/shell.rb +67 -0
  19. data/lib/leap_cli/commands/test.rb +55 -0
  20. data/lib/leap_cli/commands/user.rb +140 -0
  21. data/lib/leap_cli/commands/util.rb +50 -0
  22. data/lib/leap_cli/commands/vagrant.rb +201 -0
  23. data/lib/leap_cli/config/macros.rb +369 -0
  24. data/lib/leap_cli/config/manager.rb +369 -0
  25. data/lib/leap_cli/config/node.rb +37 -0
  26. data/lib/leap_cli/config/object.rb +336 -0
  27. data/lib/leap_cli/config/object_list.rb +174 -0
  28. data/lib/leap_cli/config/secrets.rb +43 -0
  29. data/lib/leap_cli/config/tag.rb +18 -0
  30. data/lib/leap_cli/constants.rb +7 -0
  31. data/lib/leap_cli/leapfile.rb +97 -0
  32. data/lib/leap_cli/load_paths.rb +15 -0
  33. data/lib/leap_cli/log.rb +166 -0
  34. data/lib/leap_cli/logger.rb +216 -0
  35. data/lib/leap_cli/markdown_document_listener.rb +134 -0
  36. data/lib/leap_cli/path.rb +84 -0
  37. data/lib/leap_cli/remote/leap_plugin.rb +204 -0
  38. data/lib/leap_cli/remote/puppet_plugin.rb +66 -0
  39. data/lib/leap_cli/remote/rsync_plugin.rb +35 -0
  40. data/lib/leap_cli/remote/tasks.rb +36 -0
  41. data/lib/leap_cli/requirements.rb +19 -0
  42. data/lib/leap_cli/ssh_key.rb +130 -0
  43. data/lib/leap_cli/util/remote_command.rb +110 -0
  44. data/lib/leap_cli/util/secret.rb +54 -0
  45. data/lib/leap_cli/util/x509.rb +32 -0
  46. data/lib/leap_cli/util.rb +431 -0
  47. data/lib/leap_cli/version.rb +9 -0
  48. data/lib/leap_cli.rb +46 -0
  49. data/lib/lib_ext/capistrano_connections.rb +16 -0
  50. data/lib/lib_ext/gli.rb +52 -0
  51. data/lib/lib_ext/markdown_document_listener.rb +122 -0
  52. data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +200 -0
  53. data/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +77 -0
  54. data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +97 -0
  55. data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +266 -0
  56. data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +148 -0
  57. data/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb +144 -0
  58. data/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb +65 -0
  59. data/vendor/certificate_authority/lib/certificate_authority/revocable.rb +14 -0
  60. data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +10 -0
  61. data/vendor/certificate_authority/lib/certificate_authority/signing_entity.rb +16 -0
  62. data/vendor/certificate_authority/lib/certificate_authority/signing_request.rb +56 -0
  63. data/vendor/certificate_authority/lib/certificate_authority.rb +21 -0
  64. data/vendor/rsync_command/lib/rsync_command/ssh_options.rb +159 -0
  65. data/vendor/rsync_command/lib/rsync_command/thread_pool.rb +36 -0
  66. data/vendor/rsync_command/lib/rsync_command/version.rb +3 -0
  67. data/vendor/rsync_command/lib/rsync_command.rb +96 -0
  68. data/vendor/rsync_command/test/rsync_test.rb +74 -0
  69. data/vendor/rsync_command/test/ssh_options_test.rb +61 -0
  70. data/vendor/vagrant_ssh_keys/vagrant.key +27 -0
  71. data/vendor/vagrant_ssh_keys/vagrant.pub +1 -0
  72. metadata +345 -0
@@ -0,0 +1,200 @@
1
+ module CertificateAuthority
2
+ class Certificate
3
+ include ActiveModel::Validations
4
+ include Revocable
5
+
6
+ attr_accessor :distinguished_name
7
+ attr_accessor :serial_number
8
+ attr_accessor :key_material
9
+ attr_accessor :not_before
10
+ attr_accessor :not_after
11
+ attr_accessor :extensions
12
+ attr_accessor :openssl_body
13
+
14
+ alias :subject :distinguished_name #Same thing as the DN
15
+
16
+ attr_accessor :parent
17
+
18
+ validate do |certificate|
19
+ errors.add :base, "Distinguished name must be valid" unless distinguished_name.valid?
20
+ errors.add :base, "Key material must be valid" unless key_material.valid?
21
+ errors.add :base, "Serial number must be valid" unless serial_number.valid?
22
+ errors.add :base, "Extensions must be valid" unless extensions.each do |item|
23
+ unless item.respond_to?(:valid?)
24
+ true
25
+ else
26
+ item.valid?
27
+ end
28
+ end
29
+ end
30
+
31
+ def initialize
32
+ self.distinguished_name = DistinguishedName.new
33
+ self.serial_number = SerialNumber.new
34
+ self.key_material = MemoryKeyMaterial.new
35
+ self.not_before = Time.now
36
+ self.not_after = Time.now + 60 * 60 * 24 * 365 #One year
37
+ self.parent = self
38
+ self.extensions = load_extensions()
39
+
40
+ self.signing_entity = false
41
+
42
+ end
43
+
44
+ def sign!(signing_profile={})
45
+ raise "Invalid certificate #{self.errors.full_messages}" unless valid?
46
+ merge_profile_with_extensions(signing_profile)
47
+
48
+ openssl_cert = OpenSSL::X509::Certificate.new
49
+ openssl_cert.version = 2
50
+ openssl_cert.not_before = self.not_before
51
+ openssl_cert.not_after = self.not_after
52
+ openssl_cert.public_key = self.key_material.public_key
53
+
54
+ openssl_cert.serial = self.serial_number.number
55
+
56
+ openssl_cert.subject = self.distinguished_name.to_x509_name
57
+ openssl_cert.issuer = parent.distinguished_name.to_x509_name
58
+
59
+ require 'tempfile'
60
+ t = Tempfile.new("bullshit_conf")
61
+ # t = File.new("/tmp/openssl.cnf")
62
+ ## The config requires a file even though we won't use it
63
+ openssl_config = OpenSSL::Config.new(t.path)
64
+
65
+ factory = OpenSSL::X509::ExtensionFactory.new
66
+ factory.subject_certificate = openssl_cert
67
+
68
+ #NB: If the parent doesn't have an SSL body we're making this a self-signed cert
69
+ if parent.openssl_body.nil?
70
+ factory.issuer_certificate = openssl_cert
71
+ else
72
+ factory.issuer_certificate = parent.openssl_body
73
+ end
74
+
75
+ self.extensions.keys.each do |k|
76
+ config_extensions = extensions[k].config_extensions
77
+ openssl_config = merge_options(openssl_config,config_extensions)
78
+ end
79
+
80
+ # p openssl_config.sections
81
+
82
+ factory.config = openssl_config
83
+
84
+ # Order matters: e.g. for self-signed, subjectKeyIdentifier must come before authorityKeyIdentifier
85
+ self.extensions.keys.sort{|a,b| b<=>a}.each do |k|
86
+ e = extensions[k]
87
+ next if e.to_s.nil? or e.to_s == "" ## If the extension returns an empty string we won't include it
88
+ ext = factory.create_ext(e.openssl_identifier, e.to_s)
89
+ openssl_cert.add_extension(ext)
90
+ end
91
+
92
+ if signing_profile["digest"].nil?
93
+ digest = OpenSSL::Digest::Digest.new("SHA512")
94
+ else
95
+ digest = OpenSSL::Digest::Digest.new(signing_profile["digest"])
96
+ end
97
+ self.openssl_body = openssl_cert.sign(parent.key_material.private_key,digest)
98
+ t.close! if t.is_a?(Tempfile)# We can get rid of the ridiculous temp file
99
+ self.openssl_body
100
+ end
101
+
102
+ def is_signing_entity?
103
+ self.extensions["basicConstraints"].ca
104
+ end
105
+
106
+ def signing_entity=(signing)
107
+ self.extensions["basicConstraints"].ca = signing
108
+ end
109
+
110
+ def revoked?
111
+ !self.revoked_at.nil?
112
+ end
113
+
114
+ def to_pem
115
+ raise "Certificate has no signed body" if self.openssl_body.nil?
116
+ self.openssl_body.to_pem
117
+ end
118
+
119
+ def is_root_entity?
120
+ self.parent == self && is_signing_entity?
121
+ end
122
+
123
+ def is_intermediate_entity?
124
+ (self.parent != self) && is_signing_entity?
125
+ end
126
+
127
+ private
128
+
129
+ def merge_profile_with_extensions(signing_profile={})
130
+ return self.extensions if signing_profile["extensions"].nil?
131
+ signing_config = signing_profile["extensions"]
132
+ signing_config.keys.each do |k|
133
+ extension = self.extensions[k]
134
+ items = signing_config[k]
135
+ items.keys.each do |profile_item_key|
136
+ if extension.respond_to?("#{profile_item_key}=".to_sym)
137
+ extension.send("#{profile_item_key}=".to_sym, items[profile_item_key] )
138
+ else
139
+ p "Tried applying '#{profile_item_key}' to #{extension.class} but it doesn't respond!"
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ def load_extensions
146
+ extension_hash = {}
147
+
148
+ temp_extensions = []
149
+ basic_constraints = CertificateAuthority::Extensions::BasicConstraints.new
150
+ temp_extensions << basic_constraints
151
+ crl_distribution_points = CertificateAuthority::Extensions::CrlDistributionPoints.new
152
+ temp_extensions << crl_distribution_points
153
+ subject_key_identifier = CertificateAuthority::Extensions::SubjectKeyIdentifier.new
154
+ temp_extensions << subject_key_identifier
155
+ authority_key_identifier = CertificateAuthority::Extensions::AuthorityKeyIdentifier.new
156
+ temp_extensions << authority_key_identifier
157
+ authority_info_access = CertificateAuthority::Extensions::AuthorityInfoAccess.new
158
+ temp_extensions << authority_info_access
159
+ key_usage = CertificateAuthority::Extensions::KeyUsage.new
160
+ temp_extensions << key_usage
161
+ extended_key_usage = CertificateAuthority::Extensions::ExtendedKeyUsage.new
162
+ temp_extensions << extended_key_usage
163
+ subject_alternative_name = CertificateAuthority::Extensions::SubjectAlternativeName.new
164
+ temp_extensions << subject_alternative_name
165
+ certificate_policies = CertificateAuthority::Extensions::CertificatePolicies.new
166
+ temp_extensions << certificate_policies
167
+
168
+ temp_extensions.each do |extension|
169
+ extension_hash[extension.openssl_identifier] = extension
170
+ end
171
+
172
+ extension_hash
173
+ end
174
+
175
+ def merge_options(config,hash)
176
+ hash.keys.each do |k|
177
+ config[k] = hash[k]
178
+ end
179
+ config
180
+ end
181
+
182
+ def self.from_openssl openssl_cert
183
+ unless openssl_cert.is_a? OpenSSL::X509::Certificate
184
+ raise "Can only construct from an OpenSSL::X509::Certificate"
185
+ end
186
+
187
+ certificate = Certificate.new
188
+ # Only subject, key_material, and body are used for signing
189
+ certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
190
+ certificate.key_material.public_key = openssl_cert.public_key
191
+ certificate.openssl_body = openssl_cert
192
+ certificate.serial_number.number = openssl_cert.serial.to_i
193
+ certificate.not_before = openssl_cert.not_before
194
+ certificate.not_after = openssl_cert.not_after
195
+ # TODO extensions
196
+ certificate
197
+ end
198
+
199
+ end
200
+ end
@@ -0,0 +1,77 @@
1
+ module CertificateAuthority
2
+ class CertificateRevocationList
3
+ include ActiveModel::Validations
4
+
5
+ attr_accessor :certificates
6
+ attr_accessor :parent
7
+ attr_accessor :crl_body
8
+ attr_accessor :next_update
9
+
10
+ validate do |crl|
11
+ errors.add :next_update, "Next update must be a positive value" if crl.next_update < 0
12
+ errors.add :parent, "A parent entity must be set" if crl.parent.nil?
13
+ end
14
+
15
+ def initialize
16
+ self.certificates = []
17
+ self.next_update = 60 * 60 * 4 # 4 hour default
18
+ end
19
+
20
+ def <<(revocable)
21
+ case revocable
22
+ when Revocable
23
+ raise "Only revoked entities can be added to a CRL" unless revocable.revoked?
24
+ self.certificates << revocable
25
+ when OpenSSL::X509::Certificate
26
+ raise "Not implemented yet"
27
+ else
28
+ raise "#{revocable.class} cannot be included in a CRL"
29
+ end
30
+ end
31
+
32
+ def sign!(signing_profile={})
33
+ raise "No parent entity has been set!" if self.parent.nil?
34
+ raise "Invalid CRL" unless self.valid?
35
+
36
+ revocations = self.certificates.collect do |revocable|
37
+ revocation = OpenSSL::X509::Revoked.new
38
+
39
+ ## We really just need a serial number, now we have to dig it out
40
+ case revocable
41
+ when Certificate
42
+ x509_cert = OpenSSL::X509::Certificate.new(revocable.to_pem)
43
+ revocation.serial = x509_cert.serial
44
+ when SerialNumber
45
+ revocation.serial = revocable.number
46
+ end
47
+ revocation.time = revocable.revoked_at
48
+ revocation
49
+ end
50
+
51
+ crl = OpenSSL::X509::CRL.new
52
+ revocations.each do |revocation|
53
+ crl.add_revoked(revocation)
54
+ end
55
+
56
+ crl.version = 1
57
+ crl.last_update = Time.now
58
+ crl.next_update = Time.now + self.next_update
59
+
60
+ signing_cert = OpenSSL::X509::Certificate.new(self.parent.to_pem)
61
+ if signing_profile["digest"].nil?
62
+ digest = OpenSSL::Digest::Digest.new("SHA512")
63
+ else
64
+ digest = OpenSSL::Digest::Digest.new(signing_profile["digest"])
65
+ end
66
+ crl.issuer = signing_cert.subject
67
+ self.crl_body = crl.sign(self.parent.key_material.private_key, digest)
68
+
69
+ self.crl_body
70
+ end
71
+
72
+ def to_pem
73
+ raise "No signed CRL body" if self.crl_body.nil?
74
+ self.crl_body.to_pem
75
+ end
76
+ end#CertificateRevocationList
77
+ end
@@ -0,0 +1,97 @@
1
+ module CertificateAuthority
2
+ class DistinguishedName
3
+ include ActiveModel::Validations
4
+
5
+ validates_presence_of :common_name
6
+
7
+ attr_accessor :common_name
8
+ alias :cn :common_name
9
+ alias :cn= :common_name=
10
+
11
+ attr_accessor :locality
12
+ alias :l :locality
13
+ alias :l= :locality=
14
+
15
+ attr_accessor :state
16
+ alias :s :state
17
+ alias :st= :state=
18
+
19
+ attr_accessor :country
20
+ alias :c :country
21
+ alias :c= :country=
22
+
23
+ attr_accessor :organization
24
+ alias :o :organization
25
+ alias :o= :organization=
26
+
27
+ attr_accessor :organizational_unit
28
+ alias :ou :organizational_unit
29
+ alias :ou= :organizational_unit=
30
+
31
+ attr_accessor :email_address
32
+ alias :emailAddress :email_address
33
+ alias :emailAddress= :email_address=
34
+
35
+ def to_x509_name
36
+ raise "Invalid Distinguished Name" unless valid?
37
+
38
+ # NB: the capitalization in the strings counts
39
+ name = OpenSSL::X509::Name.new
40
+ name.add_entry("C", country) unless country.blank?
41
+ name.add_entry("ST", state) unless state.blank?
42
+ name.add_entry("L", locality) unless locality.blank?
43
+ name.add_entry("O", organization) unless organization.blank?
44
+ name.add_entry("OU", organizational_unit) unless organizational_unit.blank?
45
+ name.add_entry("CN", common_name)
46
+ name.add_entry("emailAddress", email_address) unless email_address.blank?
47
+ name
48
+ end
49
+
50
+ def ==(other)
51
+ # Use the established OpenSSL comparison
52
+ self.to_x509_name() == other.to_x509_name()
53
+ end
54
+
55
+ def self.from_openssl openssl_name
56
+ unless openssl_name.is_a? OpenSSL::X509::Name
57
+ raise "Argument must be a OpenSSL::X509::Name"
58
+ end
59
+
60
+ WrappedDistinguishedName.new(openssl_name)
61
+ end
62
+ end
63
+
64
+ ## This is a significantly more complicated case. It's possible that
65
+ ## generically handled certificates will include custom OIDs in the
66
+ ## subject.
67
+ class WrappedDistinguishedName < DistinguishedName
68
+ attr_accessor :x509_name
69
+
70
+ def initialize(x509_name)
71
+ @x509_name = x509_name
72
+
73
+ subject = @x509_name.to_a
74
+ subject.each do |element|
75
+ field = element[0].downcase
76
+ value = element[1]
77
+ #type = element[2] ## -not used
78
+ method_sym = "#{field}=".to_sym
79
+ if self.respond_to?(method_sym)
80
+ self.send("#{field}=",value)
81
+ else
82
+ ## Custom OID
83
+ @custom_oids = true
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ def to_x509_name
90
+ @x509_name
91
+ end
92
+
93
+ def custom_oids?
94
+ @custom_oids
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,266 @@
1
+ module CertificateAuthority
2
+ module Extensions
3
+ module ExtensionAPI
4
+ def to_s
5
+ raise "Implementation required"
6
+ end
7
+
8
+ def config_extensions
9
+ {}
10
+ end
11
+
12
+ def openssl_identifier
13
+ raise "Implementation required"
14
+ end
15
+ end
16
+
17
+ class BasicConstraints
18
+ include ExtensionAPI
19
+ include ActiveModel::Validations
20
+ attr_accessor :ca
21
+ attr_accessor :path_len
22
+ validates :ca, :inclusion => [true,false]
23
+
24
+ def initialize
25
+ self.ca = false
26
+ end
27
+
28
+ def is_ca?
29
+ self.ca
30
+ end
31
+
32
+ def path_len=(value)
33
+ raise "path_len must be a non-negative integer" if value < 0 or !value.is_a?(Fixnum)
34
+ @path_len = value
35
+ end
36
+
37
+ def openssl_identifier
38
+ "basicConstraints"
39
+ end
40
+
41
+ def to_s
42
+ result = ""
43
+ result += "CA:#{self.ca}"
44
+ result += ",pathlen:#{self.path_len}" unless self.path_len.nil?
45
+ result
46
+ end
47
+ end
48
+
49
+ class CrlDistributionPoints
50
+ include ExtensionAPI
51
+
52
+ attr_accessor :uri
53
+
54
+ def initialize
55
+ # self.uri = "http://moo.crlendPoint.example.com/something.crl"
56
+ end
57
+
58
+ def openssl_identifier
59
+ "crlDistributionPoints"
60
+ end
61
+
62
+ ## NB: At this time it seems OpenSSL's extension handlers don't support
63
+ ## any of the config options the docs claim to support... everything comes back
64
+ ## "missing value" on GENERAL NAME. Even if copied verbatim
65
+ def config_extensions
66
+ {
67
+ # "custom_crl_fields" => {"fullname" => "URI:#{fullname}"},
68
+ # "issuer_sect" => {"CN" => "crlissuer.com", "C" => "US", "O" => "shudder"}
69
+ }
70
+ end
71
+
72
+ def to_s
73
+ return "" if self.uri.nil?
74
+ "URI:#{self.uri}"
75
+ end
76
+ end
77
+
78
+ class SubjectKeyIdentifier
79
+ include ExtensionAPI
80
+ def openssl_identifier
81
+ "subjectKeyIdentifier"
82
+ end
83
+
84
+ def to_s
85
+ "hash"
86
+ end
87
+ end
88
+
89
+ class AuthorityKeyIdentifier
90
+ include ExtensionAPI
91
+
92
+ def openssl_identifier
93
+ "authorityKeyIdentifier"
94
+ end
95
+
96
+ def to_s
97
+ "keyid,issuer"
98
+ end
99
+ end
100
+
101
+ class AuthorityInfoAccess
102
+ include ExtensionAPI
103
+
104
+ attr_accessor :ocsp
105
+
106
+ def initialize
107
+ self.ocsp = []
108
+ end
109
+
110
+ def openssl_identifier
111
+ "authorityInfoAccess"
112
+ end
113
+
114
+ def to_s
115
+ return "" if self.ocsp.empty?
116
+ "OCSP;URI:#{self.ocsp}"
117
+ end
118
+ end
119
+
120
+ class KeyUsage
121
+ include ExtensionAPI
122
+
123
+ attr_accessor :usage
124
+
125
+ def initialize
126
+ self.usage = ["digitalSignature", "nonRepudiation"]
127
+ end
128
+
129
+ def openssl_identifier
130
+ "keyUsage"
131
+ end
132
+
133
+ def to_s
134
+ "#{self.usage.join(',')}"
135
+ end
136
+ end
137
+
138
+ class ExtendedKeyUsage
139
+ include ExtensionAPI
140
+
141
+ attr_accessor :usage
142
+
143
+ def initialize
144
+ self.usage = ["serverAuth","clientAuth"]
145
+ end
146
+
147
+ def openssl_identifier
148
+ "extendedKeyUsage"
149
+ end
150
+
151
+ def to_s
152
+ "#{self.usage.join(',')}"
153
+ end
154
+ end
155
+
156
+ class SubjectAlternativeName
157
+ include ExtensionAPI
158
+
159
+ attr_accessor :uris, :dns_names, :ips
160
+
161
+ def initialize
162
+ self.uris = []
163
+ self.dns_names = []
164
+ self.ips = []
165
+ end
166
+
167
+ def uris=(value)
168
+ raise "URIs must be an array" unless value.is_a?(Array)
169
+ @uris = value
170
+ end
171
+
172
+ def dns_names=(value)
173
+ raise "DNS names must be an array" unless value.is_a?(Array)
174
+ @dns_names = value
175
+ end
176
+
177
+ def ips=(value)
178
+ raise "IPs must be an array" unless value.is_a?(Array)
179
+ @ips = value
180
+ end
181
+
182
+ def openssl_identifier
183
+ "subjectAltName"
184
+ end
185
+
186
+ def to_s
187
+ res = self.uris.map {|u| "URI:#{u}" }
188
+ res += self.dns_names.map {|d| "DNS:#{d}" }
189
+ res += self.ips.map {|i| "IP:#{i}" }
190
+
191
+ return res.join(',')
192
+ end
193
+ end
194
+
195
+ class CertificatePolicies
196
+ include ExtensionAPI
197
+
198
+ attr_accessor :policy_identifier
199
+ attr_accessor :cps_uris
200
+ ##User notice
201
+ attr_accessor :explicit_text
202
+ attr_accessor :organization
203
+ attr_accessor :notice_numbers
204
+
205
+ def initialize
206
+ @contains_data = false
207
+ end
208
+
209
+
210
+ def openssl_identifier
211
+ "certificatePolicies"
212
+ end
213
+
214
+ def user_notice=(value={})
215
+ value.keys.each do |key|
216
+ self.send("#{key}=".to_sym, value[key])
217
+ end
218
+ end
219
+
220
+ def config_extensions
221
+ config_extension = {}
222
+ custom_policies = {}
223
+ notice = {}
224
+ unless self.policy_identifier.nil?
225
+ custom_policies["policyIdentifier"] = self.policy_identifier
226
+ end
227
+
228
+ if !self.cps_uris.nil? and self.cps_uris.is_a?(Array)
229
+ self.cps_uris.each_with_index do |cps_uri,i|
230
+ custom_policies["CPS.#{i}"] = cps_uri
231
+ end
232
+ end
233
+
234
+ unless self.explicit_text.nil?
235
+ notice["explicitText"] = self.explicit_text
236
+ end
237
+
238
+ unless self.organization.nil?
239
+ notice["organization"] = self.organization
240
+ end
241
+
242
+ unless self.notice_numbers.nil?
243
+ notice["noticeNumbers"] = self.notice_numbers
244
+ end
245
+
246
+ if notice.keys.size > 0
247
+ custom_policies["userNotice.1"] = "@notice"
248
+ config_extension["notice"] = notice
249
+ end
250
+
251
+ if custom_policies.keys.size > 0
252
+ config_extension["custom_policies"] = custom_policies
253
+ @contains_data = true
254
+ end
255
+
256
+ config_extension
257
+ end
258
+
259
+ def to_s
260
+ return "" unless @contains_data
261
+ "ia5org,@custom_policies"
262
+ end
263
+ end
264
+
265
+ end
266
+ end