keycard 0.1.1 → 0.1.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/README.md +37 -2
- data/keycard.gemspec +0 -1
- data/lib/keycard/direct_request.rb +19 -0
- data/lib/keycard/institution_finder.rb +1 -1
- data/lib/keycard/proxied_request.rb +24 -0
- data/lib/keycard/railtie.rb +8 -3
- data/lib/keycard/request_attributes.rb +28 -5
- data/lib/keycard/version.rb +1 -1
- data/lib/keycard.rb +8 -0
- metadata +4 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ba441d104509e55f853e1003f6dd2d8c39f362e5e93ee619b0dd9378f8c13b8
|
4
|
+
data.tar.gz: 0d503c7e8c4682348e2c6d1ba9d9d0425fdf61429a278882368bad5cb19c4823
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 578ff3eb3e114a3060b0236f6c471fabf45e947b1f2184828f68206eab35071bfa182482cfbab4e9a1750a48e2e127d1aa4e4feda050a11e53c1937ad0778837
|
7
|
+
data.tar.gz: a268b75e7207d0de7626b8f675567eddce0c070158343e2f55d424c6868c06837bfcd03c0be68a3ff8b1edc42aa5798df7d3b59cbadb5b00bea1173a0e855e6d
|
data/README.md
CHANGED
@@ -37,9 +37,44 @@ And then execute:
|
|
37
37
|
|
38
38
|
$ bundle
|
39
39
|
|
40
|
-
|
40
|
+
## Configuration
|
41
41
|
|
42
|
-
|
42
|
+
There are two aspects of Keycard that are configurable: the database for IP
|
43
|
+
ranges as they map to institutions (IP blocks map to networks, and networks are
|
44
|
+
associated with institutions), and the access mode (whether your application is
|
45
|
+
served directly or behind a reverse proxy). These will be unified eventually,
|
46
|
+
but for now, they are configured separately.
|
47
|
+
|
48
|
+
## For the Database
|
49
|
+
|
50
|
+
For the database, there is a Railtie that, when running in a Rails app,
|
51
|
+
attempts to use the same connection information as ActiveRecord. If you are
|
52
|
+
running in this configuration, you will need to run a `rake db:migrate` to
|
53
|
+
create the Keycard tables and add them to your `db/schema.rb`. From there forward,
|
54
|
+
running `db:setup` or `db:schema:load` will create these tables for you. There is
|
55
|
+
a `keycard:migrate` Rake task if you want to run it separately, but it hooks into
|
56
|
+
the Rails `db:migrate` by default for convenience.
|
57
|
+
|
58
|
+
If you need to customize the database configuration, which will be typical for
|
59
|
+
at least the production environment, the easiest way is to define an
|
60
|
+
initializer. In a multi-application environment, the database may be read-only,
|
61
|
+
which will require the `Keycard::DB.config` to have its `readonly` property set
|
62
|
+
to `true`. You can also set either the `Keycard::DB.config.opts` to the options
|
63
|
+
to pass to the Sequel connection or set `Keycard::DB.config.url` to use a
|
64
|
+
connction string. The latter is equivalent to setting the `KEYCARD_DATABASE_URL`
|
65
|
+
environment variable.
|
66
|
+
|
67
|
+
## For the Access Mode
|
68
|
+
|
69
|
+
To extract the username and client IP from each request, Keycard must be
|
70
|
+
configured for an "access mode". This can be set in an initializer, under the
|
71
|
+
`Keycard.config.access` property, and should be either `:direct` if clients
|
72
|
+
will make HTTP requests directly to the Ruby webserver, or `:proxy` if a
|
73
|
+
reverse proxy will be used.
|
74
|
+
|
75
|
+
Under the hood, these modes amount to using either `REMOTE_USER` and
|
76
|
+
`REMOTE_ADDR` in the environment set by the Ruby webserver for direct mode or
|
77
|
+
the `X-Forwarded-User` and `X-Forwarded-For` headers set by a reverse proxy.
|
43
78
|
|
44
79
|
## License
|
45
80
|
|
data/keycard.gemspec
CHANGED
@@ -25,7 +25,6 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
-
spec.add_dependency "mysql2"
|
29
28
|
spec.add_dependency "sequel"
|
30
29
|
|
31
30
|
spec.add_development_dependency "bundler", "~> 1.16"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Keycard
|
4
|
+
# This request wrapper should be used when the application will serve HTTP
|
5
|
+
# requests directly or through a proxy that sets up the usual environment.
|
6
|
+
class DirectRequest < SimpleDelegator
|
7
|
+
def self.for(request)
|
8
|
+
new(request)
|
9
|
+
end
|
10
|
+
|
11
|
+
def username
|
12
|
+
env['REMOTE_USER'] || ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def client_ip
|
16
|
+
(env['REMOTE_ADDR'] || '').split(',').first || ''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Keycard
|
4
|
+
# This request wrapper should be used when the application will be served
|
5
|
+
# behind a reverse proxy. It relies on the trusted relationship with the
|
6
|
+
# proxy to use HTTP headers for forwarded values.
|
7
|
+
#
|
8
|
+
# The typical headers forwarded are X-Forwarded-User and X-Forwarded-For,
|
9
|
+
# which, somewhat confusingly, are transposed into HTTP_X_REMOTE_USER and
|
10
|
+
# HTTP_X_FORWARDED_FOR once the Rack request is assembled.
|
11
|
+
class ProxiedRequest < SimpleDelegator
|
12
|
+
def self.for(request)
|
13
|
+
new(request)
|
14
|
+
end
|
15
|
+
|
16
|
+
def username
|
17
|
+
env['HTTP_X_REMOTE_USER'] || ''
|
18
|
+
end
|
19
|
+
|
20
|
+
def client_ip
|
21
|
+
(env['HTTP_X_FORWARDED_FOR'] || '').split(',').first || ''
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/keycard/railtie.rb
CHANGED
@@ -66,9 +66,14 @@ module Keycard
|
|
66
66
|
initializer "keycard.before_initializers", before: :load_config_initializers do
|
67
67
|
config = Keycard::DB.config
|
68
68
|
unless config.url
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
case Rails.env
|
70
|
+
when "development"
|
71
|
+
config[:opts] = { adapter: 'sqlite', database: "db/keycard_development.sqlite3" }
|
72
|
+
when "test"
|
73
|
+
config[:opts] = { adapter: 'sqlite' }
|
74
|
+
else
|
75
|
+
raise "Keycard::DB.config must be configured"
|
76
|
+
end
|
72
77
|
end
|
73
78
|
|
74
79
|
Railtie.before_blocks.each do |block|
|
@@ -5,9 +5,10 @@ module Keycard
|
|
5
5
|
# complete set of things that determine the user's #identity), given a Rack
|
6
6
|
# request.
|
7
7
|
class RequestAttributes
|
8
|
-
def initialize(request, finder: InstitutionFinder.new)
|
9
|
-
@
|
10
|
-
@
|
8
|
+
def initialize(request, finder: InstitutionFinder.new, request_factory: default_factory)
|
9
|
+
@request = request
|
10
|
+
@finder = finder
|
11
|
+
@request_factory = request_factory
|
11
12
|
end
|
12
13
|
|
13
14
|
def [](attr)
|
@@ -15,12 +16,34 @@ module Keycard
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def all
|
18
|
-
finder.attributes_for(request)
|
19
|
+
user_attributes.merge(finder.attributes_for(request))
|
19
20
|
end
|
20
21
|
|
21
22
|
private
|
22
23
|
|
24
|
+
def user_attributes
|
25
|
+
{ username: request.username }
|
26
|
+
end
|
27
|
+
|
28
|
+
def request
|
29
|
+
request_factory.for(@request)
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_factory
|
33
|
+
access = Keycard.config.access.to_sym
|
34
|
+
case access
|
35
|
+
when :direct
|
36
|
+
DirectRequest
|
37
|
+
when :proxy
|
38
|
+
ProxiedRequest
|
39
|
+
else
|
40
|
+
# TODO: Warn about this once to the appropriate log; probably in a config check, not here.
|
41
|
+
# puts "Keycard does not recognize the '#{access}' access mode, using 'direct'."
|
42
|
+
DirectRequest
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
23
46
|
attr_reader :finder
|
24
|
-
attr_reader :
|
47
|
+
attr_reader :request_factory
|
25
48
|
end
|
26
49
|
end
|
data/lib/keycard/version.rb
CHANGED
data/lib/keycard.rb
CHANGED
@@ -2,12 +2,20 @@
|
|
2
2
|
|
3
3
|
require "keycard/version"
|
4
4
|
require "sequel"
|
5
|
+
require "ostruct"
|
5
6
|
|
6
7
|
# All of the Keycard components are contained within this top-level module.
|
7
8
|
module Keycard
|
9
|
+
def self.config
|
10
|
+
@config ||= OpenStruct.new(
|
11
|
+
access: :direct
|
12
|
+
)
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
16
|
require "keycard/db"
|
11
17
|
require "keycard/railtie" if defined?(Rails)
|
12
18
|
require "keycard/request_attributes"
|
13
19
|
require "keycard/institution_finder"
|
20
|
+
require "keycard/direct_request"
|
21
|
+
require "keycard/proxied_request"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keycard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Botimer
|
@@ -9,22 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-06-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: mysql2
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '0'
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: '0'
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: sequel
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -202,7 +188,9 @@ files:
|
|
202
188
|
- keycard.gemspec
|
203
189
|
- lib/keycard.rb
|
204
190
|
- lib/keycard/db.rb
|
191
|
+
- lib/keycard/direct_request.rb
|
205
192
|
- lib/keycard/institution_finder.rb
|
193
|
+
- lib/keycard/proxied_request.rb
|
206
194
|
- lib/keycard/railtie.rb
|
207
195
|
- lib/keycard/request_attributes.rb
|
208
196
|
- lib/keycard/version.rb
|