Skip to content

Argelbargel/external-ingress-auth

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Artifact Hub release license

External Ingress Authentication

External Ingress Authentication provides an external authentication-service for Kubernetes Ingress Controllers which allows to authenticate users and authorize requests based on group-membership and request-parameters like remote-ip, request-method and/or requested path.

External Ingress Authentication works perfectly with NGINX ingress controller via External Authentication.

Features

  • Authentication and Authorization for kubernetes ingresses.
  • Internal, file-based authentication backend
  • Or use your ldap-server for authentication; supports protocols ldap:// and ldaps://
  • Fine grained access control via flexible authorization rules - allows you to e.g. protect only some paths of the application behind your Ingress
  • Centralized rule-management for all ingresses in your cluster and/or ingress-specific authorization rules
  • HTTP response headers with username and matched groups for the backend.
  • Brute force protection blocking too many failed authentication requests
  • Log format in Plain-Text or JSON.

Documentation

Installation

The easiest way to install and configure the External Ingress Authentication service in your Kubernetes cluster is to use the provided Helm chart.

Configuration

Most configuration parameters are passed to the service-container via environment variables. Global authorization rules and the user- and group-definitions for htpasswd authentication must be mounted at the paths specified in the respective environment variables.

Environment Variables

Authentication

External Ingress Authentication can use an internal, file-based authentication backend and/or a ldap-server for authentication.

HtPasswd

HtPasswd authentication is modeled analog to Apache httpd's mod_authn_file and mod_authz_groupfile using a file generated by htpasswd for users and passwords and a separate file mapping users to groups.

Variable Default-Value Description
HTPASSWD_FILE_PATH ./config/.htpasswd specifies the location of a htpasswd-file containing usernames and passwords. If empty, the htpasswd-backend will not be used. The service expect this file to be utf-8 encoded.
HTPASSWD_GROUP_FILE_PATH optional specifies the location of a file mapping the users in the htpasswd-file to groups. It has the same format as the file used by Apache httpd's mod_authz_groupfile. If no path is specified, users authenticated by the htpasswd-backend are not mapped to groups. The service expect this file to be utf-8 encoded.
LDAP
Variable Required/Default-Value Description
LDAP_SERVER_URL optional specifies the uri to the ldap-server. If not specified, the ldap-backend will not be used
LDAP_BIND_DN required, if ldap enabled specifies the ldap-query used to authenticate an user. Must contain the placeholder {username} which is replaced by the username (e.g. cn={username},cn=Users,dn=example,dn=com)
LDAP_SEARCH_BASE required, if ldap enabled specifies the base-query used to search for users when determining their group membership (e.g. cn=Users,dn=example,dn=com)
LDAP_SEARCH_FILTER (sAMAccountName={username}) specifies the filter used to query users when determing their group membership. Must contain the placeholder {username} which is replaced with the given username when authenticating
LDAP_MANAGER_DN required, if ldap enabled specifies the User-DN used to query the LDAP-server to determine group-membership (e.g. cn=manager,dn=Users,dn=example,dn.com)
LDAP_MANAGER_PASSWORD required, if ldap enabled specified the Password for the Manager-User given in LDAP_MANAGER_DN
Authorization
Variable Required/Default-Value Description
AUTHORIZATION_RULES_PATH optional path to a file containing authorization rules; if none is supplied the default authorization-rule is used unless additional rules are supplied by ingress-configuration. The service expect this file to be utf-8 encoded.
AUTHORIZATION_INGRESS_RULES_ENABLED false whether authorization rules can be provided by ingresses or not. See security considerations concerning authorization rules provided by ingresses before enabling this!
AUTHORIZATION_INGRESS_RULES_SECRET required secret key an ingress must provide when sending authorization-rules to the service. See security considerations concerning authorization rules provided by ingresses for details. If no value is provided, the service generates a random secret on every (re-)start which can not be accessed.
Brute-Force-Protection
Variable Required/Default-Value Description
BRUTE_FORCE_PROTECTION_ENABLED true enables/disables the brute-force-protection which prevents too many login-attempts
BRUTE_FORCE_PROTECTION_MAX_FAILURE_COUNT 5 specifies after how many failed login attempts the IP is blocked by the protection
BRUTE_FORCE_PROTECTION_EXPIRATION_SECONDS 60 specifies the time window within which failed login attempts are counted and for how long an IP gets blocked
HTTPS/TLS
Variable Required/Default-Value Description
TLS_CERT optional specifies the path to the certificate used for TLS/HTTPS. If no certificate is specified, the service communicates via unsecured HTTP
TLS_KEY optional specifies the key for the certificate specified in TLS_CERT
Miscellaneous
Variable Required/Default-Value Description
AUTH_CACHE_TTL_SECONDS 15 specifies how long the authentication of users and selection of authorization-rules is cached within the service (see below)
GUNICORN_CMD_ARGS optional allows you to specify custom arguments for the gunicorn-server used by the service
LOG_LEVEL INFO specifies the log-level. Valid values are ERROR, WARN, INFO, DEBUG and TRACE.
LOG_FORMAT JSON specifies the log-format

