mirror of
https://github.com/oddlama/nix-config.git
synced 2025-10-10 23:00:39 +02:00
feat: patch oauth2-proxy to support scopes as groups
This commit is contained in:
parent
1a0378ee5c
commit
eb9ee0bf0d
7 changed files with 65 additions and 16 deletions
|
@ -151,7 +151,7 @@ kanidm group create grafana-server-admins
|
||||||
kanidm group create grafana-admins
|
kanidm group create grafana-admins
|
||||||
kanidm group create grafana-editors
|
kanidm group create grafana-editors
|
||||||
kanidm system oauth2 create grafana "Grafana" https://grafana.${personalDomain}
|
kanidm system oauth2 create grafana "Grafana" https://grafana.${personalDomain}
|
||||||
kanidm system oauth2 update-scope-map grafana grafana-access openid profile email
|
kanidm system oauth2 update-scope-map grafana grafana-access openid email profile
|
||||||
kanidm system oauth2 update-sup-scope-map grafana grafana-server-admins server_admin
|
kanidm system oauth2 update-sup-scope-map grafana grafana-server-admins server_admin
|
||||||
kanidm system oauth2 update-sup-scope-map grafana grafana-admins admin
|
kanidm system oauth2 update-sup-scope-map grafana grafana-admins admin
|
||||||
kanidm system oauth2 update-sup-scope-map grafana grafana-editors editor
|
kanidm system oauth2 update-sup-scope-map grafana grafana-editors editor
|
||||||
|
@ -160,7 +160,7 @@ kanidm system oauth2 show-basic-secret grafana
|
||||||
kanidm group create web-sentinel-access
|
kanidm group create web-sentinel-access
|
||||||
kanidm group create web-sentinel-adguardhome-access
|
kanidm group create web-sentinel-adguardhome-access
|
||||||
kanidm system oauth2 create web-sentinel "Web services" https://oauth2.${personalDomain}
|
kanidm system oauth2 create web-sentinel "Web services" https://oauth2.${personalDomain}
|
||||||
kanidm system oauth2 update-scope-map web-sentinel web-sentinel-access openid profile email
|
kanidm system oauth2 update-scope-map web-sentinel web-sentinel-access openid email
|
||||||
kanidm system oauth2 update-sup-scope-map web-sentinel web-sentinel-adguardhome-access access_adguardhome
|
kanidm system oauth2 update-sup-scope-map web-sentinel web-sentinel-adguardhome-access access_adguardhome
|
||||||
kanidm system oauth2 show-basic-secret web-sentinel
|
kanidm system oauth2 show-basic-secret web-sentinel
|
||||||
# Add new user
|
# Add new user
|
||||||
|
@ -169,6 +169,7 @@ kanidm person create myuser "My User"
|
||||||
kanidm person update myuser --legalname "Full Name" --mail "myuser@example.com"
|
kanidm person update myuser --legalname "Full Name" --mail "myuser@example.com"
|
||||||
kanidm group add-members grafana-access myuser
|
kanidm group add-members grafana-access myuser
|
||||||
kanidm group add-members grafana-server-admins myuser
|
kanidm group add-members grafana-server-admins myuser
|
||||||
|
kanidm group add-members web-sentinel-access myuser
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
enable = true;
|
enable = true;
|
||||||
cookieDomain = config.repo.secrets.local.personalDomain;
|
cookieDomain = config.repo.secrets.local.personalDomain;
|
||||||
portalDomain = "oauth2.${config.repo.secrets.local.personalDomain}";
|
portalDomain = "oauth2.${config.repo.secrets.local.personalDomain}";
|
||||||
|
# TODO portal redirect to dashboard (in case someone clicks on kanidm "Web services")
|
||||||
};
|
};
|
||||||
|
|
||||||
age.secrets.oauth2-proxy-secret = {
|
age.secrets.oauth2-proxy-secret = {
|
||||||
|
@ -16,24 +17,21 @@
|
||||||
group = "oauth2_proxy";
|
group = "oauth2_proxy";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.oauth2_proxy = {
|
services.oauth2_proxy = let
|
||||||
|
clientId = "web-sentinel";
|
||||||
|
in {
|
||||||
provider = "oidc";
|
provider = "oidc";
|
||||||
scope = "openid email";
|
scope = "openid email";
|
||||||
loginURL = "https://${config.proxiedDomains.kanidm}/ui/oauth2";
|
loginURL = "https://${config.proxiedDomains.kanidm}/ui/oauth2";
|
||||||
redeemURL = "https://${config.proxiedDomains.kanidm}/oauth2/token";
|
redeemURL = "https://${config.proxiedDomains.kanidm}/oauth2/token";
|
||||||
validateURL = "https://${config.proxiedDomains.kanidm}/oauth2/openid/web-sentinel/userinfo";
|
validateURL = "https://${config.proxiedDomains.kanidm}/oauth2/openid/${clientId}/userinfo";
|
||||||
clientID = "web-sentinel";
|
clientID = clientId;
|
||||||
keyFile = config.age.secrets.oauth2-proxy-secret.path;
|
keyFile = config.age.secrets.oauth2-proxy-secret.path;
|
||||||
email.domains = ["*"];
|
email.domains = ["*"];
|
||||||
|
|
||||||
extraConfig = {
|
extraConfig = {
|
||||||
# TODO good idea? would fail when offline
|
oidc-issuer-url = "https://${config.proxiedDomains.kanidm}/oauth2/openid/${clientId}";
|
||||||
# TODO autorestart after 30 minutes, infinite times.
|
|
||||||
oidc-issuer-url = "https://${config.proxiedDomains.kanidm}/oauth2/openid/web-sentinel";
|
|
||||||
skip-provider-button = true;
|
skip-provider-button = true;
|
||||||
|
|
||||||
# TODO away
|
|
||||||
show-debug-on-error = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ in {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert adguardhomeDomain;
|
useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert adguardhomeDomain;
|
||||||
oauth2.enable = true;
|
oauth2.enable = true;
|
||||||
oauth2.allowedGroups = ["adguardhome"];
|
oauth2.allowedGroups = ["access_adguardhome"];
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://adguardhome";
|
proxyPass = "http://adguardhome";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
|
|
|
@ -99,12 +99,14 @@ in {
|
||||||
|
|
||||||
cookie.domain = ".${cfg.cookieDomain}";
|
cookie.domain = ".${cfg.cookieDomain}";
|
||||||
cookie.secure = true;
|
cookie.secure = true;
|
||||||
cookie.httpOnly = false;
|
# FIXME disabled because of errors. My closest guess is that this
|
||||||
cookie.refresh = "5m";
|
# reuses refresh tokens but kanidm forbids that. Not sure though.
|
||||||
|
#cookie.refresh = "5m";
|
||||||
cookie.expire = "30m";
|
cookie.expire = "30m";
|
||||||
|
|
||||||
reverseProxy = true;
|
reverseProxy = true;
|
||||||
httpAddress = "unix:///run/oauth2_proxy/oauth2_proxy.sock";
|
httpAddress = "unix:///run/oauth2_proxy/oauth2_proxy.sock";
|
||||||
|
redirectURL = "https://${cfg.portalDomain}/oauth2/callback";
|
||||||
setXauthrequest = true;
|
setXauthrequest = true;
|
||||||
|
|
||||||
extraConfig = {
|
extraConfig = {
|
||||||
|
@ -112,12 +114,10 @@ in {
|
||||||
code-challenge-method = "S256";
|
code-challenge-method = "S256";
|
||||||
# Share the cookie with all subpages
|
# Share the cookie with all subpages
|
||||||
whitelist-domain = ".${cfg.cookieDomain}";
|
whitelist-domain = ".${cfg.cookieDomain}";
|
||||||
redirect-url = "https://${cfg.portalDomain}/oauth2/callback";
|
|
||||||
set-authorization-header = true;
|
set-authorization-header = true;
|
||||||
pass-access-token = true;
|
pass-access-token = true;
|
||||||
skip-jwt-bearer-tokens = true;
|
skip-jwt-bearer-tokens = true;
|
||||||
upstream = "static://202";
|
upstream = "static://202";
|
||||||
# TODO allowed group?
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
[
|
[
|
||||||
(import ./caddy.nix)
|
(import ./caddy.nix)
|
||||||
|
(import ./oauth2-proxy)
|
||||||
]
|
]
|
||||||
|
|
44
pkgs/oauth2-proxy/0001-scopes-as-groups.patch
Normal file
44
pkgs/oauth2-proxy/0001-scopes-as-groups.patch
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
diff --git a/providers/oidc.go b/providers/oidc.go
|
||||||
|
index aadaf7c5..18b03a3e 100644
|
||||||
|
--- a/providers/oidc.go
|
||||||
|
+++ b/providers/oidc.go
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
||||||
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
|
||||||
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
|
||||||
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||||
|
+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -80,6 +81,31 @@ func (p *OIDCProvider) Redeem(ctx context.Context, redirectURL, code, codeVerifi
|
||||||
|
// EnrichSession is called after Redeem to allow providers to enrich session fields
|
||||||
|
// such as User, Email, Groups with provider specific API calls.
|
||||||
|
func (p *OIDCProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
|
||||||
|
+ // Fallback to ValidateURL if ProfileURL not set for legacy compatibility
|
||||||
|
+ profileURL := p.ValidateURL.String()
|
||||||
|
+ if p.ProfileURL.String() != "" {
|
||||||
|
+ profileURL = p.ProfileURL.String()
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ json, err := requests.New(profileURL).
|
||||||
|
+ WithContext(ctx).
|
||||||
|
+ SetHeader("Authorization", "Bearer "+s.AccessToken).
|
||||||
|
+ Do().
|
||||||
|
+ UnmarshalSimpleJSON()
|
||||||
|
+ if err != nil {
|
||||||
|
+ logger.Errorf("failed making request %v", err)
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ groups, err := json.Get("scopes").StringArray()
|
||||||
|
+ if err == nil {
|
||||||
|
+ for _, group := range groups {
|
||||||
|
+ if group != "" {
|
||||||
|
+ s.Groups = append(s.Groups, group)
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// If a mandatory email wasn't set, error at this point.
|
||||||
|
if s.Email == "" {
|
||||||
|
return errors.New("neither the id_token nor the profileURL set an email")
|
5
pkgs/oauth2-proxy/default.nix
Normal file
5
pkgs/oauth2-proxy/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
final: prev: {
|
||||||
|
oauth2-proxy = prev.oauth2-proxy.overrideAttrs (_: {
|
||||||
|
patches = [./0001-scopes-as-groups.patch];
|
||||||
|
});
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue