Unverified Commit a19b4b84 authored by Sandro Jäckel's avatar Sandro Jäckel
Browse files

nixos/oauth2-proxy{,-nginx}: remove with lib

parent 34f87f39
Loading
Loading
Loading
Loading
+19 −20
Original line number Diff line number Diff line
{ config, lib, ... }:
with lib;
let
  cfg = config.services.oauth2-proxy.nginx;
in
{
  options.services.oauth2-proxy.nginx = {
    proxy = mkOption {
      type = types.str;
    proxy = lib.mkOption {
      type = lib.types.str;
      default = config.services.oauth2-proxy.httpAddress;
      defaultText = literalExpression "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 = mkOption {
      type = types.str;
    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
@@ -24,33 +23,33 @@ in
      '';
    };

    virtualHosts = mkOption {
    virtualHosts = lib.mkOption {
      type = let
        vhostSubmodule = types.submodule {
        vhostSubmodule = lib.types.submodule {
          options = {
            allowed_groups = mkOption {
              type = types.nullOr (types.listOf types.str);
            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 = mkOption {
              type = types.nullOr (types.listOf types.str);
            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 = mkOption {
              type = types.nullOr (types.listOf types.str);
            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 = types.listOf types.str;
        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 = types.attrsOf vhostSubmodule;
      in types.coercedTo oldType convertFunc newType;
        newType = lib.types.attrsOf vhostSubmodule;
      in lib.types.coercedTo oldType convertFunc newType;
      default = {};
      example = {
        "protected.foo.com" = {
@@ -65,11 +64,11 @@ in
    };
  };

  config.services.oauth2-proxy = mkIf (cfg.virtualHosts != [] && (hasPrefix "127.0.0.1:" cfg.proxy)) {
  config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != [] && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
    enable = true;
  };

  config.services.nginx = mkIf (cfg.virtualHosts != [] && config.services.oauth2-proxy.enable) (mkMerge ([
  config.services.nginx = lib.mkIf (cfg.virtualHosts != [] && config.services.oauth2-proxy.enable) (lib.mkMerge ([
    {
      virtualHosts.${cfg.domain}.locations."/oauth2/" = {
        proxyPass = cfg.proxy;
@@ -79,7 +78,7 @@ in
        '';
      };
    }
  ] ++ optional (cfg.virtualHosts != []) {
  ] ++ lib.optional (cfg.virtualHosts != []) {
    recommendedProxySettings = true; # needed because duplicate headers
  } ++ (lib.mapAttrsToList (vhost: conf: {
    virtualHosts.${vhost} = {
+112 −113
Original line number Diff line number Diff line
{ config, lib, pkgs, ... }:

with lib;
let
  cfg = config.services.oauth2-proxy;

@@ -71,28 +70,28 @@ let
  } // (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
  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 = concatStringsSep " " (mapAttrsToList mapConfig allConfig);
  configString = lib.concatStringsSep " " (lib.mapAttrsToList mapConfig allConfig);
in
{
  options.services.oauth2-proxy = {
    enable = mkEnableOption "oauth2-proxy";
    enable = lib.mkEnableOption "oauth2-proxy";

    package = mkPackageOption pkgs "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 = mkOption {
      type = types.enum [
    provider = lib.mkOption {
      type = lib.types.enum [
        "adfs"
        "azure"
        "bitbucket"
@@ -114,24 +113,24 @@ in
      '';
    };

    approvalPrompt = mkOption {
      type = types.enum ["force" "auto"];
    approvalPrompt = lib.mkOption {
      type = lib.types.enum ["force" "auto"];
      default = "force";
      description = ''
        OAuth approval_prompt.
      '';
    };

    clientID = mkOption {
      type = types.nullOr types.str;
    clientID = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      description = ''
        The OAuth Client ID.
      '';
      example = "123456.apps.googleusercontent.com";
    };

    oidcIssuerUrl = mkOption {
      type = types.nullOr types.str;
    oidcIssuerUrl = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        The OAuth issuer URL.
@@ -139,15 +138,15 @@ in
      example = "https://login.microsoftonline.com/{TENANT_ID}/v2.0";
    };

    clientSecret = mkOption {
      type = types.nullOr types.str;
    clientSecret = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      description = ''
        The OAuth Client Secret.
      '';
    };

    skipAuthRegexes = mkOption {
     type = types.listOf types.str;
    skipAuthRegexes = lib.mkOption {
     type = lib.types.listOf lib.types.str;
     default = [];
     description = ''
       Skip authentication for requests matching any of these regular
@@ -157,8 +156,8 @@ in

    # XXX: Not clear whether these two options are mutually exclusive or not.
    email = {
      domains = mkOption {
        type = types.listOf types.str;
      domains = lib.mkOption {
        type = lib.types.listOf lib.types.str;
        default = [];
        description = ''
          Authenticate emails with the specified domains. Use
@@ -166,8 +165,8 @@ in
        '';
      };

      addresses = mkOption {
        type = types.nullOr types.lines;
      addresses = lib.mkOption {
        type = lib.types.nullOr lib.types.lines;
        default = null;
        description = ''
          Line-separated email addresses that are allowed to authenticate.
@@ -175,8 +174,8 @@ in
      };
    };

    loginURL = mkOption {
      type = types.nullOr types.str;
    loginURL = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        Authentication endpoint.
@@ -188,8 +187,8 @@ in
      example = "https://provider.example.com/oauth/authorize";
    };

    redeemURL = mkOption {
      type = types.nullOr types.str;
    redeemURL = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        Token redemption endpoint.
@@ -201,8 +200,8 @@ in
      example = "https://provider.example.com/oauth/token";
    };

    validateURL = mkOption {
      type = types.nullOr types.str;
    validateURL = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        Access token validation endpoint.
@@ -214,10 +213,10 @@ in
      example = "https://provider.example.com/user/emails";
    };

    redirectURL = mkOption {
    redirectURL = lib.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;
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        The OAuth2 redirect URL.
@@ -226,16 +225,16 @@ in
    };

    azure = {
      tenant = mkOption {
        type = types.str;
      tenant = lib.mkOption {
        type = lib.types.str;
        default = "common";
        description = ''
          Go to a tenant-specific or common (tenant-independent) endpoint.
        '';
      };

      resource = mkOption {
        type = types.str;
      resource = lib.mkOption {
        type = lib.types.str;
        description = ''
          The resource that is protected.
        '';
@@ -243,8 +242,8 @@ in
    };

    google = {
      adminEmail = mkOption {
        type = types.str;
      adminEmail = lib.mkOption {
        type = lib.types.str;
        description = ''
          The Google Admin to impersonate for API calls.

@@ -256,16 +255,16 @@ in
        '';
      };

      groups = mkOption {
        type = types.listOf types.str;
      groups = lib.mkOption {
        type = lib.types.listOf lib.types.str;
        default = [];
        description = ''
          Restrict logins to members of these Google groups.
        '';
      };

      serviceAccountJSON = mkOption {
        type = types.path;
      serviceAccountJSON = lib.mkOption {
        type = lib.types.path;
        description = ''
          The path to the service account JSON credentials.
        '';
@@ -273,16 +272,16 @@ in
    };

    github = {
      org = mkOption {
        type = types.nullOr types.str;
      org = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        default = null;
        description = ''
          Restrict logins to members of this organisation.
        '';
      };

      team = mkOption {
        type = types.nullOr types.str;
      team = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        default = null;
        description = ''
          Restrict logins to members of this team.
@@ -293,8 +292,8 @@ in

    ####################################################
    # UPSTREAM Configuration
    upstream = mkOption {
      type = with types; coercedTo str (x: [x]) (listOf str);
    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://`
@@ -302,40 +301,40 @@ in
      '';
    };

    passAccessToken = mkOption {
      type = types.bool;
    passAccessToken = lib.mkOption {
      type = lib.types.bool;
      default = false;
      description = ''
        Pass OAuth access_token to upstream via X-Forwarded-Access-Token header.
      '';
    };

    passBasicAuth = mkOption {
      type = types.bool;
    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 = mkOption {
      type = types.nullOr types.str;
    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 = mkOption {
      type = types.bool;
    passHostHeader = lib.mkOption {
      type = lib.types.bool;
      default = true;
      description = ''
        Pass the request Host Header to upstream.
      '';
    };

    signatureKey = mkOption {
      type = types.nullOr types.str;
    signatureKey = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        GAP-Signature request signature key.
@@ -344,8 +343,8 @@ in
    };

    cookie = {
      domain = mkOption {
        type = types.nullOr types.str;
      domain = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        default = null;
        description = ''
          Optional cookie domains to force cookies to (ie: `.yourcompany.com`).
@@ -355,33 +354,33 @@ in
        example = ".yourcompany.com";
      };

      expire = mkOption {
        type = types.str;
      expire = lib.mkOption {
        type = lib.types.str;
        default = "168h0m0s";
        description = ''
          Expire timeframe for cookie.
        '';
      };

      httpOnly = mkOption {
        type = types.bool;
      httpOnly = lib.mkOption {
        type = lib.types.bool;
        default = true;
        description = ''
          Set HttpOnly cookie flag.
        '';
      };

      name = mkOption {
        type = types.str;
      name = lib.mkOption {
        type = lib.types.str;
        default = "_oauth2_proxy";
        description = ''
          The name of the cookie that the oauth_proxy creates.
        '';
      };

      refresh = mkOption {
      refresh = lib.mkOption {
        # XXX: Unclear what the behavior is when this is not specified.
        type = types.nullOr types.str;
        type = lib.types.nullOr lib.types.str;
        default = null;
        description = ''
          Refresh the cookie after this duration; 0 to disable.
@@ -389,15 +388,15 @@ in
        example = "168h0m0s";
      };

      secret = mkOption {
        type = types.nullOr types.str;
      secret = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        description = ''
          The seed string for secure cookies.
        '';
      };

      secure = mkOption {
        type = types.bool;
      secure = lib.mkOption {
        type = lib.types.bool;
        default = true;
        description = ''
          Set secure (HTTPS) cookie flag.
@@ -408,8 +407,8 @@ in
    ####################################################
    # OAUTH2 PROXY configuration

    httpAddress = mkOption {
      type = types.str;
    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
@@ -419,8 +418,8 @@ in
    };

    htpasswd = {
      file = mkOption {
        type = types.nullOr types.path;
      file = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        description = ''
          Additionally authenticate against a htpasswd file. Entries must be
@@ -428,8 +427,8 @@ in
        '';
      };

      displayForm = mkOption {
        type = types.bool;
      displayForm = lib.mkOption {
        type = lib.types.bool;
        default = true;
        description = ''
          Display username / password login form if an htpasswd file is provided.
@@ -437,16 +436,16 @@ in
      };
    };

    customTemplatesDir = mkOption {
      type = types.nullOr types.path;
    customTemplatesDir = lib.mkOption {
      type = lib.types.nullOr lib.types.path;
      default = null;
      description = ''
        Path to custom HTML templates.
      '';
    };

    reverseProxy = mkOption {
      type = types.bool;
    reverseProxy = lib.mkOption {
      type = lib.types.bool;
      default = false;
      description = ''
        In case when running behind a reverse proxy, controls whether headers
@@ -456,8 +455,8 @@ in
      '';
    };

    proxyPrefix = mkOption {
      type = types.str;
    proxyPrefix = lib.mkOption {
      type = lib.types.str;
      default = "/oauth2";
      description = ''
        The url root path that this proxy should be nested under.
@@ -465,30 +464,30 @@ in
    };

    tls = {
      enable = mkOption {
        type = types.bool;
      enable = lib.mkOption {
        type = lib.types.bool;
        default = false;
        description = ''
          Whether to serve over TLS.
        '';
      };

      certificate = mkOption {
        type = types.path;
      certificate = lib.mkOption {
        type = lib.types.path;
        description = ''
          Path to certificate file.
        '';
      };

      key = mkOption {
        type = types.path;
      key = lib.mkOption {
        type = lib.types.path;
        description = ''
          Path to private key file.
        '';
      };

      httpsAddress = mkOption {
        type = types.str;
      httpsAddress = lib.mkOption {
        type = lib.types.str;
        default = ":443";
        description = ''
          `addr:port` to listen on for HTTPS clients.
@@ -500,8 +499,8 @@ in
      };
    };

    requestLogging = mkOption {
      type = types.bool;
    requestLogging = lib.mkOption {
      type = lib.types.bool;
      default = true;
      description = ''
        Log requests to stdout.
@@ -512,42 +511,42 @@ in
    # UNKNOWN

    # XXX: Is this mandatory? Is it part of another group? Is it part of the provider specification?
    scope = mkOption {
    scope = lib.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;
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        OAuth scope specification.
      '';
    };

    profileURL = mkOption {
      type = types.nullOr types.str;
    profileURL = lib.mkOption {
      type = lib.types.nullOr lib.types.str;
      default = null;
      description = ''
        Profile access endpoint.
      '';
    };

    setXauthrequest = mkOption {
      type = types.nullOr types.bool;
    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 = mkOption {
    extraConfig = lib.mkOption {
      default = {};
      type = types.attrsOf types.anything;
      type = lib.types.attrsOf lib.types.anything;
      description = ''
        Extra config to pass to oauth2-proxy.
      '';
    };

    keyFile = mkOption {
      type = types.nullOr types.path;
    keyFile = lib.mkOption {
      type = lib.types.nullOr lib.types.path;
      default = null;
      description = ''
        oauth2-proxy allows passing sensitive configuration via environment variables.
@@ -560,14 +559,14 @@ in
  };

  imports = [
    (mkRenamedOptionModule [ "services" "oauth2_proxy" ] [ "services" "oauth2-proxy" ])
    (lib.mkRenamedOptionModule [ "services" "oauth2_proxy" ] [ "services" "oauth2-proxy" ])
  ];

  config = mkIf cfg.enable {
    services.oauth2-proxy = mkIf (cfg.keyFile != null) {
      clientID = mkDefault null;
      clientSecret = mkDefault null;
      cookie.secret = mkDefault null;
  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 = {
@@ -589,7 +588,7 @@ in
        User = "oauth2-proxy";
        Restart = "always";
        ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
        EnvironmentFile = mkIf (cfg.keyFile != null) cfg.keyFile;
        EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
      };
    };