Authorization Rules

Authentication backends are solely used to authenticate a user's credentials and to provide information about the user's group-memberships. All further authorization-restrictions (or lack thereof) are configured by rules declared in the config-file specified in AUTHORIZATION_RULES_PATH or in the ingress-configuration.

Authorization Rule Format

Authorization rules are declared in the format <hosts>:<ip-ranges>:<methods>:<paths>:<users>:<groups>:<groups-operator>:<users-groups-operator>. The parts have the following meaning:

Rule element Default-Value Description
<hosts> ** comma-separated list of ingress-hosts the rule applies to. Use * to match subdomains, e.g. *.example.com matches sub.example.com (but not example.com itself). The default value ** applies to all ingress-hosts
<ip-ranges> ** comma-separated list of ip-ranges. For the rule to apply, the remote-ip from which the request is made must be within the given ranges. The default value ** applies to any remote-ip
<methods> ** comma-separated list of http-methods. The rule only applies if a request is made with the given methods. The default-value ** applies to any method
<paths> ** comma-separated list of requested paths the rule applies to. The pattern is evaluated using PurePath#full_match(), so /public/** matches any path below /public/ and /downloads/* matches for any file below the path /downloads/. The defaul-value ** matches any path
<users> <authenticated> comma-separated list of usernames. To be authorized, an authenticated user must be in this list and/or one of the groups specified (see <users-groups-operator>). To block any request to a resource, use the special value <forbidden>. To allow public/unauthenticated-access to a resource use <public>. If the list contains <forbidden>or <public>, any further settings concerning group-membership etc. are ignored. Rules containing <forbidden> or <public> must specify non-wildcard values for either ip-ranges, methods or paths. The default-value <authenticated>, which is just and alias for **, allows access for all authenticated users
<groups> ** comma-separated list of groups. To be authorized, an authenticated user must be member of one or all of the specified groups - see <groups-operator> - and possibly in the list of users (see <users-groups-operator>). The default-value ** allows access for all authenticated users
<groups-operator> OR specifies whether an authenticated user must be member of all groups specified in <groups> (AND) or any of them (OR)
<users-groups-operator> AND specifies whether an authenticated user match the <users> and <groups> part of the rule (AND) or only one of them (OR)

Note that if any of the list-elements above contains the wildcards ** or <authenticated> any other element in the list is ignored (so **,value is equivalent to **).

Examples
Allow public, unauthenticated access

