lex-kerberos 0.1.2 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69c3dd5c8ef68a25cc39f06b412e3b9f07854e02643ef44bf2f1082965c72d62
4
- data.tar.gz: 0d1b20b4dfc12d31e21a9a00c14be7f76f15ece54a2d8fdb3fcc9703ee76cc46
3
+ metadata.gz: 3f1d192f07e0352efa5eac1726291cab685501a0ef58d3ec63977ac9e803e607
4
+ data.tar.gz: e7c528d4073e5d21ba399799323784a079b3574054c71db6df756c55c940b3e3
5
5
  SHA512:
6
- metadata.gz: c7663b961a7468ccb52e6133b9d12ab57cb47c086cfe2f6264f3a35f3697340a5725415aeb5d115838d44bb0195b4d8e5cb25ef05b681a3680561d57734ffcae
7
- data.tar.gz: 27de46aa7005ba6d43a57b0460f2436fecf15a4851a0cccc6f5198efbd82c906d4b9b17f37c8d571a538ba4514ff594a5d5bca614c518050bf735bcd1dca00fb
6
+ metadata.gz: 99e260e9bd9c16e1426eb2fb16227984bae0ef8ac450481fd7cc949423e25b930fc90ae377a89e80dca2c373db18b200b840d77da22ee34814541bd401255f15
7
+ data.tar.gz: b4ab6bb59a514d3c380ea5da4e47e05dd53a22d2da209e7829ec7d5012442231c93baad21406369fbc4636c0b21c69072914712e8be116c306d21f59efeecd9f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.1.3] - 2026-03-19
6
+
7
+ ### Added
8
+ - `Hooks::Negotiate` hook class for Kerberos SPNEGO authentication via expanded hooks system
9
+ - `Runners::Authenticate#negotiate` method handling full HTTP Negotiate flow with custom response
10
+ - RBAC role mapping and JWT token issuance (guarded, requires LegionIO framework)
11
+ - Negotiate endpoint now routes through `Ingress.run` for RBAC and audit support
12
+
13
+ ### Changed
14
+ - Kerberos negotiate endpoint moves from hardcoded `/api/auth/negotiate` in LegionIO to `/api/hooks/lex/kerberos/negotiate`
15
+
5
16
  ## [0.1.2] - 2026-03-18
6
17
 
7
18
  ### Added
data/CLAUDE.md CHANGED
@@ -113,7 +113,7 @@ Optional framework dependencies (guarded with `defined?`, not in gemspec):
113
113
 
114
114
  ```bash
115
115
  bundle install
116
- bundle exec rspec # 43 specs, 91.67% coverage
116
+ bundle exec rspec # 43 specs across 8 spec files, 91.67% coverage
117
117
  bundle exec rubocop # Clean
118
118
  ```
119
119
 
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Kerberos
6
+ module Hooks
7
+ class Negotiate < Legion::Extensions::Hooks::Base
8
+ def route(_headers, _payload)
9
+ :negotiate
10
+ end
11
+
12
+ def runner_class
13
+ 'Legion::Extensions::Kerberos::Runners::Authenticate'
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -32,6 +32,20 @@ module Legion
32
32
  { result: build_result(spnego: spnego, groups: groups, ldap_error: ldap_error, profile: profile) }
33
33
  end
34
34
 
35
+ def negotiate(headers: {}, **)
36
+ auth_header = headers['HTTP_AUTHORIZATION']
37
+ unless auth_header&.match?(/\ANegotiate\s+/i)
38
+ return negotiate_error('negotiate_required', 'Negotiate token required')
39
+ end
40
+
41
+ auth_result = negotiate_authenticate(auth_header.sub(/\ANegotiate\s+/i, ''))
42
+ unless auth_result&.dig(:success)
43
+ return negotiate_error('kerberos_auth_failed', 'Kerberos authentication failed')
44
+ end
45
+
46
+ negotiate_success(auth_result)
47
+ end
48
+
35
49
  private
