/
config.github.ru
120 lines (97 loc) · 3.35 KB
/
config.github.ru
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# config.ru
require 'himari'
require 'himari/aws'
require 'json'
require 'omniauth'
require 'omniauth-github'
require 'rack'
require 'rack/session/cookie'
require 'faraday'
use(Rack::Session::Cookie,
path: '/',
expire_after: 3600,
secure: true,
secret: ENV.fetch('SECRET_KEY_BASE'),
)
use OmniAuth::Builder do
provider :github
end
use(Himari::Middlewares::Config,
issuer: 'https://idp.example.net',
providers: [
{ name: :github, button: 'Log in with GitHub' },
],
storage: Himari::Storages::Filesystem.new('/var/lib/himari/data'),
)
# Signing key
use(Himari::Middlewares::SigningKey,
id: 'key1', # kid
pkey: OpenSSL::PKey::RSA.new(File.read('...'), ''),
)
# Add clients as many as you need
use(Himari::Middlewares::Client,
name: 'awsalb', # friendly name (this can be referenced from policies)
id: '...',
secret_hash: '...', # Digest::SHA384.hexdigest of actual secret
redirect_uris: %w(https://app.example.net/oauth2/idpresponse),
)
use(Himari::Middlewares::ClaimsRule, name: 'github-initialize') do |context, decision|
next decision.skip!("provider not in scope") unless context.provider == 'github'
decision.initialize_claims!(
sub: "github_#{context.auth[:uid]}",
name: context.auth[:info][:nickname],
preferred_username: context.auth[:info][:nickname],
email: context.auth[:info][:email],
)
decision.user_data[:provider] = 'github'
decision.continue!
end
gh_faraday = Faraday.new(url: 'https://api.github.com') do |b|
b.response :json
b.response :raise_error
end
use(Himari::Middlewares::ClaimsRule, name: 'github-oauth-teams') do |context, decision|
next decision.skip!("provider not in scope") unless context.provider == 'github'
# https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user
# (not available in GitHub Apps = only available in OAuth apps)
user_teams_resp = gh_faraday.get('user/teams', {per_page: 100}, { 'Accept' => 'application/vnd.github+json', 'Authorization' => "Bearer #{context.auth[:credentials][:token]}" }).body
teams_in_scope = %w(
contoso/engineers
contoso/admins
)
teams = user_teams_resp
.map { |team| "#{team.fetch('organization').fetch('login')}/#{team.fetch('slug')}" }
.select { |login_slug| teams_in_scope.include?(login_slug) }
next decision.skip!("no teams in scope") if teams.empty?
# claims
decision.claims[:groups] ||= []
decision.claims[:groups].concat(teams)
decision.claims[:groups].uniq!
decision.continue!
end
# Select who can be authenticated through Himari
use(Himari::Middlewares::AuthenticationRule, name: 'allow-github-with-teams') do |context, decision|
next decision.skip!("provider not in scope") unless context.provider == 'github'
if context.claims[:groups] && !context.claims[:groups].empty?
next decision.allow!
end
decision.skip!
end
use(Himari::Middlewares::AuthenticationRule, name: 'deny-someone') do |context, decision|
if context.claims[:sub] == 'something-to-ban'
context.deny!
end
decision.skip!
end
# Authorize client on behalf of a signed in user based on authz rule
use(Himari::Middlewares::AuthorizationRule, name: 'default') do |context, decision|
decision.allowed_claims.push(:groups)
available_for_everyone = %w(
wiki
)
if available_for_everyone.include?(context.client.name)
next decision.allow!
end
decision.skip!
end
run Himari::App