The rule **:**:**:/public/**:<public> grants public access to anything below /public/ on any host without authenticating against the authentication backends. Requests matching this rule are authorized even in the case that no authentication backends are configured

Block all requests to a resource

The rule **:**:**:/system/**:<forbidden> blocks all requests to anything below /system/ on any host without authenticating against the authentication backends.

Restrict access to users in some groups

The rule **:**:**:**:<authenticated>:group1,group2 restricts access to any resource to authenticated users who are member of group1 or group2

The rule **:**:**:**:<authenticated>:group1,group2:AND restricts access to any resource or authenticated users who are member of group1 and group2

Restrict access to specific users

The rule **:**:POST,PUT,DELETE:/admin/**:admin,operator restricts access for modifying requests below /admin/ to the users admin or operator

Combine users and groups

The rule **:**:PUT:/admin/**:admin,operator:editors restricts access for PUT-requests below /admin/ to either admin or operator or users in the group editors

The rule **:**:DELETE:/admin/**:admin,operator:cleaners:OR:AND allows access for DELETE-requests below /admin/ only to users admin or operator if the are also in the group cleaners

Host-specific rules

The rule example.com,*.example.com:172.100.0.1/24:**:**:<public> allows public access to example.com and all direct subdomains from within the range 172.100.0.1 - 172.100.0.254

The rule example.com:**:**:**:<authenticated>:Testers,Reviewers restricts requests to example.com to users in either group Testers or Reviewers

Default Authorization Rule

If no other rules match (or you did not provide any), requests are authorized against the rule **:**:**:**:<authenticated>:**:OR:AND - so unless other rules are supplied, all (and only) successfully authenticated users are authorized. To use the default-rule in the authorization rules file or ingress provided authorization rules you can simple use the shortcut <authenticated> for this default rule instead of the full rule-declaration above.

To make the this fallback explicit, it is recommended to always end your rules list with <authenticated>.

Authorization File Format

The authorization file may contain multiple rules separated by any (unescaped) whitespace-character.

Thus you may either specify multiple rules on one line:

**:**:**:/public:<public> **:**:**:/admin/**:admin <authenticated>

Or one rule per line:

**:**:**:/public:<public>
**:**:**:/admin/**:admin
<authenticated>

Rules are evaluated in the order that they are provided. The first rule matching all request-parameters (ingress-hostname, remote-ip, request-method and requested-path) is used to authorize the request.

You may add comments to the rules-file. Every line starting with # is regarded as a comment.

Escaping of separator characters

Any of the special separator characters used in the rules definition (:, , and whitespace) can be escaped using \<character, e.g. User\ containing a \:\ colon.

Usage

After installing the service in your cluster you have to configure your Ingress-resource to use the service for external authentication. Nginx Ingress Controllor provides a simple example for this setup.

The following assumes you're using ingress-nginx 0.9.0 or newer. For a detailed description of the annotations used see nginx-ingress-controller annotations.

Default Ingress Configuration

For simple user-authentication without additional authorization restrictions to specific groups or users, you simple add the annotation nginx.ingress.kubernetes.io/auth-url to your ingress:

---
kind: Ingress
metadata:
  name: external-auth-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/auth-url: <url to the service>/ # MUST end with /
    # recommended: cache responses of the authentication-service (see below for details)
    nginx.ingress.kubernetes.io/auth-cache-key: $http_authorization
    nginx.ingress.kubernetes.io/auth-cache-duration: 200 401 403 1m
    # optional: add this if you want to pass the name of the authenticated user to the secured service
    nginx.ingress.kubernetes.io/auth-response-headers: x-user
spec:
  rules:
  - host: secured-service.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: secured-service
            port: 
              number: 80

Caching Authorization Responses in the Ingress

To improve response-times you can configure the nginx ingress-controller to cache the responses of the authentication service so that no requests outside the ingress are required. In most use-cases enabling response-caching is recommended. To enable response-caching in the ingress, add the following annotations:

nginx.ingress.kubernetes.io/auth-cache-key: $http_authorization # uses the value of the authorization-header as cache-key
nginx.ingress.kubernetes.io/auth-cache-duration: 200 401 403 1m # caches all responses for one minute

Using Ingress-specific Authorization Rules

Depending on the auth-service's configuration you can provide ingress-specific authorization rules replacing those declared in the config-file of the service.

Security considerations

Ingress-specific rules are sent to the service using http headers. The service cannot discern between headers sent by the ingress-controller or by a client and passed through the ingress. Thus you have to ensure that all ingresses using external ingress authentication's service send the header X-Authorization-Rules when enabling ingress-specific authorization rules.

The requirement for the secret to be sent in the header X-External-Auth-Secret alongside the authorization rules for them to take effect is mainly meant as a reminder to ensure every ingress uses the annotation nginx.ingress.kubernetes.io/auth-proxy-set-headers and a ConfigMap containing the X-Authorization-Header. Everyone who has access to the secret's value (e.g. can access Secrets or whichever resource the secret's value is stored in in your cluster) will be able to send manipulated authorization rules unless your ingresses do provide a value for X-Authorization-Rules in the ingresses configuration.

To indicate that the rules configured in the auth-services should be used by the ingress it is sufficient to sent an empty value in X-Authorization-Rules; setting the value to e.g. # use default rules is more concise and readable, though.

Non-empty, valid ingress-specific authorization rules completely replace those declared in the config-file of the service for requests passed to the service by that ingress. If none of the rules provided by the ingress match, the default authorization rule is used to authorize a request. Nonetheless it is recommended to end your rules list with <authenticated> to make that fact explicit.

Ingress configuration

To provide additional rules, you have to specify them in a ConfigMap:

---
kind: Ingress
metadata:
  name: external-auth-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/auth-url: <url to the service>/ # MUST end with / 
    nginx.ingress.kubernetes.io/auth-proxy-set-headers: default/auth-headers
    # recommended: cache responses of the authentication-service (see below for details)
    nginx.ingress.kubernetes.io/auth-cache-key: $http_authorization
    nginx.ingress.kubernetes.io/auth-cache-duration: 200 401 403 1m
    # optional: add this if you want to pass the name and groups of the authenticated user to the secured service
    nginx.ingress.kubernetes.io/auth-response-headers: x-user, x-groups
  spec:
  rules:
  - host: secured-service.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: secured-service
            port: 
              number: 80

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: auth-headers
  namespace: default
data:"
  X-Authorization-Rules: "<rule1> <rule2> <authenticated>"
  X-External-Auth-Secret: "<secret>"

Be aware that you have to reference the ConfigMap using <namespace>/<name> in nginx.ingress.kubernetes.io/auth-proxy-set-headers - otherwise the ConfigMap will be searched in the ingresses namespace.

Response-Headers

On successful authentication/authorization the service returns the username and the authorized groups within the HTTP-headers X-User and X-Groups which can be passed through the ingress using the annotation nginx.ingress.kubernetes.io/auth-response-headers.

Caching within the service

The service itself caches authentication results and the selection of authorization-rules to prevent overloading the service or its authentication backends; by default this cache has a lifetime of 15 seconds; this can be changed via the environment variable AUTH_CACHE_TTL_SECONDS.

Authentication-Cache

The cache stores whether credentials were valid and the group-memberships of successfully authenticated users.

Rules-Cache

Selection of the authorization rules is cached based on ingress-host, remote-ip, http-method and requested path. While the selected rule is cached, whether an user is authorized to access a resource is always re-evaluated for every request.

Metrics

The service exports metrics in prometheus-format about it's operation at the endpoint /metrics. Additionally to the default-metrics collected by flask-prometheus-exporter, it exposes metrics about the authorization-requests it received per ingress-host and their status in auth_requests_total and about ips blocked by the brute-force-protection in blocked_ips_total.

License

Source code is licensed under MIT-License

Contributors

About

External Ingress Authentication provides external authentication for Kubernetes Ingress Controllers

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages

  • Python 92.9%
  • HTML 2.4%
  • CSS 2.4%
  • Dockerfile 2.0%
  • Shell 0.3%