Merge pull request #273233 from SuperSandro2000/oauth2-proxy

nixos/oauth2-proxy{,-nginx}: renamed from oauth2_proxy, also renamed the servi…

Sandro bafcff9b 98f5a7c4

Changed files
+155 -155
nixos
doc
manual
release-notes
modules
+2
nixos/doc/manual/release-notes/rl-2405.section.md
···
- `services.zope2` has been removed as `zope2` is unmaintained and was relying on Python2.
- `services.avahi.nssmdns` got split into `services.avahi.nssmdns4` and `services.avahi.nssmdns6` which enable the mDNS NSS switch for IPv4 and IPv6 respectively.
Since most mDNS responders only register IPv4 addresses, most users want to keep the IPv6 support disabled to avoid long timeouts.
···
- `services.zope2` has been removed as `zope2` is unmaintained and was relying on Python2.
+
- `services.oauth2_proxy` was renamed to `services.oauth2-proxy`. Also the corresponding service, user and group were renamed.
+
- `services.avahi.nssmdns` got split into `services.avahi.nssmdns4` and `services.avahi.nssmdns6` which enable the mDNS NSS switch for IPv4 and IPv6 respectively.
Since most mDNS responders only register IPv4 addresses, most users want to keep the IPv6 support disabled to avoid long timeouts.
+2 -2
nixos/modules/module-list.nix
···
./services/security/kanidm.nix
./services/security/munge.nix
./services/security/nginx-sso.nix
-
./services/security/oauth2_proxy.nix
-
./services/security/oauth2_proxy_nginx.nix
./services/security/opensnitch.nix
./services/security/pass-secret-service.nix
./services/security/physlock.nix
···
./services/security/kanidm.nix
./services/security/munge.nix
./services/security/nginx-sso.nix
+
./services/security/oauth2-proxy.nix
+
./services/security/oauth2-proxy-nginx.nix
./services/security/opensnitch.nix
./services/security/pass-secret-service.nix
./services/security/physlock.nix
+124 -125
nixos/modules/services/security/oauth2_proxy.nix nixos/modules/services/security/oauth2-proxy.nix
···
-
# NixOS module for oauth2_proxy.
-
{ config, lib, pkgs, ... }:
-
with lib;
let
-
cfg = config.services.oauth2_proxy;
-
# oauth2_proxy provides many options that are only relevant if you are using
# a certain provider. This set maps from provider name to a function that
# takes the configuration and returns a string that can be inserted into the
-
# command-line to launch oauth2_proxy.
providerSpecificOptions = {
azure = cfg: {
azure-tenant = cfg.azure.tenant;
···
} // (getProviderOptions cfg cfg.provider) // cfg.extraConfig;
mapConfig = key: attr:
-
optionalString (attr != null && attr != []) (
-
if isDerivation attr then mapConfig key (toString attr) else
-
if (builtins.typeOf attr) == "set" then concatStringsSep " "
-
(mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
-
if (builtins.typeOf attr) == "list" then concatMapStringsSep " " (mapConfig key) attr else
-
if (builtins.typeOf attr) == "bool" then "--${key}=${boolToString attr}" else
if (builtins.typeOf attr) == "string" then "--${key}='${attr}'" else
"--${key}=${toString attr}");
-
configString = concatStringsSep " " (mapAttrsToList mapConfig allConfig);
in
{
-
options.services.oauth2_proxy = {
-
enable = mkEnableOption "oauth2_proxy";
-
package = mkPackageOption pkgs "oauth2-proxy" { };
##############################################
# PROVIDER configuration
# Taken from: https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/providers.go
-
provider = mkOption {
-
type = types.enum [
"adfs"
"azure"
"bitbucket"
···
'';
};
-
approvalPrompt = mkOption {
-
type = types.enum ["force" "auto"];
default = "force";
description = ''
OAuth approval_prompt.
'';
};
-
clientID = mkOption {
-
type = types.nullOr types.str;
description = ''
The OAuth Client ID.
'';
example = "123456.apps.googleusercontent.com";
};
-
oidcIssuerUrl = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
The OAuth issuer URL.
···
example = "https://login.microsoftonline.com/{TENANT_ID}/v2.0";
};
-
clientSecret = mkOption {
-
type = types.nullOr types.str;
description = ''
The OAuth Client Secret.
'';
};
-
skipAuthRegexes = mkOption {
-
type = types.listOf types.str;
default = [];
description = ''
Skip authentication for requests matching any of these regular
···
# XXX: Not clear whether these two options are mutually exclusive or not.
email = {
-
domains = mkOption {
-
type = types.listOf types.str;
default = [];
description = ''
Authenticate emails with the specified domains. Use
···
'';
};
-
addresses = mkOption {
-
type = types.nullOr types.lines;
default = null;
description = ''
Line-separated email addresses that are allowed to authenticate.
···
};
};
-
loginURL = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Authentication endpoint.
···
example = "https://provider.example.com/oauth/authorize";
};
-
redeemURL = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Token redemption endpoint.
···
example = "https://provider.example.com/oauth/token";
};
-
validateURL = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Access token validation endpoint.
···
example = "https://provider.example.com/user/emails";
};
-
redirectURL = mkOption {
# XXX: jml suspects this is always necessary, but the command-line
# doesn't require it so making it optional.
-
type = types.nullOr types.str;
default = null;
description = ''
The OAuth2 redirect URL.
···
};
azure = {
-
tenant = mkOption {
-
type = types.str;
default = "common";
description = ''
Go to a tenant-specific or common (tenant-independent) endpoint.
'';
};
-
resource = mkOption {
-
type = types.str;
description = ''
The resource that is protected.
'';
···
};
google = {
-
adminEmail = mkOption {
-
type = types.str;
description = ''
The Google Admin to impersonate for API calls.
···
'';
};
-
groups = mkOption {
-
type = types.listOf types.str;
default = [];
description = ''
Restrict logins to members of these Google groups.
'';
};
-
serviceAccountJSON = mkOption {
-
type = types.path;
description = ''
The path to the service account JSON credentials.
'';
···
};
github = {
-
org = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Restrict logins to members of this organisation.
'';
};
-
team = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Restrict logins to members of this team.
···
####################################################
# UPSTREAM Configuration
-
upstream = mkOption {
-
type = with types; coercedTo str (x: [x]) (listOf str);
default = [];
description = ''
The http url(s) of the upstream endpoint or `file://`
···
'';
};
-
passAccessToken = mkOption {
-
type = types.bool;
default = false;
description = ''
Pass OAuth access_token to upstream via X-Forwarded-Access-Token header.
'';
};
-
passBasicAuth = mkOption {
-
type = types.bool;
default = true;
description = ''
Pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream.
'';
};
-
basicAuthPassword = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
The password to set when passing the HTTP Basic Auth header.
'';
};
-
passHostHeader = mkOption {
-
type = types.bool;
default = true;
description = ''
Pass the request Host Header to upstream.
'';
};
-
signatureKey = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
GAP-Signature request signature key.
···
};
cookie = {
-
domain = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Optional cookie domains to force cookies to (ie: `.yourcompany.com`).
···
example = ".yourcompany.com";
};
-
expire = mkOption {
-
type = types.str;
default = "168h0m0s";
description = ''
Expire timeframe for cookie.
'';
};
-
httpOnly = mkOption {
-
type = types.bool;
default = true;
description = ''
Set HttpOnly cookie flag.
'';
};
-
name = mkOption {
-
type = types.str;
default = "_oauth2_proxy";
description = ''
The name of the cookie that the oauth_proxy creates.
'';
};
-
refresh = mkOption {
# XXX: Unclear what the behavior is when this is not specified.
-
type = types.nullOr types.str;
default = null;
description = ''
Refresh the cookie after this duration; 0 to disable.
···
example = "168h0m0s";
};
-
secret = mkOption {
-
type = types.nullOr types.str;
description = ''
The seed string for secure cookies.
'';
};
-
secure = mkOption {
-
type = types.bool;
default = true;
description = ''
Set secure (HTTPS) cookie flag.
···
####################################################
# OAUTH2 PROXY configuration
-
httpAddress = mkOption {
-
type = types.str;
default = "http://127.0.0.1:4180";
description = ''
HTTPS listening address. This module does not expose the port by
···
};
htpasswd = {
-
file = mkOption {
-
type = types.nullOr types.path;
default = null;
description = ''
Additionally authenticate against a htpasswd file. Entries must be
···
'';
};
-
displayForm = mkOption {
-
type = types.bool;
default = true;
description = ''
Display username / password login form if an htpasswd file is provided.
···
};
};
-
customTemplatesDir = mkOption {
-
type = types.nullOr types.path;
default = null;
description = ''
Path to custom HTML templates.
'';
};
-
reverseProxy = mkOption {
-
type = types.bool;
default = false;
description = ''
In case when running behind a reverse proxy, controls whether headers
···
'';
};
-
proxyPrefix = mkOption {
-
type = types.str;
default = "/oauth2";
description = ''
The url root path that this proxy should be nested under.
···
};
tls = {
-
enable = mkOption {
-
type = types.bool;
default = false;
description = ''
Whether to serve over TLS.
'';
};
-
certificate = mkOption {
-
type = types.path;
description = ''
Path to certificate file.
'';
};
-
key = mkOption {
-
type = types.path;
description = ''
Path to private key file.
'';
};
-
httpsAddress = mkOption {
-
type = types.str;
default = ":443";
description = ''
`addr:port` to listen on for HTTPS clients.
···
};
};
-
requestLogging = mkOption {
-
type = types.bool;
default = true;
description = ''
Log requests to stdout.
···
# UNKNOWN
# XXX: Is this mandatory? Is it part of another group? Is it part of the provider specification?
-
scope = mkOption {
# XXX: jml suspects this is always necessary, but the command-line
# doesn't require it so making it optional.
-
type = types.nullOr types.str;
default = null;
description = ''
OAuth scope specification.
'';
};
-
profileURL = mkOption {
-
type = types.nullOr types.str;
default = null;
description = ''
Profile access endpoint.
'';
};
-
setXauthrequest = mkOption {
-
type = types.nullOr types.bool;
default = false;
description = ''
Set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode). Setting this to 'null' means using the upstream default (false).
'';
};
-
extraConfig = mkOption {
default = {};
-
type = types.attrsOf types.anything;
description = ''
Extra config to pass to oauth2-proxy.
'';
};
-
keyFile = mkOption {
-
type = types.nullOr types.path;
default = null;
description = ''
oauth2-proxy allows passing sensitive configuration via environment variables.
···
OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
and specify the path here.
'';
-
example = "/run/keys/oauth2_proxy";
};
-
};
-
config = mkIf cfg.enable {
-
services.oauth2_proxy = mkIf (cfg.keyFile != null) {
-
clientID = mkDefault null;
-
clientSecret = mkDefault null;
-
cookie.secret = mkDefault null;
};
-
users.users.oauth2_proxy = {
description = "OAuth2 Proxy";
isSystemUser = true;
-
group = "oauth2_proxy";
};
-
users.groups.oauth2_proxy = {};
-
systemd.services.oauth2_proxy = {
description = "OAuth2 Proxy";
path = [ cfg.package ];
wantedBy = [ "multi-user.target" ];
···
after = [ "network-online.target" ];
serviceConfig = {
-
User = "oauth2_proxy";
Restart = "always";
ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
-
EnvironmentFile = mkIf (cfg.keyFile != null) cfg.keyFile;
};
};
···
{ config, lib, pkgs, ... }:
let
+
cfg = config.services.oauth2-proxy;
+
# oauth2-proxy provides many options that are only relevant if you are using
# a certain provider. This set maps from provider name to a function that
# takes the configuration and returns a string that can be inserted into the
+
# command-line to launch oauth2-proxy.
providerSpecificOptions = {
azure = cfg: {
azure-tenant = cfg.azure.tenant;
···
} // (getProviderOptions cfg cfg.provider) // cfg.extraConfig;
mapConfig = key: attr:
+
lib.optionalString (attr != null && attr != []) (
+
if lib.isDerivation attr then mapConfig key (toString attr) else
+
if (builtins.typeOf attr) == "set" then lib.concatStringsSep " "
+
(lib.mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
+
if (builtins.typeOf attr) == "list" then lib.concatMapStringsSep " " (mapConfig key) attr else
+
if (builtins.typeOf attr) == "bool" then "--${key}=${lib.boolToString attr}" else
if (builtins.typeOf attr) == "string" then "--${key}='${attr}'" else
"--${key}=${toString attr}");
+
configString = lib.concatStringsSep " " (lib.mapAttrsToList mapConfig allConfig);
in
{
+
options.services.oauth2-proxy = {
+
enable = lib.mkEnableOption "oauth2-proxy";
+
package = lib.mkPackageOption pkgs "oauth2-proxy" { };
##############################################
# PROVIDER configuration
# Taken from: https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/providers.go
+
provider = lib.mkOption {
+
type = lib.types.enum [
"adfs"
"azure"
"bitbucket"
···
'';
};
+
approvalPrompt = lib.mkOption {
+
type = lib.types.enum ["force" "auto"];
default = "force";
description = ''
OAuth approval_prompt.
'';
};
+
clientID = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
description = ''
The OAuth Client ID.
'';
example = "123456.apps.googleusercontent.com";
};
+
oidcIssuerUrl = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
The OAuth issuer URL.
···
example = "https://login.microsoftonline.com/{TENANT_ID}/v2.0";
};
+
clientSecret = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
description = ''
The OAuth Client Secret.
'';
};
+
skipAuthRegexes = lib.mkOption {
+
type = lib.types.listOf lib.types.str;
default = [];
description = ''
Skip authentication for requests matching any of these regular
···
# XXX: Not clear whether these two options are mutually exclusive or not.
email = {
+
domains = lib.mkOption {
+
type = lib.types.listOf lib.types.str;
default = [];
description = ''
Authenticate emails with the specified domains. Use
···
'';
};
+
addresses = lib.mkOption {
+
type = lib.types.nullOr lib.types.lines;
default = null;
description = ''
Line-separated email addresses that are allowed to authenticate.
···
};
};
+
loginURL = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Authentication endpoint.
···
example = "https://provider.example.com/oauth/authorize";
};
+
redeemURL = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Token redemption endpoint.
···
example = "https://provider.example.com/oauth/token";
};
+
validateURL = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Access token validation endpoint.
···
example = "https://provider.example.com/user/emails";
};
+
redirectURL = lib.mkOption {
# XXX: jml suspects this is always necessary, but the command-line
# doesn't require it so making it optional.
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
The OAuth2 redirect URL.
···
};
azure = {
+
tenant = lib.mkOption {
+
type = lib.types.str;
default = "common";
description = ''
Go to a tenant-specific or common (tenant-independent) endpoint.
'';
};
+
resource = lib.mkOption {
+
type = lib.types.str;
description = ''
The resource that is protected.
'';
···
};
google = {
+
adminEmail = lib.mkOption {
+
type = lib.types.str;
description = ''
The Google Admin to impersonate for API calls.
···
'';
};
+
groups = lib.mkOption {
+
type = lib.types.listOf lib.types.str;
default = [];
description = ''
Restrict logins to members of these Google groups.
'';
};
+
serviceAccountJSON = lib.mkOption {
+
type = lib.types.path;
description = ''
The path to the service account JSON credentials.
'';
···
};
github = {
+
org = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Restrict logins to members of this organisation.
'';
};
+
team = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Restrict logins to members of this team.
···
####################################################
# UPSTREAM Configuration
+
upstream = lib.mkOption {
+
type = with lib.types; coercedTo str (x: [x]) (listOf str);
default = [];
description = ''
The http url(s) of the upstream endpoint or `file://`
···
'';
};
+
passAccessToken = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Pass OAuth access_token to upstream via X-Forwarded-Access-Token header.
'';
};
+
passBasicAuth = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream.
'';
};
+
basicAuthPassword = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
The password to set when passing the HTTP Basic Auth header.
'';
};
+
passHostHeader = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Pass the request Host Header to upstream.
'';
};
+
signatureKey = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
GAP-Signature request signature key.
···
};
cookie = {
+
domain = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Optional cookie domains to force cookies to (ie: `.yourcompany.com`).
···
example = ".yourcompany.com";
};
+
expire = lib.mkOption {
+
type = lib.types.str;
default = "168h0m0s";
description = ''
Expire timeframe for cookie.
'';
};
+
httpOnly = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Set HttpOnly cookie flag.
'';
};
+
name = lib.mkOption {
+
type = lib.types.str;
default = "_oauth2_proxy";
description = ''
The name of the cookie that the oauth_proxy creates.
'';
};
+
refresh = lib.mkOption {
# XXX: Unclear what the behavior is when this is not specified.
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Refresh the cookie after this duration; 0 to disable.
···
example = "168h0m0s";
};
+
secret = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
description = ''
The seed string for secure cookies.
'';
};
+
secure = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Set secure (HTTPS) cookie flag.
···
####################################################
# OAUTH2 PROXY configuration
+
httpAddress = lib.mkOption {
+
type = lib.types.str;
default = "http://127.0.0.1:4180";
description = ''
HTTPS listening address. This module does not expose the port by
···
};
htpasswd = {
+
file = lib.mkOption {
+
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Additionally authenticate against a htpasswd file. Entries must be
···
'';
};
+
displayForm = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Display username / password login form if an htpasswd file is provided.
···
};
};
+
customTemplatesDir = lib.mkOption {
+
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Path to custom HTML templates.
'';
};
+
reverseProxy = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
In case when running behind a reverse proxy, controls whether headers
···
'';
};
+
proxyPrefix = lib.mkOption {
+
type = lib.types.str;
default = "/oauth2";
description = ''
The url root path that this proxy should be nested under.
···
};
tls = {
+
enable = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Whether to serve over TLS.
'';
};
+
certificate = lib.mkOption {
+
type = lib.types.path;
description = ''
Path to certificate file.
'';
};
+
key = lib.mkOption {
+
type = lib.types.path;
description = ''
Path to private key file.
'';
};
+
httpsAddress = lib.mkOption {
+
type = lib.types.str;
default = ":443";
description = ''
`addr:port` to listen on for HTTPS clients.
···
};
};
+
requestLogging = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Log requests to stdout.
···
# UNKNOWN
# XXX: Is this mandatory? Is it part of another group? Is it part of the provider specification?
+
scope = lib.mkOption {
# XXX: jml suspects this is always necessary, but the command-line
# doesn't require it so making it optional.
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
OAuth scope specification.
'';
};
+
profileURL = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Profile access endpoint.
'';
};
+
setXauthrequest = lib.mkOption {
+
type = lib.types.nullOr lib.types.bool;
default = false;
description = ''
Set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode). Setting this to 'null' means using the upstream default (false).
'';
};
+
extraConfig = lib.mkOption {
default = {};
+
type = lib.types.attrsOf lib.types.anything;
description = ''
Extra config to pass to oauth2-proxy.
'';
};
+
keyFile = lib.mkOption {
+
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
oauth2-proxy allows passing sensitive configuration via environment variables.
···
OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
and specify the path here.
'';
+
example = "/run/keys/oauth2-proxy";
};
};
+
imports = [
+
(lib.mkRenamedOptionModule [ "services" "oauth2_proxy" ] [ "services" "oauth2-proxy" ])
+
];
+
config = lib.mkIf cfg.enable {
+
services.oauth2-proxy = lib.mkIf (cfg.keyFile != null) {
+
clientID = lib.mkDefault null;
+
clientSecret = lib.mkDefault null;
+
cookie.secret = lib.mkDefault null;
};
+
users.users.oauth2-proxy = {
description = "OAuth2 Proxy";
isSystemUser = true;
+
group = "oauth2-proxy";
};
+
users.groups.oauth2-proxy = {};
+
systemd.services.oauth2-proxy = {
description = "OAuth2 Proxy";
path = [ cfg.package ];
wantedBy = [ "multi-user.target" ];
···
after = [ "network-online.target" ];
serviceConfig = {
+
User = "oauth2-proxy";
Restart = "always";
ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
+
EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
};
};
+27 -28
nixos/modules/services/security/oauth2_proxy_nginx.nix nixos/modules/services/security/oauth2-proxy-nginx.nix
···
{ config, lib, ... }:
-
with lib;
let
-
cfg = config.services.oauth2_proxy.nginx;
in
{
-
options.services.oauth2_proxy.nginx = {
-
proxy = mkOption {
-
type = types.str;
-
default = config.services.oauth2_proxy.httpAddress;
-
defaultText = literalExpression "config.services.oauth2_proxy.httpAddress";
description = ''
-
The address of the reverse proxy endpoint for oauth2_proxy
'';
};
-
domain = mkOption {
-
type = types.str;
description = ''
-
The domain under which the oauth2_proxy will be accesible and the path of cookies are set to.
This setting must be set to ensure back-redirects are working properly
-
if oauth2-proxy is configured with {option}`services.oauth2_proxy.cookie.domain`
-
or multiple {option}`services.oauth2_proxy.nginx.virtualHosts` that are not on the same domain.
'';
};
-
virtualHosts = mkOption {
type = let
-
vhostSubmodule = types.submodule {
options = {
-
allowed_groups = mkOption {
-
type = types.nullOr (types.listOf types.str);
description = "List of groups to allow access to this vhost, or null to allow all.";
default = null;
};
-
allowed_emails = mkOption {
-
type = types.nullOr (types.listOf types.str);
description = "List of emails to allow access to this vhost, or null to allow all.";
default = null;
};
-
allowed_email_domains = mkOption {
-
type = types.nullOr (types.listOf types.str);
description = "List of email domains to allow access to this vhost, or null to allow all.";
default = null;
};
};
};
-
oldType = types.listOf types.str;
convertFunc = x:
-
lib.warn "services.oauth2_proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty {} x}"
lib.genAttrs x (_: {});
-
newType = types.attrsOf vhostSubmodule;
-
in types.coercedTo oldType convertFunc newType;
default = {};
example = {
"protected.foo.com" = {
···
};
};
-
config.services.oauth2_proxy = mkIf (cfg.virtualHosts != [] && (hasPrefix "127.0.0.1:" cfg.proxy)) {
enable = true;
};
-
config.services.nginx = mkIf (cfg.virtualHosts != [] && config.services.oauth2_proxy.enable) (mkMerge ([
{
virtualHosts.${cfg.domain}.locations."/oauth2/" = {
proxyPass = cfg.proxy;
···
'';
};
}
-
] ++ optional (cfg.virtualHosts != []) {
recommendedProxySettings = true; # needed because duplicate headers
} ++ (lib.mapAttrsToList (vhost: conf: {
virtualHosts.${vhost} = {
···
{ config, lib, ... }:
let
+
cfg = config.services.oauth2-proxy.nginx;
in
{
+
options.services.oauth2-proxy.nginx = {
+
proxy = lib.mkOption {
+
type = lib.types.str;
+
default = config.services.oauth2-proxy.httpAddress;
+
defaultText = lib.literalExpression "config.services.oauth2-proxy.httpAddress";
description = ''
+
The address of the reverse proxy endpoint for oauth2-proxy
'';
};
+
domain = lib.mkOption {
+
type = lib.types.str;
description = ''
+
The domain under which the oauth2-proxy will be accesible and the path of cookies are set to.
This setting must be set to ensure back-redirects are working properly
+
if oauth2-proxy is configured with {option}`services.oauth2-proxy.cookie.domain`
+
or multiple {option}`services.oauth2-proxy.nginx.virtualHosts` that are not on the same domain.
'';
};
+
virtualHosts = lib.mkOption {
type = let
+
vhostSubmodule = lib.types.submodule {
options = {
+
allowed_groups = lib.mkOption {
+
type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = "List of groups to allow access to this vhost, or null to allow all.";
default = null;
};
+
allowed_emails = lib.mkOption {
+
type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = "List of emails to allow access to this vhost, or null to allow all.";
default = null;
};
+
allowed_email_domains = lib.mkOption {
+
type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = "List of email domains to allow access to this vhost, or null to allow all.";
default = null;
};
};
};
+
oldType = lib.types.listOf lib.types.str;
convertFunc = x:
+
lib.warn "services.oauth2-proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty {} x}"
lib.genAttrs x (_: {});
+
newType = lib.types.attrsOf vhostSubmodule;
+
in lib.types.coercedTo oldType convertFunc newType;
default = {};
example = {
"protected.foo.com" = {
···
};
};
+
config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != [] && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
enable = true;
};
+
config.services.nginx = lib.mkIf (cfg.virtualHosts != [] && config.services.oauth2-proxy.enable) (lib.mkMerge ([
{
virtualHosts.${cfg.domain}.locations."/oauth2/" = {
proxyPass = cfg.proxy;
···
'';
};
}
+
] ++ lib.optional (cfg.virtualHosts != []) {
recommendedProxySettings = true; # needed because duplicate headers
} ++ (lib.mapAttrsToList (vhost: conf: {
virtualHosts.${vhost} = {