conjur-rack 1.4.0 → 5.0.0
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 +5 -5
- data/CHANGELOG.md +44 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +7 -1
- data/Jenkinsfile +63 -0
- data/LICENSE.txt +1 -1
- data/README.md +3 -5
- data/conjur-rack.gemspec +9 -6
- data/lib/conjur/rack/authenticator.rb +122 -51
- data/lib/conjur/rack/user.rb +80 -18
- data/lib/conjur/rack/version.rb +1 -1
- data/lib/conjur/rack.rb +23 -0
- data/publish.sh +7 -0
- data/spec/rack/authenticator_spec.rb +155 -83
- data/spec/rack/path_prefix_spec.rb +3 -3
- data/spec/rack/user_spec.rb +165 -65
- data/spec/rack_spec.rb +49 -0
- data/spec/spec_helper.rb +36 -0
- data/test.sh +12 -0
- metadata +56 -30
- data/.rvmrc +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bc0ff03755a64c04c14e15a5648c01484872315ac6e04904815ed93a115a569e
|
4
|
+
data.tar.gz: e7fd818c8efff7d6037c632117d8f73e021c185ebf5bebc08feeae75e88d72e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55a29ba4ee7e25e26514298c780c77a779252168419b516efc238af619a58a809faea7ba2664130876a43ad3d74929394f473532054c6b83dc16651f7141291b
|
7
|
+
data.tar.gz: e27d9e5cb3e26bbf5bef707dfb51e1509b1957f9a26a54b12467e046160f3097e6a776247f308364a8f5a7a8dd904e02f8a00d112c24c81c7ef2772cc0c3402c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,47 @@
|
|
1
|
+
# unreleased version
|
2
|
+
|
3
|
+
# v5.0.0
|
4
|
+
|
5
|
+
* Support Ruby 3.
|
6
|
+
* Bump `slosilo` to v3.0 with ruby 3.
|
7
|
+
* Remove pinned `bundler` version, use default system bundler.
|
8
|
+
|
9
|
+
# v4.2.0
|
10
|
+
|
11
|
+
* Bump `slosilo` to v2.2 in order to be FIPS compliant
|
12
|
+
|
13
|
+
# v4.0.0
|
14
|
+
|
15
|
+
* Bump `rack` to v2, `bundler` to v1.16 in gemspec
|
16
|
+
* Add Jenkinsfile to project
|
17
|
+
* Ignore headers such as Conjur-Privilege or Conjur-Audit if they're not
|
18
|
+
supported by the API (instead of erroring out).
|
19
|
+
|
20
|
+
# v3.1.0
|
21
|
+
|
22
|
+
* Support for JWT Slosilo tokens.
|
23
|
+
|
24
|
+
# v3.0.0.pre
|
25
|
+
|
26
|
+
* Initial support for Conjur 5.
|
27
|
+
|
28
|
+
# v2.3.0
|
29
|
+
|
30
|
+
* Add TRUSTED_PROXIES support
|
31
|
+
|
32
|
+
# v2.2.0
|
33
|
+
|
34
|
+
* resolve 'own' token to CONJUR_ACCOUNT env var
|
35
|
+
* add #optional paths to Conjur::Rack authenticator
|
36
|
+
|
37
|
+
# v2.1.0
|
38
|
+
|
39
|
+
* Add handling for `Conjur-Audit-Roles` and `Conjur-Audit-Resources`
|
40
|
+
|
41
|
+
# v2.0.0
|
42
|
+
|
43
|
+
* Change `global_sudo?` to `global_elevate?`
|
44
|
+
|
1
45
|
# v1.4.0
|
2
46
|
|
3
47
|
* Add `validated_global_privilege` helper function to get the global privilege, if any, which has been submitted with the request and verified by the Conjur server.
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
For general contribution and community guidelines, please see the [community repo](https://github.com/cyberark/community).
|
4
|
+
|
5
|
+
## Contributing Workflow
|
6
|
+
|
7
|
+
1. [Fork the project](https://help.github.com/en/github/getting-started-with-github/fork-a-repo)
|
8
|
+
2. [Clone your fork](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository)
|
9
|
+
3. Make local changes to your fork by editing files
|
10
|
+
3. [Commit your changes](https://help.github.com/en/github/managing-files-in-a-repository/adding-a-file-to-a-repository-using-the-command-line)
|
11
|
+
4. [Push your local changes to the remote server](https://help.github.com/en/github/using-git/pushing-commits-to-a-remote-repository)
|
12
|
+
5. [Create new Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork)
|
13
|
+
|
14
|
+
From here your pull request will be reviewed and once you've responded to all
|
15
|
+
feedback it will be merged into the project. Congratulations, you're a
|
16
|
+
contributor!
|
data/Gemfile
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
+
# make sure github uses TLS
|
4
|
+
git_source(:github) { |name| "https://github.com/#{name}.git" }
|
5
|
+
|
6
|
+
#ruby=ruby-3.0
|
7
|
+
#ruby-gemset=conjur-rack
|
8
|
+
|
3
9
|
# Specify your gem's dependencies in conjur-rack.gemspec
|
4
10
|
gemspec
|
5
11
|
|
6
|
-
gem 'conjur-api', github: '
|
12
|
+
# gem 'conjur-api', github: 'cyberark/conjur-api-ruby', branch: 'master'
|
data/Jenkinsfile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
pipeline {
|
2
|
+
agent { label 'executor-v2' }
|
3
|
+
|
4
|
+
options {
|
5
|
+
timestamps()
|
6
|
+
buildDiscarder(logRotator(daysToKeepStr: '30'))
|
7
|
+
}
|
8
|
+
|
9
|
+
stages {
|
10
|
+
stage('Run tests') {
|
11
|
+
steps {
|
12
|
+
sh './test.sh'
|
13
|
+
|
14
|
+
junit 'spec/reports/*.xml'
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
// Only publish to RubyGems if the HEAD is
|
19
|
+
// tagged with the same version as in version.rb
|
20
|
+
stage('Publish to RubyGems') {
|
21
|
+
agent { label 'executor-v2' }
|
22
|
+
|
23
|
+
when {
|
24
|
+
expression { currentBuild.resultIsBetterOrEqualTo('SUCCESS') }
|
25
|
+
branch "master"
|
26
|
+
expression {
|
27
|
+
def exitCode = sh returnStatus: true, script: ''' set +x
|
28
|
+
echo "Determining if publishing is requested..."
|
29
|
+
|
30
|
+
VERSION=`cat lib/conjur/rack/version.rb | grep VERSION | sed 's/.* "//;s/"//'`
|
31
|
+
echo Declared version: $VERSION
|
32
|
+
|
33
|
+
# Jenkins git plugin is broken and always fetches with `--no-tags`
|
34
|
+
# (or `--tags`, neither of which is what you want), so tags end up
|
35
|
+
# not being fetched. Try to fix that.
|
36
|
+
# (Unfortunately this fetches all remote heads, so we may have to find
|
37
|
+
# another solution for bigger repos.)
|
38
|
+
git fetch -q
|
39
|
+
|
40
|
+
# note when tag not found git rev-parse will just print its name
|
41
|
+
TAG=`git rev-list -n 1 "v$VERSION" 2>/dev/null || :`
|
42
|
+
echo Tag v$VERSION: $TAG
|
43
|
+
|
44
|
+
HEAD=`git rev-parse HEAD`
|
45
|
+
echo HEAD: $HEAD
|
46
|
+
|
47
|
+
test "$HEAD" = "$TAG"
|
48
|
+
'''
|
49
|
+
return exitCode == 0
|
50
|
+
}
|
51
|
+
}
|
52
|
+
steps {
|
53
|
+
sh './publish.sh'
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
post {
|
59
|
+
always {
|
60
|
+
cleanupAndNotify(currentBuild.currentResult)
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -22,8 +22,6 @@ TODO: Write usage instructions here
|
|
22
22
|
|
23
23
|
## Contributing
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
25
|
+
We welcome contributions of all kinds to this repository. For instructions on
|
26
|
+
how to get started and descriptions of our development workflows, please see our
|
27
|
+
[contributing guide](CONTRIBUTING.md).
|
data/conjur-rack.gemspec
CHANGED
@@ -18,12 +18,15 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "slosilo"
|
22
|
-
spec.add_dependency "conjur-api", "
|
23
|
-
spec.add_dependency "rack"
|
24
|
-
|
25
|
-
spec.add_development_dependency "bundler", "~> 1.3"
|
21
|
+
spec.add_dependency "slosilo", "~> 3.0"
|
22
|
+
spec.add_dependency "conjur-api", "< 6"
|
23
|
+
spec.add_dependency "rack", "~> 2"
|
24
|
+
|
26
25
|
spec.add_development_dependency "rake"
|
27
|
-
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "activesupport", "< 7"
|
28
28
|
spec.add_development_dependency 'ci_reporter_rspec'
|
29
|
+
spec.add_development_dependency 'pry-byebug'
|
30
|
+
spec.add_development_dependency 'rspec-its'
|
31
|
+
|
29
32
|
end
|
@@ -2,36 +2,51 @@ require "conjur/rack/user"
|
|
2
2
|
|
3
3
|
module Conjur
|
4
4
|
module Rack
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def conjur_rack
|
8
|
+
Thread.current[:conjur_rack] ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def identity?
|
12
|
+
!conjur_rack[:identity].nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def user
|
16
|
+
User.new(identity[0], identity[1],
|
17
|
+
:privilege => privilege,
|
18
|
+
:remote_ip => remote_ip,
|
19
|
+
:audit_roles => audit_roles,
|
20
|
+
:audit_resources => audit_resources
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def identity
|
25
|
+
conjur_rack[:identity] or raise "No Conjur identity for current request"
|
26
|
+
end
|
27
|
+
|
28
|
+
# class attributes
|
29
|
+
[:privilege, :remote_ip, :audit_roles, :audit_resources].each do |a|
|
30
|
+
define_method(a) do
|
31
|
+
conjur_rack[a]
|
32
|
+
end
|
33
|
+
end
|
23
34
|
end
|
35
|
+
|
24
36
|
|
25
37
|
class Authenticator
|
26
38
|
class AuthorizationError < SecurityError
|
27
39
|
end
|
28
40
|
class SignatureError < SecurityError
|
29
41
|
end
|
42
|
+
class Forbidden < SecurityError
|
43
|
+
end
|
30
44
|
|
31
45
|
attr_reader :app, :options
|
32
46
|
|
33
47
|
# +options+:
|
34
|
-
# :except :: a list of request path patterns for which to skip authentication
|
48
|
+
# :except :: a list of request path patterns for which to skip authentication.
|
49
|
+
# :optional :: request path patterns for which authentication is optional.
|
35
50
|
def initialize app, options = {}
|
36
51
|
@app = app
|
37
52
|
@options = options
|
@@ -39,10 +54,13 @@ module Conjur
|
|
39
54
|
|
40
55
|
# threadsafe accessors, values are established explicitly below
|
41
56
|
def env; Thread.current[:rack_env] ; end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
57
|
+
|
58
|
+
# instance attributes
|
59
|
+
[:token, :account, :privilege, :remote_ip, :audit_roles, :audit_resources].each do |a|
|
60
|
+
define_method(a) do
|
61
|
+
conjur_rack[a]
|
62
|
+
end
|
63
|
+
end
|
46
64
|
|
47
65
|
def call rackenv
|
48
66
|
# never store request-specific variables as application attributes
|
@@ -50,13 +68,19 @@ module Conjur
|
|
50
68
|
if authenticate?
|
51
69
|
begin
|
52
70
|
identity = verify_authorization_and_get_identity # [token, account]
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
71
|
+
|
72
|
+
if identity
|
73
|
+
conjur_rack[:token] = identity[0]
|
74
|
+
conjur_rack[:account] = identity[1]
|
75
|
+
conjur_rack[:identity] = identity
|
76
|
+
conjur_rack[:privilege] = http_privilege
|
77
|
+
conjur_rack[:remote_ip] = http_remote_ip
|
78
|
+
conjur_rack[:audit_roles] = http_audit_roles
|
79
|
+
conjur_rack[:audit_resources] = http_audit_resources
|
80
|
+
end
|
59
81
|
|
82
|
+
rescue Forbidden
|
83
|
+
return error 403, $!.message
|
60
84
|
rescue SecurityError, RestClient::Exception
|
61
85
|
return error 401, $!.message
|
62
86
|
end
|
@@ -65,61 +89,108 @@ module Conjur
|
|
65
89
|
@app.call rackenv
|
66
90
|
ensure
|
67
91
|
Thread.current[:rack_env] = nil
|
68
|
-
Thread.current[:
|
69
|
-
Thread.current[:conjur_rack_token] = nil
|
70
|
-
Thread.current[:conjur_rack_account] = nil
|
71
|
-
Thread.current[:conjur_rack_privilege] = nil
|
72
|
-
Thread.current[:conjur_rack_remote_ip] = nil
|
92
|
+
Thread.current[:conjur_rack] = {}
|
73
93
|
end
|
74
94
|
end
|
75
95
|
|
76
96
|
protected
|
77
97
|
|
98
|
+
def conjur_rack
|
99
|
+
Conjur::Rack.conjur_rack
|
100
|
+
end
|
101
|
+
|
78
102
|
def validate_token_and_get_account token
|
79
|
-
failure = SignatureError.new("
|
103
|
+
failure = SignatureError.new("Unauthorized: Invalid token")
|
80
104
|
raise failure unless (signer = Slosilo.token_signer token)
|
81
|
-
|
82
|
-
|
105
|
+
if signer == 'own'
|
106
|
+
ENV['CONJUR_ACCOUNT'] or raise failure
|
107
|
+
else
|
108
|
+
raise failure unless signer =~ /\Aauthn:(.+)\z/
|
109
|
+
$1
|
110
|
+
end
|
83
111
|
end
|
84
112
|
|
85
113
|
def error status, message
|
86
114
|
[status, { 'Content-Type' => 'text/plain', 'Content-Length' => message.length.to_s }, [message] ]
|
87
115
|
end
|
116
|
+
|
117
|
+
def parsed_token
|
118
|
+
token = http_authorization.to_s[/^Token token="(.*)"/, 1]
|
119
|
+
token = token && JSON.parse(Base64.decode64(token))
|
120
|
+
token = Slosilo::JWT token rescue token
|
121
|
+
rescue JSON::ParserError
|
122
|
+
raise AuthorizationError.new("Malformed authorization token")
|
123
|
+
end
|
88
124
|
|
125
|
+
RECOGNIZED_CLAIMS = [
|
126
|
+
'iat', 'exp', # recognized by Slosilo
|
127
|
+
'cidr', 'sub',
|
128
|
+
'iss', 'aud', 'jti' # RFC 7519, not handled but recognized
|
129
|
+
].freeze
|
130
|
+
|
89
131
|
def verify_authorization_and_get_identity
|
90
|
-
if
|
91
|
-
|
92
|
-
|
93
|
-
|
132
|
+
if token = parsed_token
|
133
|
+
begin
|
134
|
+
account = validate_token_and_get_account token
|
135
|
+
if token.respond_to?(:claims)
|
136
|
+
claims = token.claims
|
137
|
+
raise AuthorizationError, "token contains unrecognized claims" unless \
|
138
|
+
(claims.keys.map(&:to_s) - RECOGNIZED_CLAIMS).empty?
|
139
|
+
if (cidr = claims['cidr'])
|
140
|
+
raise Forbidden, "IP address rejected" unless \
|
141
|
+
cidr.map(&IPAddr.method(:new)).any? { |c| c.include? http_remote_ip }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
return [token, account]
|
145
|
+
end
|
94
146
|
else
|
95
|
-
|
147
|
+
path = http_path
|
148
|
+
if optional_paths.find{|p| p.match(path)}.nil?
|
149
|
+
raise AuthorizationError.new("Authorization missing")
|
150
|
+
else
|
151
|
+
nil
|
152
|
+
end
|
96
153
|
end
|
97
154
|
end
|
98
155
|
|
99
156
|
def authenticate?
|
157
|
+
path = http_path
|
100
158
|
if options[:except]
|
101
159
|
options[:except].find{|p| p.match(path)}.nil?
|
102
160
|
else
|
103
161
|
true
|
104
162
|
end
|
105
163
|
end
|
106
|
-
|
107
|
-
def conjur_privilege
|
108
|
-
env['HTTP_X_CONJUR_PRIVILEGE']
|
109
|
-
end
|
110
164
|
|
111
|
-
def
|
165
|
+
def optional_paths
|
166
|
+
options[:optional] || []
|
167
|
+
end
|
168
|
+
|
169
|
+
def http_authorization
|
112
170
|
env['HTTP_AUTHORIZATION']
|
113
171
|
end
|
114
|
-
|
115
|
-
def
|
172
|
+
|
173
|
+
def http_privilege
|
174
|
+
env['HTTP_X_CONJUR_PRIVILEGE']
|
175
|
+
end
|
176
|
+
|
177
|
+
def http_remote_ip
|
116
178
|
require 'rack/request'
|
117
179
|
::Rack::Request.new(env).ip
|
118
180
|
end
|
119
|
-
|
120
|
-
def
|
181
|
+
|
182
|
+
def http_audit_roles
|
183
|
+
env['HTTP_CONJUR_AUDIT_ROLES']
|
184
|
+
end
|
185
|
+
|
186
|
+
def http_audit_resources
|
187
|
+
env['HTTP_CONJUR_AUDIT_RESOURCES']
|
188
|
+
end
|
189
|
+
|
190
|
+
def http_path
|
121
191
|
[ env['SCRIPT_NAME'], env['PATH_INFO'] ].join
|
122
192
|
end
|
193
|
+
|
123
194
|
end
|
124
195
|
end
|
125
196
|
end
|
data/lib/conjur/rack/user.rb
CHANGED
@@ -2,25 +2,32 @@ require 'conjur/api'
|
|
2
2
|
|
3
3
|
module Conjur
|
4
4
|
module Rack
|
5
|
+
# Token data can be a string (which is the user login), or a Hash.
|
6
|
+
# If it's a hash, it should contain the user login keyed by the string 'login'.
|
7
|
+
# The rest of the payload is available as +attributes+.
|
5
8
|
class User
|
6
|
-
|
9
|
+
attr_reader :token, :account, :privilege, :remote_ip, :audit_roles, :audit_resources
|
7
10
|
|
8
|
-
def initialize(token, account,
|
11
|
+
def initialize(token, account, options = {})
|
9
12
|
@token = token
|
10
13
|
@account = account
|
11
|
-
|
12
|
-
|
14
|
+
# Third argument used to be the name of privilege, be
|
15
|
+
# backwards compatible:
|
16
|
+
if options.respond_to?(:to_str)
|
17
|
+
@privilege = options
|
18
|
+
else
|
19
|
+
@privilege = options[:privilege]
|
20
|
+
@remote_ip = options[:remote_ip]
|
21
|
+
@audit_roles = options[:audit_roles]
|
22
|
+
@audit_resources = options[:audit_resources]
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
15
26
|
# This file was accidently calling account conjur_account,
|
16
27
|
# I'm adding an alias in case that's going on anywhere else.
|
17
28
|
# -- Jon
|
18
29
|
alias :conjur_account :account
|
19
|
-
alias :conjur_account= :account=
|
20
|
-
|
21
|
-
def new_association(cls, params = {})
|
22
|
-
cls.new params.merge({userid: login})
|
23
|
-
end
|
30
|
+
# alias :conjur_account= :account=
|
24
31
|
|
25
32
|
# Returns the global privilege which was present on the request, if and only
|
26
33
|
# if the user actually has that privilege.
|
@@ -30,7 +37,9 @@ module Conjur
|
|
30
37
|
# actually have that privilege according to the Conjur server.
|
31
38
|
def validated_global_privilege
|
32
39
|
unless @validated_global_privilege
|
33
|
-
@privilege = nil
|
40
|
+
@privilege = nil unless @privilege &&
|
41
|
+
api.respond_to?(:global_privilege_permitted?) &&
|
42
|
+
api.global_privilege_permitted?(@privilege)
|
34
43
|
@validated_global_privilege = true
|
35
44
|
end
|
36
45
|
@privilege
|
@@ -41,13 +50,21 @@ module Conjur
|
|
41
50
|
validated_global_privilege == "reveal"
|
42
51
|
end
|
43
52
|
|
44
|
-
# True if and only if the user has valid global '
|
45
|
-
def
|
46
|
-
validated_global_privilege == "
|
53
|
+
# True if and only if the user has valid global 'elevate' privilege.
|
54
|
+
def global_elevate?
|
55
|
+
validated_global_privilege == "elevate"
|
47
56
|
end
|
48
57
|
|
49
58
|
def login
|
50
|
-
|
59
|
+
parse_token
|
60
|
+
|
61
|
+
@login
|
62
|
+
end
|
63
|
+
|
64
|
+
def attributes
|
65
|
+
parse_token
|
66
|
+
|
67
|
+
@attributes || {}
|
51
68
|
end
|
52
69
|
|
53
70
|
def roleid
|
@@ -63,17 +80,62 @@ module Conjur
|
|
63
80
|
def role
|
64
81
|
api.role(roleid)
|
65
82
|
end
|
66
|
-
|
83
|
+
|
84
|
+
def audit_resources
|
85
|
+
Conjur::API.decode_audit_ids(@audit_resources) if @audit_resources
|
86
|
+
end
|
87
|
+
|
88
|
+
def audit_roles
|
89
|
+
Conjur::API.decode_audit_ids(@audit_roles) if @audit_roles
|
90
|
+
end
|
91
|
+
|
67
92
|
def api(cls = Conjur::API)
|
68
93
|
args = [ token ]
|
69
94
|
args.push remote_ip if remote_ip
|
70
95
|
api = cls.new_from_token(*args)
|
71
|
-
|
72
|
-
|
96
|
+
|
97
|
+
# These are features not present in some API versions.
|
98
|
+
# Test for them and only apply if it makes sense. Ignore otherwise.
|
99
|
+
%i(privilege audit_resources audit_roles).each do |feature|
|
100
|
+
meth = "with_#{feature}".intern
|
101
|
+
if api.respond_to?(meth) && (value = send(feature))
|
102
|
+
api = api.send meth, value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
api
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
def parse_token
|
112
|
+
return if @login
|
113
|
+
|
114
|
+
@token = Slosilo::JWT token
|
115
|
+
load_jwt token
|
116
|
+
rescue ArgumentError
|
117
|
+
if data = token['data']
|
118
|
+
return load_legacy data
|
73
119
|
else
|
74
|
-
|
120
|
+
raise "malformed token"
|
75
121
|
end
|
76
122
|
end
|
123
|
+
|
124
|
+
def load_legacy data
|
125
|
+
if data.is_a?(String)
|
126
|
+
@login = token['data']
|
127
|
+
elsif data.is_a?(Hash)
|
128
|
+
@attributes = token['data'].clone
|
129
|
+
@login = @attributes.delete('login') or raise "No 'login' field in token data"
|
130
|
+
else
|
131
|
+
raise "Expecting String or Hash token data, got #{data.class.name}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def load_jwt jwt
|
136
|
+
@attributes = jwt.claims.merge (jwt.header || {}) # just pass all the info
|
137
|
+
@login = jwt.claims['sub'] or raise "No 'sub' field in claims"
|
138
|
+
end
|
77
139
|
end
|
78
140
|
end
|
79
141
|
end
|
data/lib/conjur/rack/version.rb
CHANGED
data/lib/conjur/rack.rb
CHANGED
@@ -1,3 +1,26 @@
|
|
1
1
|
require "conjur/rack/version"
|
2
2
|
require "conjur/rack/authenticator"
|
3
3
|
require "conjur/rack/path_prefix"
|
4
|
+
require 'ipaddr'
|
5
|
+
require 'set'
|
6
|
+
|
7
|
+
module TrustedProxies
|
8
|
+
|
9
|
+
def trusted_proxy?(ip)
|
10
|
+
trusted_proxies ? trusted_proxies.any? { |cidr| cidr.include?(ip) } : super
|
11
|
+
end
|
12
|
+
|
13
|
+
def trusted_proxies
|
14
|
+
@trusted_proxies || ENV['TRUSTED_PROXIES'].try do |proxies|
|
15
|
+
cidrs = Set.new(proxies.split(',') + ['127.0.0.1'])
|
16
|
+
@trusted_proxies = cidrs.collect {|cidr| IPAddr.new(cidr) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
module Rack
|
23
|
+
class Request
|
24
|
+
prepend TrustedProxies
|
25
|
+
end
|
26
|
+
end
|
data/publish.sh
ADDED