rkerberos 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +59 -0
- data/MANIFEST.md +24 -0
- data/README.md +55 -3
- data/Rakefile +35 -0
- data/ext/rkerberos/ccache.c +103 -9
- data/ext/rkerberos/config.c +4 -4
- data/ext/rkerberos/context.c +63 -8
- data/ext/rkerberos/kadm5.c +79 -65
- data/ext/rkerberos/keytab.c +237 -106
- data/ext/rkerberos/policy.c +1 -1
- data/ext/rkerberos/rkerberos.c +264 -8
- data/ext/rkerberos/rkerberos.h +2 -0
- data/rkerberos.gemspec +16 -7
- data/spec/config_spec.rb +4 -4
- data/spec/context_spec.rb +36 -0
- data/spec/credentials_cache_spec.rb +53 -0
- data/spec/kadm5_spec.rb +40 -1
- data/spec/krb5_keytab_spec.rb +195 -0
- data/spec/krb5_spec.rb +177 -1
- metadata +16 -27
- data/CHANGES +0 -34
- data/Dockerfile +0 -42
- data/MANIFEST +0 -16
- data/docker/Dockerfile.kdc +0 -16
- data/docker/docker-entrypoint.sh +0 -23
- data/docker/kadm5.acl +0 -1
- data/docker/kdc.conf +0 -13
- data/docker/krb5.conf +0 -14
- data/docker-compose.yml +0 -44
data/spec/krb5_keytab_spec.rb
CHANGED
|
@@ -29,6 +29,10 @@ RSpec.describe Kerberos::Krb5::Keytab do
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
after(:all) do
|
|
33
|
+
FileUtils.rm_f(@keytab_file)
|
|
34
|
+
end
|
|
35
|
+
|
|
32
36
|
subject(:keytab) { described_class.new }
|
|
33
37
|
|
|
34
38
|
describe 'constructor' do
|
|
@@ -43,4 +47,195 @@ RSpec.describe Kerberos::Krb5::Keytab do
|
|
|
43
47
|
}.to raise_error(Kerberos::Krb5::Keytab::Exception)
|
|
44
48
|
end
|
|
45
49
|
end
|
|
50
|
+
|
|
51
|
+
describe '#keytab_name and #keytab_type' do
|
|
52
|
+
it 'returns the underlying name and type strings' do
|
|
53
|
+
kt = described_class.new(@keytab_name)
|
|
54
|
+
expect(kt).to respond_to(:keytab_name)
|
|
55
|
+
expect(kt).to respond_to(:keytab_type)
|
|
56
|
+
|
|
57
|
+
expect(kt.keytab_name).to be_a(String)
|
|
58
|
+
expect(kt.keytab_type).to be_a(String)
|
|
59
|
+
|
|
60
|
+
# name should include the residual portion we supplied
|
|
61
|
+
expect(kt.keytab_name).to include(File.basename(@keytab_file))
|
|
62
|
+
# type should match the scheme
|
|
63
|
+
expect(kt.keytab_type.downcase).to eq("file")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '#close' do
|
|
68
|
+
it 'returns true' do
|
|
69
|
+
kt = described_class.new(@keytab_name)
|
|
70
|
+
expect(kt.close).to eq(true)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'can be called multiple times without error' do
|
|
74
|
+
kt = described_class.new(@keytab_name)
|
|
75
|
+
kt.close
|
|
76
|
+
expect { kt.close }.not_to raise_error
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'raises an error when calling keytab_name after close' do
|
|
80
|
+
kt = described_class.new(@keytab_name)
|
|
81
|
+
kt.close
|
|
82
|
+
expect { kt.keytab_name }.to raise_error(Kerberos::Krb5::Exception)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'raises an error when calling keytab_type after close' do
|
|
86
|
+
kt = described_class.new(@keytab_name)
|
|
87
|
+
kt.close
|
|
88
|
+
expect { kt.keytab_type }.to raise_error(Kerberos::Krb5::Exception)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'does not segfault when garbage collected after close' do
|
|
92
|
+
kt = described_class.new(@keytab_name)
|
|
93
|
+
kt.close
|
|
94
|
+
kt = nil
|
|
95
|
+
GC.start
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe '.foreach' do
|
|
100
|
+
it 'yields keytab entries for a valid keytab' do
|
|
101
|
+
entries = []
|
|
102
|
+
described_class.foreach(@keytab_name) { |entry| entries << entry }
|
|
103
|
+
expect(entries.length).to eq(2)
|
|
104
|
+
entries.each do |entry|
|
|
105
|
+
expect(entry).to be_a(Kerberos::Krb5::Keytab::Entry)
|
|
106
|
+
expect(entry.principal).to be_a(String)
|
|
107
|
+
expect(entry.principal).to match(/@#{Regexp.quote(@realm)}$/)
|
|
108
|
+
expect(entry.vno).to be_a(Integer)
|
|
109
|
+
expect(entry.timestamp).to be_a(Time)
|
|
110
|
+
expect(entry.key).to be_a(Integer)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'uses the default keytab when no name is provided' do
|
|
115
|
+
# The default keytab may not exist in the test container, so we
|
|
116
|
+
# just verify it attempts to use it (raises keytab-related error
|
|
117
|
+
# rather than ArgumentError or similar).
|
|
118
|
+
begin
|
|
119
|
+
described_class.foreach { |_| }
|
|
120
|
+
rescue Kerberos::Krb5::Exception
|
|
121
|
+
# Expected when default keytab is absent
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'raises an error for a non-existent keytab file' do
|
|
126
|
+
expect {
|
|
127
|
+
described_class.foreach("FILE:/no/such/keytab") { |_| }
|
|
128
|
+
}.to raise_error(Kerberos::Krb5::Exception)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'raises an error for an invalid keytab type' do
|
|
132
|
+
expect {
|
|
133
|
+
described_class.foreach("BOGUS:/tmp/keytab") { |_| }
|
|
134
|
+
}.to raise_error(Kerberos::Krb5::Exception)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'does not leak resources when the block raises' do
|
|
138
|
+
expect {
|
|
139
|
+
described_class.foreach(@keytab_name) { |_| raise "boom" }
|
|
140
|
+
}.to raise_error(RuntimeError, "boom")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'does not leak resources when the block breaks' do
|
|
144
|
+
result = catch(:done) do
|
|
145
|
+
described_class.foreach(@keytab_name) { |_| throw :done, :escaped }
|
|
146
|
+
:completed
|
|
147
|
+
end
|
|
148
|
+
expect(result).to eq(:escaped)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe '#each' do
|
|
153
|
+
it 'yields keytab entries for a valid keytab' do
|
|
154
|
+
kt = described_class.new(@keytab_name)
|
|
155
|
+
entries = []
|
|
156
|
+
kt.each { |entry| entries << entry }
|
|
157
|
+
expect(entries.length).to eq(2)
|
|
158
|
+
entries.each do |entry|
|
|
159
|
+
expect(entry).to be_a(Kerberos::Krb5::Keytab::Entry)
|
|
160
|
+
expect(entry.principal).to be_a(String)
|
|
161
|
+
expect(entry.vno).to be_a(Integer)
|
|
162
|
+
expect(entry.timestamp).to be_a(Time)
|
|
163
|
+
expect(entry.key).to be_a(Integer)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it 'does not leak resources when the block raises' do
|
|
168
|
+
kt = described_class.new(@keytab_name)
|
|
169
|
+
expect {
|
|
170
|
+
kt.each { |_| raise "boom" }
|
|
171
|
+
}.to raise_error(RuntimeError, "boom")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'does not leak resources when the block breaks' do
|
|
175
|
+
kt = described_class.new(@keytab_name)
|
|
176
|
+
result = catch(:done) do
|
|
177
|
+
kt.each { |_| throw :done, :escaped }
|
|
178
|
+
:completed
|
|
179
|
+
end
|
|
180
|
+
expect(result).to eq(:escaped)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe '#get_entry' do
|
|
185
|
+
it 'finds an entry by principal name' do
|
|
186
|
+
kt = described_class.new(@keytab_name)
|
|
187
|
+
entry = kt.get_entry("testuser1@#{@realm}")
|
|
188
|
+
expect(entry).to be_a(Kerberos::Krb5::Keytab::Entry)
|
|
189
|
+
expect(entry.principal).to eq("testuser1@#{@realm}")
|
|
190
|
+
expect(entry.vno).to eq(1)
|
|
191
|
+
expect(entry.timestamp).to be_a(Time)
|
|
192
|
+
expect(entry.key).to be_a(Integer)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'finds an entry filtering by vno' do
|
|
196
|
+
kt = described_class.new(@keytab_name)
|
|
197
|
+
entry = kt.get_entry("testuser1@#{@realm}", 1)
|
|
198
|
+
expect(entry.principal).to eq("testuser1@#{@realm}")
|
|
199
|
+
expect(entry.vno).to eq(1)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'finds an entry filtering by vno and enctype' do
|
|
203
|
+
kt = described_class.new(@keytab_name)
|
|
204
|
+
# aes128-cts-hmac-sha1-96 is enctype 17
|
|
205
|
+
entry = kt.get_entry("testuser1@#{@realm}", 1, 17)
|
|
206
|
+
expect(entry.principal).to eq("testuser1@#{@realm}")
|
|
207
|
+
expect(entry.vno).to eq(1)
|
|
208
|
+
expect(entry.key).to eq(17)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'raises an error for a non-existent principal' do
|
|
212
|
+
kt = described_class.new(@keytab_name)
|
|
213
|
+
expect {
|
|
214
|
+
kt.get_entry("bogus@#{@realm}")
|
|
215
|
+
}.to raise_error(Kerberos::Krb5::Exception)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it 'is aliased as find' do
|
|
219
|
+
kt = described_class.new(@keytab_name)
|
|
220
|
+
expect(kt.method(:find)).to eq(kt.method(:get_entry))
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe '#dup' do
|
|
225
|
+
it 'creates an independent handle referring to same keytab' do
|
|
226
|
+
kt1 = described_class.new(@keytab_name)
|
|
227
|
+
kt2 = kt1.dup
|
|
228
|
+
expect(kt2).to be_a(described_class)
|
|
229
|
+
expect(kt2.keytab_name).to eq(kt1.keytab_name)
|
|
230
|
+
|
|
231
|
+
# closing one should not invalidate the other
|
|
232
|
+
kt1.close
|
|
233
|
+
expect { kt2.keytab_name }.not_to raise_error
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it 'clone is an alias for dup' do
|
|
237
|
+
kt = described_class.new(@keytab_name)
|
|
238
|
+
expect(kt.method(:clone)).to eq(kt.method(:dup))
|
|
239
|
+
end
|
|
240
|
+
end
|
|
46
241
|
end
|
data/spec/krb5_spec.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
require 'rkerberos'
|
|
5
5
|
require 'open3'
|
|
6
|
+
require 'pty'
|
|
7
|
+
require 'expect'
|
|
6
8
|
|
|
7
9
|
RSpec.describe Kerberos::Krb5 do
|
|
8
10
|
before(:all) do
|
|
@@ -10,6 +12,7 @@ RSpec.describe Kerberos::Krb5 do
|
|
|
10
12
|
Open3.popen3('klist') { |_, _, stderr| @cache_found = false unless stderr.gets.nil? }
|
|
11
13
|
@krb5_conf = ENV['KRB5_CONFIG'] || '/etc/krb5.conf'
|
|
12
14
|
@realm = IO.read(@krb5_conf).split("\n").grep(/default_realm/).first.split('=').last.lstrip.chomp
|
|
15
|
+
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
subject(:krb5) { described_class.new }
|
|
@@ -18,7 +21,7 @@ RSpec.describe Kerberos::Krb5 do
|
|
|
18
21
|
let(:service) { 'kadmin/admin' }
|
|
19
22
|
|
|
20
23
|
it 'has the correct version constant' do
|
|
21
|
-
expect(Kerberos::Krb5::VERSION).to eq('0.2.
|
|
24
|
+
expect(Kerberos::Krb5::VERSION).to eq('0.2.2')
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
it 'accepts a block and yields itself' do
|
|
@@ -44,4 +47,177 @@ RSpec.describe Kerberos::Krb5 do
|
|
|
44
47
|
expect(krb5.method(:default_realm)).to eq(krb5.method(:get_default_realm))
|
|
45
48
|
end
|
|
46
49
|
end
|
|
50
|
+
|
|
51
|
+
describe '#verify_init_creds' do
|
|
52
|
+
# Some KDC setups may not correctly set the initial password during
|
|
53
|
+
# entrypoint startup; enforce it here via the admin API so the test is
|
|
54
|
+
# deterministic.
|
|
55
|
+
before do
|
|
56
|
+
user = "testuser1@#{@realm}"
|
|
57
|
+
Kerberos::Kadm5.new(
|
|
58
|
+
principal: ENV.fetch('KRB5_ADMIN_PRINCIPAL', 'admin/admin@EXAMPLE.COM'),
|
|
59
|
+
password: ENV.fetch('KRB5_ADMIN_PASSWORD', 'adminpassword')
|
|
60
|
+
) do |kadmin|
|
|
61
|
+
kadmin.set_password(user, 'changeme')
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'responds to verify_init_creds' do
|
|
66
|
+
expect(krb5).to respond_to(:verify_init_creds)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'raises when no credentials have been acquired' do
|
|
70
|
+
expect { krb5.verify_init_creds }.to raise_error(Kerberos::Krb5::Exception)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'validates argument types' do
|
|
74
|
+
expect { krb5.verify_init_creds(true) }.to raise_error(TypeError)
|
|
75
|
+
expect { krb5.verify_init_creds(nil, true) }.to raise_error(TypeError)
|
|
76
|
+
expect { krb5.verify_init_creds(nil, nil, true) }.to raise_error(TypeError)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'verifies credentials obtained via password' do
|
|
80
|
+
krb5.get_init_creds_password(user, 'changeme')
|
|
81
|
+
expect(krb5.verify_init_creds).to be true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'accepts a server principal string' do
|
|
85
|
+
krb5.get_init_creds_password(user, 'changeme')
|
|
86
|
+
expect(krb5.verify_init_creds("kadmin/admin@#{@realm}")).to be true
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'accepts a Keytab object' do
|
|
90
|
+
krb5.get_init_creds_password(user, 'changeme')
|
|
91
|
+
kt = Kerberos::Krb5::Keytab.new
|
|
92
|
+
expect(krb5.verify_init_creds(nil, kt)).to be true
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'stores additional credentials in provided CredentialsCache' do
|
|
96
|
+
ccache = Kerberos::Krb5::CredentialsCache.new
|
|
97
|
+
krb5.get_init_creds_password(user, 'changeme')
|
|
98
|
+
expect(krb5.verify_init_creds(nil, nil, ccache)).to be true
|
|
99
|
+
expect(ccache.primary_principal).to be_a(String)
|
|
100
|
+
expect(ccache.primary_principal).to include('@')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'provides authenticate! which acquires and verifies (Zanarotti mitigation)' do
|
|
104
|
+
expect(krb5).to respond_to(:authenticate!)
|
|
105
|
+
expect(krb5.authenticate!(user, 'changeme')).to be true
|
|
106
|
+
expect(krb5.verify_init_creds).to be true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'accepts an optional service argument' do
|
|
110
|
+
expect { krb5.authenticate!(user, 'changeme', 'kadmin/changepw') }.not_to raise_error
|
|
111
|
+
expect(krb5.verify_init_creds).to be true
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'validates argument types for authenticate!' do
|
|
115
|
+
expect { krb5.authenticate!(true, true) }.to raise_error(TypeError)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe '#change_password' do
|
|
120
|
+
before do
|
|
121
|
+
# Ensure testuser1 has a known password before each test.
|
|
122
|
+
Kerberos::Kadm5.new(
|
|
123
|
+
principal: ENV.fetch('KRB5_ADMIN_PRINCIPAL', 'admin/admin@EXAMPLE.COM'),
|
|
124
|
+
password: ENV.fetch('KRB5_ADMIN_PASSWORD', 'adminpassword')
|
|
125
|
+
) do |kadmin|
|
|
126
|
+
kadmin.set_password(user, 'changeme')
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
after do
|
|
131
|
+
# Reset to known password so later tests are not affected.
|
|
132
|
+
Kerberos::Kadm5.new(
|
|
133
|
+
principal: ENV.fetch('KRB5_ADMIN_PRINCIPAL', 'admin/admin@EXAMPLE.COM'),
|
|
134
|
+
password: ENV.fetch('KRB5_ADMIN_PASSWORD', 'adminpassword')
|
|
135
|
+
) do |kadmin|
|
|
136
|
+
kadmin.set_password(user, 'changeme')
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'responds to change_password' do
|
|
141
|
+
expect(krb5).to respond_to(:change_password)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'requires exactly two arguments' do
|
|
145
|
+
expect { krb5.change_password }.to raise_error(ArgumentError)
|
|
146
|
+
expect { krb5.change_password('old') }.to raise_error(ArgumentError)
|
|
147
|
+
expect { krb5.change_password('old', 'new', 'extra') }.to raise_error(ArgumentError)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'raises if no principal has been established' do
|
|
151
|
+
expect { krb5.change_password('changeme', 'newpass1A!') }.to raise_error(Kerberos::Krb5::Exception, /no principal/)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'changes the password successfully' do
|
|
155
|
+
krb5.get_init_creds_password(user, 'changeme')
|
|
156
|
+
expect(krb5.change_password('changeme', 'Newpass99!')).to be true
|
|
157
|
+
# Verify we can authenticate with the new password
|
|
158
|
+
krb5_check = described_class.new
|
|
159
|
+
expect(krb5_check.get_init_creds_password(user, 'Newpass99!')).to be true
|
|
160
|
+
krb5_check.close
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'raises with a meaningful message when the old password is wrong' do
|
|
164
|
+
krb5.get_init_creds_password(user, 'changeme')
|
|
165
|
+
expect {
|
|
166
|
+
krb5.change_password('wrongpass', 'Newpass99!')
|
|
167
|
+
}.to raise_error(Kerberos::Krb5::Exception, /krb5_(get_init_creds_password|change_password)/)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'requires string arguments' do
|
|
171
|
+
expect { krb5.change_password(1, 'new') }.to raise_error(TypeError)
|
|
172
|
+
expect { krb5.change_password('old', 1) }.to raise_error(TypeError)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context 'when the KDC rejects the new password due to policy' do
|
|
176
|
+
let(:policy_user) { "policyuser@#{@realm}" }
|
|
177
|
+
# Password must satisfy strict_policy (minlength=8, minclasses=3).
|
|
178
|
+
let(:compliant_pw) { 'Changeme1!' }
|
|
179
|
+
|
|
180
|
+
it 'raises an exception with the KDC rejection reason' do
|
|
181
|
+
krb5.get_init_creds_password(policy_user, compliant_pw)
|
|
182
|
+
expect {
|
|
183
|
+
krb5.change_password(compliant_pw, 'a')
|
|
184
|
+
}.to raise_error(Kerberos::Krb5::Exception, /krb5_change_password/)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
describe '#get_init_creds_keytab' do
|
|
190
|
+
before(:each) do
|
|
191
|
+
@kt_file = File.join(Dir.tmpdir, "test_get_init_creds_#{Process.pid}_#{rand(10000)}.keytab")
|
|
192
|
+
|
|
193
|
+
PTY.spawn('ktutil') do |reader, writer, _|
|
|
194
|
+
reader.expect(/ktutil:\s+/)
|
|
195
|
+
writer.puts("add_entry -password -p testuser1@#{@realm} -k 1 -e aes128-cts-hmac-sha1-96")
|
|
196
|
+
reader.expect(/Password for #{Regexp.quote("testuser1@#{@realm}")}:\s+/)
|
|
197
|
+
writer.puts('changeme')
|
|
198
|
+
reader.expect(/ktutil:\s+/)
|
|
199
|
+
writer.puts("wkt #{@kt_file}")
|
|
200
|
+
reader.expect(/ktutil:\s+/)
|
|
201
|
+
writer.puts('quit')
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it 'responds to get_init_creds_keytab' do
|
|
206
|
+
expect(krb5).to respond_to(:get_init_creds_keytab)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'acquires credentials for a principal from a supplied keytab file' do
|
|
210
|
+
kt_name = "FILE:#{@kt_file}"
|
|
211
|
+
expect { krb5.get_init_creds_keytab(user, kt_name) }.not_to raise_error
|
|
212
|
+
expect(krb5.verify_init_creds).to be true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'accepts a CredentialsCache to receive credentials' do
|
|
216
|
+
ccache = Kerberos::Krb5::CredentialsCache.new
|
|
217
|
+
kt_name = "FILE:#{@kt_file}"
|
|
218
|
+
expect { krb5.get_init_creds_keytab(user, kt_name, nil, ccache) }.not_to raise_error
|
|
219
|
+
expect(ccache.primary_principal).to be_a(String)
|
|
220
|
+
expect(ccache.primary_principal).to include('@')
|
|
221
|
+
end
|
|
222
|
+
end
|
|
47
223
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rkerberos
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Berger
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
- - ">="
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
20
|
version: '0'
|
|
21
|
-
type: :
|
|
21
|
+
type: :development
|
|
22
22
|
prerelease: false
|
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
24
|
requirements:
|
|
@@ -63,34 +63,14 @@ email:
|
|
|
63
63
|
executables: []
|
|
64
64
|
extensions:
|
|
65
65
|
- ext/rkerberos/extconf.rb
|
|
66
|
-
extra_rdoc_files:
|
|
67
|
-
- CHANGES
|
|
68
|
-
- LICENSE
|
|
69
|
-
- MANIFEST
|
|
70
|
-
- README.md
|
|
71
|
-
- ext/rkerberos/ccache.c
|
|
72
|
-
- ext/rkerberos/config.c
|
|
73
|
-
- ext/rkerberos/context.c
|
|
74
|
-
- ext/rkerberos/kadm5.c
|
|
75
|
-
- ext/rkerberos/keytab.c
|
|
76
|
-
- ext/rkerberos/keytab_entry.c
|
|
77
|
-
- ext/rkerberos/policy.c
|
|
78
|
-
- ext/rkerberos/principal.c
|
|
79
|
-
- ext/rkerberos/rkerberos.c
|
|
66
|
+
extra_rdoc_files: []
|
|
80
67
|
files:
|
|
81
|
-
- CHANGES
|
|
82
|
-
- Dockerfile
|
|
68
|
+
- CHANGES.md
|
|
83
69
|
- Gemfile
|
|
84
70
|
- LICENSE
|
|
85
|
-
- MANIFEST
|
|
71
|
+
- MANIFEST.md
|
|
86
72
|
- README.md
|
|
87
73
|
- Rakefile
|
|
88
|
-
- docker-compose.yml
|
|
89
|
-
- docker/Dockerfile.kdc
|
|
90
|
-
- docker/docker-entrypoint.sh
|
|
91
|
-
- docker/kadm5.acl
|
|
92
|
-
- docker/kdc.conf
|
|
93
|
-
- docker/krb5.conf
|
|
94
74
|
- ext/rkerberos/ccache.c
|
|
95
75
|
- ext/rkerberos/config.c
|
|
96
76
|
- ext/rkerberos/context.c
|
|
@@ -112,10 +92,19 @@ files:
|
|
|
112
92
|
- spec/krb5_spec.rb
|
|
113
93
|
- spec/policy_spec.rb
|
|
114
94
|
- spec/principal_spec.rb
|
|
115
|
-
homepage: http://github.com/
|
|
95
|
+
homepage: http://github.com/rkerberos/rkerberos
|
|
116
96
|
licenses:
|
|
117
97
|
- Artistic-2.0
|
|
118
|
-
metadata:
|
|
98
|
+
metadata:
|
|
99
|
+
homepage_uri: https://github.com/rkerberos/rkerberos
|
|
100
|
+
bug_tracker_uri: https://github.com/rkerberos/rkerberos/issues
|
|
101
|
+
changelog_uri: https://github.com/rkerberos/rkerberos/blob/main/CHANGES.md
|
|
102
|
+
documentation_uri: https://github.com/rkerberos/rkerberos/wiki
|
|
103
|
+
source_code_uri: https://github.com/rkerberos/rkerberos
|
|
104
|
+
wiki_uri: https://github.com/rkerberos/rkerberos/wiki
|
|
105
|
+
github_repo: https://github.com/djberg96/rkerberos
|
|
106
|
+
funding_uri: https://github.com/sponsors/rkerberos
|
|
107
|
+
rubygems_mfa_required: 'true'
|
|
119
108
|
rdoc_options: []
|
|
120
109
|
require_paths:
|
|
121
110
|
- lib
|
data/CHANGES
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
= 0.2.0 - 14-Feb-2026
|
|
2
|
-
* Added Docker and Podman support for running tests in isolated environments with Kerberos and OpenLDAP services.
|
|
3
|
-
* Updated documentation with modern testing and development workflows, including container-based instructions.
|
|
4
|
-
* Improved compatibility for Ruby 3.4 and later.
|
|
5
|
-
* Enhanced build and test automation using docker-compose and podman-compose.
|
|
6
|
-
* Various bug fixes, code cleanups, and test improvements.
|
|
7
|
-
|
|
8
|
-
= 0.1.5 - 17-Oct-2016
|
|
9
|
-
* Fix build error on Ruby 2.0.0/2.1 with CFLAGS concatenation
|
|
10
|
-
|
|
11
|
-
= 0.1.4 - 14-Oct-2016
|
|
12
|
-
* Implement db_args functionality in kadmin (fixes #8)
|
|
13
|
-
* Fix a double-free error when setting the realm for a principal
|
|
14
|
-
* Fix an error in policy creation that would sometimes cause a communication failure
|
|
15
|
-
* Set C99 as the C Standard and fix all compiler warnings at this level
|
|
16
|
-
|
|
17
|
-
= 0.1.3 - 07-Sep-2013
|
|
18
|
-
* Add optional 'service' argument to get_init_creds_password (fixes #3)
|
|
19
|
-
* Artistic License 2.0 text now included (fixes #2)
|
|
20
|
-
|
|
21
|
-
= 0.1.2 - 24-Jun-2013
|
|
22
|
-
* Fix kadm5clnt build issue on EL6
|
|
23
|
-
* Remove admin_keytab references for krb5 1.11
|
|
24
|
-
* Add Gemfile
|
|
25
|
-
* Replace deprecated Config with RbConfig (Ruby 2)
|
|
26
|
-
|
|
27
|
-
= 0.1.1 - 08-May-2013
|
|
28
|
-
* Add credential cache argument to get_init_creds_keytab
|
|
29
|
-
* Fixed invalid VALUE declarations affecting non-gcc compilers
|
|
30
|
-
* Add OS X install instructions
|
|
31
|
-
|
|
32
|
-
= 0.1.0 - 28-Apr-2011
|
|
33
|
-
* Initial release. This is effectively a re-release of my own custom branch
|
|
34
|
-
of the krb5-auth library, with some minor changes.
|
data/Dockerfile
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# Dockerfile for rkerberos Ruby gem testing
|
|
2
|
-
FROM ruby:3.4
|
|
3
|
-
|
|
4
|
-
# Install MIT Kerberos, KDC, admin server, and build tools
|
|
5
|
-
RUN apt-get update && \
|
|
6
|
-
apt-get install -y --no-install-recommends \
|
|
7
|
-
libkrb5-dev krb5-user krb5-kdc krb5-admin-server rake build-essential && \
|
|
8
|
-
rm -rf /var/lib/apt/lists/*
|
|
9
|
-
|
|
10
|
-
# Set up a working directory
|
|
11
|
-
WORKDIR /app
|
|
12
|
-
|
|
13
|
-
# Set admin credentials for tests (matches docker-compose.yml)
|
|
14
|
-
ENV KRB5_ADMIN_PRINCIPAL=admin/admin@EXAMPLE.COM
|
|
15
|
-
ENV KRB5_ADMIN_PASSWORD=adminpassword
|
|
16
|
-
|
|
17
|
-
# Copy the gemspec and Gemfile for dependency installation
|
|
18
|
-
COPY Gemfile rkerberos.gemspec ./
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# Install gem dependencies and RSpec
|
|
22
|
-
RUN bundle install && gem install rspec
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Create a more complete krb5.conf for testing (with kadmin support)
|
|
26
|
-
RUN echo "[libdefaults]\n default_realm = EXAMPLE.COM\n dns_lookup_realm = false\n dns_lookup_kdc = false\n ticket_lifetime = 24h\n renew_lifetime = 7d\n forwardable = true\n[realms]\n EXAMPLE.COM = {\n kdc = kerberos-kdc\n admin_server = kerberos-kdc\n default_domain = example.com\n }\n[domain_realm]\n .example.com = EXAMPLE.COM\n example.com = EXAMPLE.COM\n[kadmin]\n default_keys = des-cbc-crc:normal des-cbc-md5:normal aes256-cts:normal aes128-cts:normal rc4-hmac:normal\n admin_server = kerberos-kdc\n" > /etc/krb5.conf
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# Create a minimal KDC and admin server config, and a permissive ACL for kadmin
|
|
30
|
-
RUN mkdir -p /etc/krb5kdc && \
|
|
31
|
-
echo "[kdcdefaults]\n kdc_ports = 88\n[kdc]\n profile = /etc/krb5.conf\n" > /etc/krb5kdc/kdc.conf && \
|
|
32
|
-
echo "admin/admin@EXAMPLE.COM *" > /etc/krb5kdc/kadm5.acl
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# Copy the rest of the code
|
|
36
|
-
COPY . .
|
|
37
|
-
|
|
38
|
-
# Compile the C extension
|
|
39
|
-
RUN rake compile
|
|
40
|
-
|
|
41
|
-
# Run RSpec tests
|
|
42
|
-
CMD ["bundle", "exec", "rspec"]
|
data/MANIFEST
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
CHANGES
|
|
2
|
-
rkerberos.gemspec
|
|
3
|
-
MANIFEST
|
|
4
|
-
Rakefile
|
|
5
|
-
README
|
|
6
|
-
ext/ccache.c
|
|
7
|
-
ext/context.c
|
|
8
|
-
ext/extconf.rb
|
|
9
|
-
ext/kadm5.c
|
|
10
|
-
ext/keytab.c
|
|
11
|
-
ext/keytab_entry.c
|
|
12
|
-
ext/rkerberos.c
|
|
13
|
-
ext/rkerberos.h
|
|
14
|
-
ext/policy.c
|
|
15
|
-
ext/principal.c
|
|
16
|
-
test/test_krb5.rb
|
data/docker/Dockerfile.kdc
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
FROM debian:bullseye
|
|
2
|
-
|
|
3
|
-
RUN apt-get update && \
|
|
4
|
-
apt-get install -y krb5-kdc krb5-admin-server krb5-user krb5-kdc-ldap ldap-utils expect && \
|
|
5
|
-
rm -rf /var/lib/apt/lists/*
|
|
6
|
-
|
|
7
|
-
# Copy configuration files
|
|
8
|
-
COPY krb5.conf /etc/krb5.conf
|
|
9
|
-
COPY kdc.conf /etc/krb5kdc/kdc.conf
|
|
10
|
-
COPY kadm5.acl /etc/krb5kdc/kadm5.acl
|
|
11
|
-
|
|
12
|
-
# Copy entrypoint
|
|
13
|
-
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
|
14
|
-
RUN chmod +x /docker-entrypoint.sh
|
|
15
|
-
|
|
16
|
-
ENTRYPOINT ["/docker-entrypoint.sh"]
|
data/docker/docker-entrypoint.sh
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -e
|
|
3
|
-
|
|
4
|
-
# Initialize KDC DB if not already present
|
|
5
|
-
if [ ! -f /etc/krb5kdc/.k5.EXAMPLE.COM ]; then
|
|
6
|
-
printf "masterpassword\nmasterpassword\n" | krb5_newrealm
|
|
7
|
-
kadmin.local -q "addprinc -pw adminpassword admin/admin"
|
|
8
|
-
fi
|
|
9
|
-
|
|
10
|
-
# Create standard test principals for keytab/credential cache tests
|
|
11
|
-
kadmin.local -q "addprinc -pw changeme testuser1@EXAMPLE.COM"
|
|
12
|
-
kadmin.local -q "addprinc -pw changeme zztop@EXAMPLE.COM"
|
|
13
|
-
kadmin.local -q "addprinc -pw changeme martymcfly@EXAMPLE.COM"
|
|
14
|
-
kadmin.local -q "ktadd -k /etc/krb5.keytab testuser1@EXAMPLE.COM"
|
|
15
|
-
kadmin.local -q "ktadd -k /etc/krb5.keytab zztop@EXAMPLE.COM"
|
|
16
|
-
kadmin.local -q "ktadd -k /etc/krb5.keytab martymcfly@EXAMPLE.COM"
|
|
17
|
-
|
|
18
|
-
# Start KDC and admin server
|
|
19
|
-
krb5kdc
|
|
20
|
-
kadmind
|
|
21
|
-
|
|
22
|
-
# Keep container running
|
|
23
|
-
trap : TERM INT; sleep infinity & wait
|
data/docker/kadm5.acl
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
admin/admin@EXAMPLE.COM *
|
data/docker/kdc.conf
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
[kdcdefaults]
|
|
2
|
-
kdc_ports = 88
|
|
3
|
-
|
|
4
|
-
[realms]
|
|
5
|
-
EXAMPLE.COM = {
|
|
6
|
-
admin_keytab = /etc/krb5kdc/kadm5.keytab
|
|
7
|
-
acl_file = /etc/krb5kdc/kadm5.acl
|
|
8
|
-
dict_file = /usr/share/dict/words
|
|
9
|
-
key_stash_file = /etc/krb5kdc/.k5.EXAMPLE.COM
|
|
10
|
-
kdc_ports = 88
|
|
11
|
-
max_life = 10h 0m 0s
|
|
12
|
-
max_renewable_life = 7d 0h 0m 0s
|
|
13
|
-
}
|
data/docker/krb5.conf
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
[libdefaults]
|
|
2
|
-
default_realm = EXAMPLE.COM
|
|
3
|
-
dns_lookup_realm = false
|
|
4
|
-
dns_lookup_kdc = false
|
|
5
|
-
|
|
6
|
-
[realms]
|
|
7
|
-
EXAMPLE.COM = {
|
|
8
|
-
kdc = kerberos-kdc
|
|
9
|
-
admin_server = kerberos-kdc
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
[domain_realm]
|
|
13
|
-
.example.com = EXAMPLE.COM
|
|
14
|
-
example.com = EXAMPLE.COM
|