r509 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/CONTRIBUTING.mdown +21 -0
- data/LICENSE +13 -0
- data/README.mdown +548 -0
- data/Rakefile +5 -0
- data/bin/r509 +16 -17
- data/doc/R509.html +42 -26
- data/doc/R509/ASN1.html +22 -16
- data/doc/R509/ASN1/GeneralName.html +180 -173
- data/doc/R509/ASN1/GeneralNames.html +390 -62
- data/doc/R509/CRL.html +9 -7
- data/doc/R509/CRL/Administrator.html +208 -623
- data/doc/R509/CRL/FileReaderWriter.html +856 -0
- data/doc/R509/CRL/ReaderWriter.html +524 -0
- data/doc/R509/CRL/SignedList.html +29 -42
- data/doc/R509/CSR.html +248 -333
- data/doc/R509/Cert.html +364 -491
- data/doc/R509/Cert/Extensions.html +134 -43
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +335 -65
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +201 -102
- data/doc/R509/Cert/Extensions/BasicConstraints.html +297 -68
- data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +690 -77
- data/doc/R509/Cert/Extensions/CertificatePolicies.html +293 -43
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +321 -173
- data/doc/R509/Cert/Extensions/GeneralNamesMixin.html +656 -0
- data/doc/R509/Cert/Extensions/InhibitAnyPolicy.html +270 -42
- data/doc/R509/Cert/Extensions/KeyUsage.html +334 -184
- data/doc/R509/Cert/Extensions/NameConstraints.html +363 -93
- data/doc/R509/{ASN1 → Cert/Extensions}/NoticeReference.html +209 -48
- data/doc/R509/Cert/Extensions/OCSPNoCheck.html +244 -17
- data/doc/R509/Cert/Extensions/PolicyConstraints.html +322 -71
- data/doc/R509/{ASN1 → Cert/Extensions}/PolicyInformation.html +204 -43
- data/doc/R509/{ASN1 → Cert/Extensions}/PolicyQualifiers.html +205 -48
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +348 -143
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +165 -13
- data/doc/R509/{ASN1 → Cert/Extensions}/UserNotice.html +204 -43
- data/doc/R509/Cert/Extensions/ValidationMixin.html +120 -0
- data/doc/R509/CertificateAuthority.html +9 -7
- data/doc/R509/CertificateAuthority/OptionsBuilder.html +475 -0
- data/doc/R509/CertificateAuthority/Signer.html +149 -198
- data/doc/R509/Config.html +10 -8
- data/doc/R509/Config/CAConfig.html +708 -625
- data/doc/R509/Config/CAConfigPool.html +179 -31
- data/doc/R509/Config/CertProfile.html +1544 -0
- data/doc/R509/Config/SubjectItemPolicy.html +437 -99
- data/doc/R509/Engine.html +14 -28
- data/doc/R509/Helpers.html +1014 -0
- data/doc/R509/MessageDigest.html +73 -25
- data/doc/R509/NameSanitizer.html +39 -39
- data/doc/R509/OCSP.html +5 -5
- data/doc/R509/OCSP/Request.html +5 -5
- data/doc/R509/OCSP/Request/Nonce.html +5 -5
- data/doc/R509/OCSP/Response.html +7 -7
- data/doc/R509/OIDMapper.html +121 -6
- data/doc/R509/PrivateKey.html +226 -227
- data/doc/R509/R509Error.html +5 -5
- data/doc/R509/SPKI.html +244 -342
- data/doc/R509/Subject.html +241 -70
- data/doc/R509/Validity.html +5 -5
- data/doc/R509/Validity/Checker.html +5 -5
- data/doc/R509/Validity/DefaultChecker.html +5 -9
- data/doc/R509/Validity/DefaultWriter.html +5 -9
- data/doc/R509/Validity/Status.html +5 -5
- data/doc/R509/Validity/Writer.html +5 -5
- data/doc/_index.html +92 -30
- data/doc/class_list.html +2 -2
- data/doc/file.CONTRIBUTING.html +96 -0
- data/doc/file.LICENSE.html +87 -0
- data/doc/file.README.html +279 -389
- data/doc/file.YAML.html +243 -0
- data/doc/file.r509.html +298 -105
- data/doc/file_list.html +11 -2
- data/doc/frames.html +1 -1
- data/doc/index.html +279 -389
- data/doc/js/full_list.js +6 -1
- data/doc/method_list.html +869 -1139
- data/doc/top-level-namespace.html +103 -5
- data/lib/r509.rb +7 -2
- data/lib/r509/asn1.rb +97 -135
- data/lib/r509/cert.rb +17 -106
- data/lib/r509/cert/extensions.rb +13 -676
- data/lib/r509/cert/extensions/authority_info_access.rb +128 -0
- data/lib/r509/cert/extensions/authority_key_identifier.rb +100 -0
- data/lib/r509/cert/extensions/base.rb +142 -0
- data/lib/r509/cert/extensions/basic_constraints.rb +119 -0
- data/lib/r509/cert/extensions/certificate_policies.rb +262 -0
- data/lib/r509/cert/extensions/crl_distribution_points.rb +98 -0
- data/lib/r509/cert/extensions/extended_key_usage.rb +189 -0
- data/lib/r509/cert/extensions/inhibit_any_policy.rb +70 -0
- data/lib/r509/cert/extensions/key_usage.rb +209 -0
- data/lib/r509/cert/extensions/name_constraints.rb +179 -0
- data/lib/r509/cert/extensions/ocsp_no_check.rb +56 -0
- data/lib/r509/cert/extensions/policy_constraints.rb +122 -0
- data/lib/r509/cert/extensions/subject_alternative_name.rb +88 -0
- data/lib/r509/cert/extensions/subject_key_identifier.rb +56 -0
- data/lib/r509/cert/extensions/validation_mixin.rb +42 -0
- data/lib/r509/certificate_authority/options_builder.rb +142 -0
- data/lib/r509/certificate_authority/signer.rb +189 -0
- data/lib/r509/config.rb +3 -600
- data/lib/r509/config/ca_config.rb +414 -0
- data/lib/r509/config/cert_profile.rb +110 -0
- data/lib/r509/config/subject_item_policy.rb +118 -0
- data/lib/r509/crl/administrator.rb +169 -0
- data/lib/r509/crl/reader_writer.rb +109 -0
- data/lib/r509/crl/signed_list.rb +135 -0
- data/lib/r509/csr.rb +35 -116
- data/lib/r509/engine.rb +21 -11
- data/lib/r509/helpers.rb +110 -0
- data/lib/r509/io_helpers.rb +18 -13
- data/lib/r509/message_digest.rb +13 -3
- data/lib/r509/oid_mapper.rb +14 -0
- data/lib/r509/private_key.rb +74 -50
- data/lib/r509/spki.rb +50 -113
- data/lib/r509/subject.rb +24 -2
- data/lib/r509/trollop.rb +788 -0
- data/lib/r509/version.rb +1 -1
- data/r509.yaml +289 -96
- data/spec/asn1_spec.rb +171 -98
- data/spec/cert/extensions/authority_info_access_spec.rb +247 -0
- data/spec/cert/extensions/authority_key_identifier_spec.rb +85 -0
- data/spec/cert/extensions/base_spec.rb +172 -0
- data/spec/cert/extensions/basic_constraints_spec.rb +185 -0
- data/spec/cert/extensions/certificate_policies_spec.rb +288 -0
- data/spec/cert/extensions/crl_distribution_points_spec.rb +149 -0
- data/spec/cert/extensions/extended_key_usage_spec.rb +174 -0
- data/spec/cert/extensions/inhibit_any_policy_spec.rb +92 -0
- data/spec/cert/extensions/key_usage_spec.rb +172 -0
- data/spec/cert/extensions/name_constraints_spec.rb +335 -0
- data/spec/cert/extensions/ocsp_no_check_spec.rb +76 -0
- data/spec/cert/extensions/policy_constraints_spec.rb +155 -0
- data/spec/cert/extensions/subject_alternative_name_spec.rb +354 -0
- data/spec/cert/extensions/subject_key_identifier_spec.rb +64 -0
- data/spec/cert_spec.rb +11 -9
- data/spec/certificate_authority/options_builder_spec.rb +307 -0
- data/spec/certificate_authority/signer_spec.rb +278 -0
- data/spec/config/ca_config_spec.rb +405 -0
- data/spec/config/cert_profile_spec.rb +88 -0
- data/spec/config/subject_item_policy_spec.rb +81 -0
- data/spec/crl/administrator_spec.rb +199 -0
- data/spec/crl/reader_writer_spec.rb +97 -0
- data/spec/crl/signed_list_spec.rb +84 -0
- data/spec/csr_spec.rb +43 -36
- data/spec/engine_spec.rb +51 -0
- data/spec/fixtures.rb +40 -40
- data/spec/fixtures/cert1.pem +1 -1
- data/spec/fixtures/config_pool_test_minimal.yaml +11 -15
- data/spec/fixtures/config_test.yaml +96 -59
- data/spec/fixtures/config_test_dsa.yaml +29 -35
- data/spec/fixtures/config_test_ec.yaml +29 -35
- data/spec/fixtures/config_test_engine_key.yaml +7 -7
- data/spec/fixtures/config_test_engine_no_key_name.yaml +6 -6
- data/spec/fixtures/config_test_minimal.yaml +3 -5
- data/spec/fixtures/config_test_password.yaml +4 -6
- data/spec/fixtures/config_test_various.yaml +147 -137
- data/spec/fixtures/crl_list_file.txt +1 -1
- data/spec/fixtures/test_ca_crl.cer +20 -0
- data/spec/fixtures/test_ca_crl.key +28 -0
- data/spec/fixtures/test_ca_crl.p12 +0 -0
- data/spec/message_digest_spec.rb +6 -0
- data/spec/oid_mapper_spec.rb +11 -0
- data/spec/private_key_spec.rb +19 -18
- data/spec/spec_helper.rb +10 -6
- data/spec/spki_spec.rb +38 -19
- data/spec/subject_spec.rb +16 -0
- metadata +108 -59
- metadata.gz.sig +0 -0
- data/README.md +0 -638
- data/doc/R509/Config/CAProfile.html +0 -1015
- data/doc/R509/IOHelpers.html +0 -564
- data/lib/r509/certificate_authority.rb +0 -407
- data/lib/r509/crl.rb +0 -351
- data/spec/cert/extensions_spec.rb +0 -1095
- data/spec/certificate_authority_spec.rb +0 -681
- data/spec/config_spec.rb +0 -562
- data/spec/crl_spec.rb +0 -226
@@ -0,0 +1,405 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r509/config/ca_config'
|
3
|
+
require 'r509/exceptions'
|
4
|
+
|
5
|
+
describe R509::Config::CAConfigPool do
|
6
|
+
context "defined manually" do
|
7
|
+
it "has no configs" do
|
8
|
+
pool = R509::Config::CAConfigPool.new({})
|
9
|
+
|
10
|
+
pool["first"].should == nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "has one config" do
|
14
|
+
config = R509::Config::CAConfig.new(
|
15
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
16
|
+
:profiles => { "first_profile" => R509::Config::CertProfile.new }
|
17
|
+
)
|
18
|
+
|
19
|
+
pool = R509::Config::CAConfigPool.new({
|
20
|
+
"first" => config
|
21
|
+
})
|
22
|
+
|
23
|
+
pool["first"].should == config
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "all configs" do
|
28
|
+
context "no configs" do
|
29
|
+
before :all do
|
30
|
+
@pool = R509::Config::CAConfigPool.new({})
|
31
|
+
end
|
32
|
+
|
33
|
+
it "creates" do
|
34
|
+
@pool.all.should == []
|
35
|
+
end
|
36
|
+
|
37
|
+
it "builds yaml" do
|
38
|
+
YAML.load(@pool.to_yaml).should == {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "one config" do
|
43
|
+
before :all do
|
44
|
+
@config = R509::Config::CAConfig.new(
|
45
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
46
|
+
:profiles => { "first_profile" => R509::Config::CertProfile.new }
|
47
|
+
)
|
48
|
+
@pool = R509::Config::CAConfigPool.new({
|
49
|
+
"first" => @config
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
it "creates" do
|
54
|
+
@pool.all.should == [@config]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "builds yaml" do
|
58
|
+
YAML.load(@pool.to_yaml).should == {"first"=>{"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1", "profiles"=>{"first_profile"=>{"default_md"=>"SHA1"}}}}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "two configs" do
|
63
|
+
before :all do
|
64
|
+
@config1 = R509::Config::CAConfig.new(
|
65
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
66
|
+
:profiles => { "first_profile" => R509::Config::CertProfile.new }
|
67
|
+
)
|
68
|
+
@config2 = R509::Config::CAConfig.new(
|
69
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
70
|
+
:profiles => { "first_profile" => R509::Config::CertProfile.new }
|
71
|
+
)
|
72
|
+
@pool = R509::Config::CAConfigPool.new({
|
73
|
+
"first" => @config1,
|
74
|
+
"second" => @config2
|
75
|
+
})
|
76
|
+
end
|
77
|
+
|
78
|
+
it "creates" do
|
79
|
+
@pool.all.size.should == 2
|
80
|
+
@pool.all.include?(@config1).should == true
|
81
|
+
@pool.all.include?(@config2).should == true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "builds yaml" do
|
85
|
+
YAML.load(@pool.to_yaml).should == {"first"=>{"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1", "profiles"=>{"first_profile"=>{"default_md"=>"SHA1"}}}, "second"=>{"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1", "profiles"=>{"first_profile"=>{"default_md"=>"SHA1"}}}}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "loaded from YAML" do
|
91
|
+
it "should load two configs" do
|
92
|
+
pool = R509::Config::CAConfigPool.from_yaml("certificate_authorities", File.read("#{File.dirname(__FILE__)}/../fixtures/config_pool_test_minimal.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
93
|
+
|
94
|
+
pool.names.should include("test_ca", "second_ca")
|
95
|
+
|
96
|
+
pool["test_ca"].should_not == nil
|
97
|
+
pool["test_ca"].num_profiles.should == 0
|
98
|
+
pool["second_ca"].should_not == nil
|
99
|
+
pool["second_ca"].num_profiles.should == 0
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
describe R509::Config::CAConfig do
|
106
|
+
before :each do
|
107
|
+
@config = R509::Config::CAConfig.new(
|
108
|
+
:ca_cert => TestFixtures.test_ca_cert
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
subject {@config}
|
113
|
+
|
114
|
+
its(:crl_validity_hours) {should == 168}
|
115
|
+
its(:ocsp_validity_hours) {should == 168}
|
116
|
+
its(:ocsp_start_skew_seconds) {should == 3600}
|
117
|
+
its(:num_profiles) {should == 0}
|
118
|
+
|
119
|
+
it "should have the proper CA cert" do
|
120
|
+
@config.ca_cert.to_pem.should == TestFixtures.test_ca_cert.to_pem
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should have the proper CA key" do
|
124
|
+
@config.ca_cert.key.to_pem.should == TestFixtures.test_ca_cert.key.to_pem
|
125
|
+
end
|
126
|
+
|
127
|
+
context "to_yaml" do
|
128
|
+
it "includes engine stub if in hardware" do
|
129
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert)
|
130
|
+
config.ca_cert.key.should_receive(:in_hardware?).and_return(true)
|
131
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "engine"=>{:so_path=>"<add_path>", :id=>"<add_name>"}}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1"}
|
132
|
+
end
|
133
|
+
it "includes ocsp_cert stub if not nil" do
|
134
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :ocsp_cert => TestFixtures.test_ca_cert)
|
135
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1"}
|
136
|
+
end
|
137
|
+
it "includes crl_cert stub if not nil" do
|
138
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :crl_cert => TestFixtures.test_ca_cert)
|
139
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "crl_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1"}
|
140
|
+
end
|
141
|
+
it "includes ocsp_chain if not nil" do
|
142
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :ocsp_chain => [OpenSSL::X509::Certificate.new])
|
143
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_chain"=>"<add_path>", "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1"}
|
144
|
+
end
|
145
|
+
it "includes crl_list_file if not nil" do
|
146
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :crl_list_file => '/some/path')
|
147
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_list_file"=>"/some/path", "crl_md"=>"SHA1"}
|
148
|
+
end
|
149
|
+
it "includes crl_number_file if not nil" do
|
150
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :crl_number_file => '/some/path')
|
151
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_number_file"=>"/some/path", "crl_md"=>"SHA1"}
|
152
|
+
end
|
153
|
+
it "includes profiles" do
|
154
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert)
|
155
|
+
profile = R509::Config::CertProfile.new(
|
156
|
+
:basic_constraints => {:ca => true}
|
157
|
+
)
|
158
|
+
config.set_profile("subroot",profile)
|
159
|
+
config.set_profile("subroot_also",profile)
|
160
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1", "profiles"=>{"subroot"=>{"basic_constraints"=>{:ca=>true, :critical=>true}, "default_md"=>"SHA1"}, "subroot_also"=>{"basic_constraints"=>{:ca=>true, :critical=>true}, "default_md"=>"SHA1"}}}
|
161
|
+
end
|
162
|
+
it "includes defaults" do
|
163
|
+
config = R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert)
|
164
|
+
YAML.load(config.to_yaml).should == {"ca_cert"=>{"cert"=>"<add_path>", "key"=>"<add_path>"}, "ocsp_start_skew_seconds"=>3600, "ocsp_validity_hours"=>168, "crl_start_skew_seconds"=>3600, "crl_validity_hours"=>168, "crl_md"=>"SHA1"}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "validates data" do
|
169
|
+
it "raises an error if you don't pass :ca_cert" do
|
170
|
+
expect { R509::Config::CAConfig.new(:crl_validity_hours => 2) }.to raise_error ArgumentError, 'Config object requires that you pass :ca_cert'
|
171
|
+
end
|
172
|
+
it "raises an error if :ca_cert is not of type R509::Cert" do
|
173
|
+
expect { R509::Config::CAConfig.new(:ca_cert => 'not a cert, and not right type') }.to raise_error ArgumentError, ':ca_cert must be of type R509::Cert'
|
174
|
+
end
|
175
|
+
it "raises an error if :ocsp_cert that is not R509::Cert" do
|
176
|
+
expect { R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :ocsp_cert => "not a cert") }.to raise_error ArgumentError, ':ocsp_cert, if provided, must be of type R509::Cert'
|
177
|
+
end
|
178
|
+
it "raises an error if :ocsp_cert does not contain a private key" do
|
179
|
+
expect { R509::Config::CAConfig.new( :ca_cert => TestFixtures.test_ca_cert, :ocsp_cert => R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT) ) }.to raise_error ArgumentError, ':ocsp_cert must contain a private key, not just a certificate'
|
180
|
+
end
|
181
|
+
it "raises an error if :crl_cert that is not R509::Cert" do
|
182
|
+
expect { R509::Config::CAConfig.new(:ca_cert => TestFixtures.test_ca_cert, :crl_cert => "not a cert") }.to raise_error ArgumentError, ':crl_cert, if provided, must be of type R509::Cert'
|
183
|
+
end
|
184
|
+
it "raises an error if :crl_cert does not contain a private key" do
|
185
|
+
expect { R509::Config::CAConfig.new( :ca_cert => TestFixtures.test_ca_cert, :crl_cert => R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT) ) }.to raise_error ArgumentError, ':crl_cert must contain a private key, not just a certificate'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it "loads the config even if :ca_cert does not contain a private key" do
|
190
|
+
config = R509::Config::CAConfig.new( :ca_cert => R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT) )
|
191
|
+
config.ca_cert.subject.to_s.should_not be_nil
|
192
|
+
end
|
193
|
+
it "returns the correct cert object on #ocsp_cert if none is specified" do
|
194
|
+
@config.ocsp_cert.should == @config.ca_cert
|
195
|
+
end
|
196
|
+
it "returns the correct cert object on #ocsp_cert if an ocsp_cert was specified" do
|
197
|
+
ocsp_cert = R509::Cert.new(
|
198
|
+
:cert => TestFixtures::TEST_CA_OCSP_CERT,
|
199
|
+
:key => TestFixtures::TEST_CA_OCSP_KEY
|
200
|
+
)
|
201
|
+
config = R509::Config::CAConfig.new(
|
202
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
203
|
+
:ocsp_cert => ocsp_cert
|
204
|
+
)
|
205
|
+
|
206
|
+
config.ocsp_cert.should == ocsp_cert
|
207
|
+
end
|
208
|
+
it "returns the correct cert object on #crl_cert if none is specified" do
|
209
|
+
@config.crl_cert.should == @config.ca_cert
|
210
|
+
end
|
211
|
+
it "returns the correct cert object on #crl_cert if an crl_cert was specified" do
|
212
|
+
crl_cert = R509::Cert.new(
|
213
|
+
:cert => TestFixtures::TEST_CA_OCSP_CERT,
|
214
|
+
:key => TestFixtures::TEST_CA_OCSP_KEY
|
215
|
+
)
|
216
|
+
config = R509::Config::CAConfig.new(
|
217
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
218
|
+
:crl_cert => crl_cert
|
219
|
+
)
|
220
|
+
|
221
|
+
config.crl_cert.should == crl_cert
|
222
|
+
end
|
223
|
+
it "fails to specify a non-Config::CertProfile as the profile" do
|
224
|
+
config = R509::Config::CAConfig.new(
|
225
|
+
:ca_cert => TestFixtures.test_ca_cert
|
226
|
+
)
|
227
|
+
|
228
|
+
expect{ config.set_profile("bogus", "not a Config::CertProfile")}.to raise_error TypeError
|
229
|
+
end
|
230
|
+
|
231
|
+
it "shouldn't let you specify a profile that's not a Config::CertProfile, on instantiation" do
|
232
|
+
expect{ R509::Config::CAConfig.new(
|
233
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
234
|
+
:profiles => { "first_profile" => "not a Config::CertProfile" }
|
235
|
+
) }.to raise_error TypeError
|
236
|
+
end
|
237
|
+
|
238
|
+
it "can specify a single profile" do
|
239
|
+
first_profile = R509::Config::CertProfile.new
|
240
|
+
|
241
|
+
config = R509::Config::CAConfig.new(
|
242
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
243
|
+
:profiles => { "first_profile" => first_profile }
|
244
|
+
)
|
245
|
+
|
246
|
+
config.profile("first_profile").should == first_profile
|
247
|
+
end
|
248
|
+
|
249
|
+
it "raises an error if you specify an invalid profile" do
|
250
|
+
first_profile = R509::Config::CertProfile.new
|
251
|
+
|
252
|
+
config = R509::Config::CAConfig.new(
|
253
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
254
|
+
:profiles => { "first_profile" => first_profile }
|
255
|
+
)
|
256
|
+
|
257
|
+
expect { config.profile("non-existent-profile") }.to raise_error(R509::R509Error, "unknown profile 'non-existent-profile'")
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should load YAML" do
|
261
|
+
config = R509::Config::CAConfig.from_yaml("test_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
262
|
+
config.crl_validity_hours.should == 72
|
263
|
+
config.ocsp_validity_hours.should == 96
|
264
|
+
config.crl_list_file.should match /list_file$/
|
265
|
+
config.crl_number_file.should match /number_file$/
|
266
|
+
config.num_profiles.should == 9
|
267
|
+
config.profile("mds").default_md.should == "SHA512"
|
268
|
+
config.profile("mds").allowed_mds.should == ['SHA512','SHA1']
|
269
|
+
aia = config.profile("aia_cdp").authority_info_access
|
270
|
+
aia.ocsp.uris.should == ['http://ocsp.domain.com']
|
271
|
+
aia.ca_issuers.uris.should == ['http://www.domain.com/cert.cer']
|
272
|
+
cdp = config.profile("aia_cdp").crl_distribution_points
|
273
|
+
cdp.uris.should == ['http://crl.domain.com/something.crl']
|
274
|
+
config.profile("ocsp_delegate_with_no_check").ocsp_no_check.should_not be_nil
|
275
|
+
config.profile("inhibit_policy").inhibit_any_policy.value.should == 2
|
276
|
+
config.profile("policy_constraints").policy_constraints.require_explicit_policy.should == 1
|
277
|
+
config.profile("policy_constraints").policy_constraints.inhibit_policy_mapping.should == 0
|
278
|
+
config.profile("name_constraints").name_constraints.should_not be_nil
|
279
|
+
end
|
280
|
+
it "loads CRL cert/key from yaml" do
|
281
|
+
config = R509::Config::CAConfig.from_yaml("crl_delegate_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
282
|
+
config.crl_cert.has_private_key?.should == true
|
283
|
+
config.crl_cert.subject.to_s.should == "/C=US/ST=Illinois/L=Chicago/O=r509 LLC/CN=r509 CRL Delegate"
|
284
|
+
end
|
285
|
+
it "loads CRL pkcs12 from yaml" do
|
286
|
+
config = R509::Config::CAConfig.from_yaml("crl_pkcs12_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
287
|
+
config.crl_cert.has_private_key?.should == true
|
288
|
+
config.crl_cert.subject.to_s.should == "/C=US/ST=Illinois/L=Chicago/O=r509 LLC/CN=r509 CRL Delegate"
|
289
|
+
end
|
290
|
+
it "loads CRL cert/key in engine from yaml" do
|
291
|
+
expect { R509::Config::CAConfig.from_yaml("crl_engine_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError,"You must supply a key_name with an engine")
|
292
|
+
end
|
293
|
+
it "loads OCSP cert/key from yaml" do
|
294
|
+
config = R509::Config::CAConfig.from_yaml("ocsp_delegate_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
295
|
+
config.ocsp_cert.has_private_key?.should == true
|
296
|
+
config.ocsp_cert.subject.to_s.should == "/C=US/ST=Illinois/L=Chicago/O=r509 LLC/CN=r509 OCSP Signer"
|
297
|
+
end
|
298
|
+
it "loads OCSP pkcs12 from yaml" do
|
299
|
+
config = R509::Config::CAConfig.from_yaml("ocsp_pkcs12_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
300
|
+
config.ocsp_cert.has_private_key?.should == true
|
301
|
+
config.ocsp_cert.subject.to_s.should == "/C=US/ST=Illinois/L=Chicago/O=r509 LLC/CN=r509 OCSP Signer"
|
302
|
+
end
|
303
|
+
it "loads OCSP cert/key in engine from yaml" do
|
304
|
+
#most of this code path is tested by loading ca_cert engine.
|
305
|
+
expect { R509::Config::CAConfig.from_yaml("ocsp_engine_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError,"You must supply a key_name with an engine")
|
306
|
+
end
|
307
|
+
it "loads OCSP chain from yaml" do
|
308
|
+
config = R509::Config::CAConfig.from_yaml("ocsp_chain_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
309
|
+
config.ocsp_chain.size.should == 2
|
310
|
+
config.ocsp_chain[0].kind_of?(OpenSSL::X509::Certificate).should == true
|
311
|
+
config.ocsp_chain[1].kind_of?(OpenSSL::X509::Certificate).should == true
|
312
|
+
end
|
313
|
+
it "should load subject_item_policy from yaml (if present)" do
|
314
|
+
config = R509::Config::CAConfig.from_yaml("test_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
315
|
+
config.profile("server").subject_item_policy.should be_nil
|
316
|
+
config.profile("server_with_subject_item_policy").subject_item_policy.optional.should include("O","OU")
|
317
|
+
config.profile("server_with_subject_item_policy").subject_item_policy.required.should include("CN","ST","C")
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should load YAML which only has a CA Cert and Key defined" do
|
321
|
+
config = R509::Config::CAConfig.from_yaml("test_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_minimal.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
322
|
+
config.num_profiles.should == 0
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should load YAML which has CA cert and key with password" do
|
326
|
+
expect { R509::Config::CAConfig.from_yaml("password_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_password.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to_not raise_error
|
327
|
+
end
|
328
|
+
|
329
|
+
it "should load YAML which has a PKCS12 with password" do
|
330
|
+
expect { R509::Config::CAConfig.from_yaml("pkcs12_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to_not raise_error
|
331
|
+
end
|
332
|
+
|
333
|
+
it "raises error on YAML with pkcs12 and key" do
|
334
|
+
expect { R509::Config::CAConfig.from_yaml("pkcs12_key_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError, "You can't specify both pkcs12 and key")
|
335
|
+
end
|
336
|
+
|
337
|
+
it "raises error on YAML with pkcs12 and cert" do
|
338
|
+
expect { R509::Config::CAConfig.from_yaml("pkcs12_cert_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError, "You can't specify both pkcs12 and cert")
|
339
|
+
end
|
340
|
+
|
341
|
+
it "raises error on YAML with pkcs12 and engine" do
|
342
|
+
expect { R509::Config::CAConfig.from_yaml("pkcs12_engine_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError, "You can't specify both engine and pkcs12")
|
343
|
+
end
|
344
|
+
|
345
|
+
it "loads config with cert and no key (useful in certain cases)" do
|
346
|
+
config = R509::Config::CAConfig.from_yaml("cert_no_key_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
347
|
+
config.ca_cert.subject.to_s.should_not be_nil
|
348
|
+
end
|
349
|
+
|
350
|
+
it "should load YAML which has an engine" do
|
351
|
+
fake_engine = double("fake_engine")
|
352
|
+
fake_engine.should_receive(:kind_of?).with(OpenSSL::Engine).and_return(true)
|
353
|
+
faux_key = OpenSSL::PKey::RSA.new(TestFixtures::TEST_CA_KEY)
|
354
|
+
fake_engine.should_receive(:load_private_key).twice.with("key").and_return(faux_key)
|
355
|
+
engine = {"SO_PATH" => "path", "ID" => "id"}
|
356
|
+
|
357
|
+
R509::Engine.instance.should_receive(:load).with(engine).and_return(fake_engine)
|
358
|
+
|
359
|
+
R509::Config::CAConfig.load_from_hash({"ca_cert"=>{"cert"=>"#{File.dirname(__FILE__)}/../fixtures/test_ca.cer", "engine"=>engine, "key_name" => "key"}, "default_md"=>"SHA512", "profiles"=>{}})
|
360
|
+
end
|
361
|
+
|
362
|
+
it "should fail if YAML for ca_cert contains engine and key" do
|
363
|
+
expect { R509::Config::CAConfig.from_yaml("engine_and_key", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_engine_key.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError, "You can't specify both key and engine")
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should fail if YAML for ca_cert contains engine but no key_name" do
|
367
|
+
expect { R509::Config::CAConfig.from_yaml("engine_no_key_name", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test_engine_no_key_name.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError, 'You must supply a key_name with an engine')
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should fail if YAML config is null" do
|
371
|
+
expect{ R509::Config::CAConfig.from_yaml("no_config_here", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError)
|
372
|
+
end
|
373
|
+
|
374
|
+
it "should fail if YAML config isn't a hash" do
|
375
|
+
expect{ R509::Config::CAConfig.from_yaml("config_is_string", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"}) }.to raise_error(ArgumentError)
|
376
|
+
end
|
377
|
+
|
378
|
+
it "should fail if YAML config doesn't give a root CA directory that's a directory" do
|
379
|
+
expect{ R509::Config::CAConfig.from_yaml("test_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures/no_directory_here"}) }.to raise_error(R509::R509Error)
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should load YAML from filename" do
|
383
|
+
config = R509::Config::CAConfig.load_yaml("test_ca", "#{File.dirname(__FILE__)}/../fixtures/config_test.yaml", {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
384
|
+
config.crl_validity_hours.should == 72
|
385
|
+
config.ocsp_validity_hours.should == 96
|
386
|
+
config.num_profiles.should == 9
|
387
|
+
end
|
388
|
+
|
389
|
+
it "can specify crl_number_file" do
|
390
|
+
config = R509::Config::CAConfig.new(
|
391
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
392
|
+
:crl_number_file => "crl_number_file.txt"
|
393
|
+
)
|
394
|
+
config.crl_number_file.should == 'crl_number_file.txt'
|
395
|
+
end
|
396
|
+
|
397
|
+
it "can specify crl_list_file" do
|
398
|
+
config = R509::Config::CAConfig.new(
|
399
|
+
:ca_cert => TestFixtures.test_ca_cert,
|
400
|
+
:crl_list_file => "crl_list_file.txt"
|
401
|
+
)
|
402
|
+
config.crl_list_file.should == 'crl_list_file.txt'
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r509/config/cert_profile'
|
3
|
+
require 'r509/config/ca_config'
|
4
|
+
require 'r509/exceptions'
|
5
|
+
|
6
|
+
describe R509::Config::CertProfile do
|
7
|
+
context "validates allowed_mds and default_md" do
|
8
|
+
it "loads allowed_mds and adds default_md when not present" do
|
9
|
+
profile = R509::Config::CertProfile.new(
|
10
|
+
:allowed_mds => ['sha256','sha1'],
|
11
|
+
:default_md => 'sha384'
|
12
|
+
)
|
13
|
+
profile.allowed_mds.should =~ ['SHA1','SHA256','SHA384']
|
14
|
+
end
|
15
|
+
|
16
|
+
it "loads allowed_mds without an explicit default_md" do
|
17
|
+
profile = R509::Config::CertProfile.new(
|
18
|
+
:allowed_mds => ['sha256','sha1']
|
19
|
+
)
|
20
|
+
profile.allowed_mds.should =~ ['SHA1','SHA256']
|
21
|
+
profile.default_md.should == R509::MessageDigest::DEFAULT_MD
|
22
|
+
end
|
23
|
+
|
24
|
+
it "loads allowed_mds with an explicit default_md" do
|
25
|
+
profile = R509::Config::CertProfile.new(
|
26
|
+
:allowed_mds => ['sha384','sha256'],
|
27
|
+
:default_md => "SHA256"
|
28
|
+
)
|
29
|
+
profile.allowed_mds.should =~ ['SHA384','SHA256']
|
30
|
+
profile.default_md.should == 'SHA256'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "loads default_md with no explicit allowed_mds" do
|
34
|
+
profile = R509::Config::CertProfile.new(
|
35
|
+
:default_md => "sha256"
|
36
|
+
)
|
37
|
+
profile.allowed_mds.should be_nil
|
38
|
+
profile.default_md.should == 'SHA256'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "errors when supplying invalid default_md" do
|
42
|
+
expect { R509::Config::CertProfile.new( :default_md => "notahash" ) }.to raise_error(ArgumentError, "An unknown message digest was supplied. Permitted: #{R509::MessageDigest::KNOWN_MDS.join(", ")}")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "errors when supplying invalid subject item policy" do
|
46
|
+
expect { R509::Config::CertProfile.new( :subject_item_policy => "notapolicy") }.to raise_error(ArgumentError, 'subject_item_policy must be of type R509::Config::SubjectItemPolicy')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
it "initializes with expected defaults" do
|
50
|
+
profile = R509::Config::CertProfile.new
|
51
|
+
profile.basic_constraints.should == nil
|
52
|
+
profile.key_usage.should == nil
|
53
|
+
profile.extended_key_usage.should == nil
|
54
|
+
profile.certificate_policies.should == nil
|
55
|
+
profile.inhibit_any_policy.should == nil
|
56
|
+
profile.policy_constraints.should == nil
|
57
|
+
profile.name_constraints.should == nil
|
58
|
+
profile.ocsp_no_check.should == nil
|
59
|
+
profile.authority_info_access.should == nil
|
60
|
+
profile.crl_distribution_points.should == nil
|
61
|
+
profile.allowed_mds.should == nil
|
62
|
+
profile.default_md.should == R509::MessageDigest::DEFAULT_MD
|
63
|
+
profile.subject_item_policy.should == nil
|
64
|
+
end
|
65
|
+
it "loads profiles from YAML while setting expected defaults" do
|
66
|
+
config = R509::Config::CAConfig.from_yaml("test_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
67
|
+
server_profile = config.profile("server") # no ocsp_no_check node
|
68
|
+
server_profile.ocsp_no_check.should == nil
|
69
|
+
ocsp_profile = config.profile("ocsp_delegate_with_no_check") # ocsp_no_check => true
|
70
|
+
ocsp_profile.ocsp_no_check.should_not == nil
|
71
|
+
client_profile = config.profile("client") # ocsp_no_check => false
|
72
|
+
client_profile.ocsp_no_check.should == nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it "builds YAML" do
|
76
|
+
config = R509::Config::CAConfig.from_yaml("test_ca", File.read("#{File.dirname(__FILE__)}/../fixtures/config_test.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/../fixtures"})
|
77
|
+
YAML.load(config.profile("server").to_yaml).should == {"basic_constraints"=>{:ca=>false, :critical=>true}, "key_usage"=>{:value=>["digitalSignature", "keyEncipherment"], :critical=>false}, "extended_key_usage"=>{:value=>["serverAuth"], :critical=>false}, "default_md"=>R509::MessageDigest::DEFAULT_MD}
|
78
|
+
end
|
79
|
+
|
80
|
+
it "includes crl distribution points in the yaml" do
|
81
|
+
config = R509::Config::CertProfile.new(
|
82
|
+
:crl_distribution_points => R509::Cert::Extensions::CRLDistributionPoints.new(
|
83
|
+
:value => [{:type => 'URI', :value => 'http://crl.myca.net/ca.crl'}]
|
84
|
+
)
|
85
|
+
)
|
86
|
+
YAML.load(config.to_yaml).should == {"crl_distribution_points"=>{:critical=>false, :value=>[{:type=>"URI", :value=>"http://crl.myca.net/ca.crl"}]}, "default_md"=>"SHA1"}
|
87
|
+
end
|
88
|
+
end
|