36
50
 
37
51
  def resolve_groups(ldap:, cfg:, username:)
@@ -53,6 +67,66 @@ module Legion
53
67
  ldap_error: ldap_error, **spnego_fields, **profile }.compact
54
68
  end
55
69
 
70
+ def negotiate_authenticate(token)
71
+ Client.new.authenticate(token: token)
72
+ rescue StandardError
73
+ nil
74
+ end
75
+
76
+ def negotiate_error(code, message)
77
+ body = negotiate_json({ error: { code: code, message: message },
78
+ meta: { timestamp: Time.now.utc.iso8601 } })
79
+ {
80
+ result: { error: code },
81
+ response: { status: 401, content_type: 'application/json',
82
+ headers: { 'WWW-Authenticate' => 'Negotiate' }, body: body }
83
+ }
84
+ end
85
+
86
+ def negotiate_success(auth_result)
87
+ profile = auth_result.slice(:first_name, :last_name, :email, :display_name)
88
+ token, roles = issue_negotiate_token(auth_result, profile)
89
+ data = { token: token, principal: auth_result[:principal],
90
+ roles: roles, auth_method: 'kerberos', **profile }.compact
91
+ negotiate_success_response(auth_result, data)
92
+ end
93
+
94
+ def negotiate_success_response(auth_result, data)
95
+ hdrs = ({ 'WWW-Authenticate' => "Negotiate #{auth_result[:output_token]}" } if auth_result[:output_token])
96
+ body = negotiate_json({ data: data, meta: { timestamp: Time.now.utc.iso8601 } })
97
+ { result: data,
98
+ response: { status: 200, content_type: 'application/json',
99
+ headers: hdrs, body: body }.compact }
100
+ end
101
+
102
+ def issue_negotiate_token(auth_result, profile)
103
+ return [nil, []] unless defined?(Legion::Rbac::KerberosClaimsMapper) && defined?(Legion::API::Token)
104
+
105
+ mapped = map_negotiate_claims(auth_result, profile)
106
+ display = mapped[:display_name] || mapped[:first_name]
107
+ token = Legion::API::Token.issue_human_token(
108
+ msid: mapped[:sub], name: display, roles: mapped[:roles], ttl: 28_800
109
+ )
110
+ [token, mapped[:roles]]
111
+ rescue StandardError
112
+ [nil, []]
113
+ end
114
+
115
+ def map_negotiate_claims(auth_result, profile)
116
+ role_map = defined?(Legion::Settings) ? (Legion::Settings.dig(:kerberos, :role_map) || {}) : {}
117
+ Legion::Rbac::KerberosClaimsMapper.map_with_fallback(
118
+ principal: auth_result[:principal], groups: auth_result[:groups] || [],
119
+ role_map: role_map, **profile
120
+ )
121
+ end
122
+
123
+ def negotiate_json(hash)
124
+ return Legion::JSON.dump(hash) if defined?(Legion::JSON)
125
+
126
+ require 'json'
127
+ ::JSON.generate(hash)
128
+ end
129
+
56
130
  include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
57
131
  Legion::Extensions::Helpers.const_defined?(:Lex)
58
132
  end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Kerberos
6
- VERSION = '0.1.2'
6
+ VERSION = '0.1.3'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-kerberos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -59,6 +59,7 @@ files:
59
59
  - lib/legion/extensions/kerberos/helpers/keytab.rb
60
60
  - lib/legion/extensions/kerberos/helpers/ldap.rb
61
61
  - lib/legion/extensions/kerberos/helpers/spnego.rb
62
+ - lib/legion/extensions/kerberos/hooks/negotiate.rb
62
63
  - lib/legion/extensions/kerberos/runners/authenticate.rb
63
64
  - lib/legion/extensions/kerberos/version.rb
64
65
  homepage: https://github.com/LegionIO/lex-kerberos