# systemctl restart atomic-openshift-master-api atomic-openshift-master-controllers
The OpenShift Container Platform master includes a built-in OAuth server. Developers and administrators obtain OAuth access tokens to authenticate themselves to the API.
As an administrator, you can configure OAuth using the master configuration file to specify an identity provider. It is a best practice to configure your identity provider during advanced installation, but you can configure it after installation.
OpenShift Container Platform user names containing |
If you installed OpenShift Container Platform using the Quick Installation or Advanced Installation method, the Deny All identity provider is used by default, which denies access for all user names and passwords. To allow access, you must choose a different identity provider and configure the master configuration file appropriately (located at /etc/origin/master/master-config.yaml by default).
When you run a master without a configuration file, the Allow All identity provider is used by default, which allows any non-empty user name and password to log in. This is useful for testing purposes. To use other identity providers, or to modify any token, grant, or session options, you must run the master from a configuration file.
Roles need to be assigned to administer the setup with an external user. |
After making changes to an identity provider, you must restart the master services for the changes to take effect: # systemctl restart atomic-openshift-master-api atomic-openshift-master-controllers |
There are four parameters common to all identity providers:
Parameter | Description |
---|---|
|
The provider name is prefixed to provider user names to form an identity name. |
|
When true, unauthenticated token requests from non-web
clients (like the CLI) are sent a To prevent cross-site request forgery (CSRF) attacks against browser clients
Basic authentication challenges are only sent if a |
|
When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. Not supported by all identity providers. If you want users to be sent to a branded page before being redirected to
the identity provider’s login, then set |
|
Defines how new identities are mapped to users when they log in. Enter one of the following values:
|
When adding or changing identity providers, you can map identities from the new
provider to existing users by setting the mappingMethod parameter to
add .
|
OpenShift Container Platform supports configuring only a single identity provider. However, you can extend the basic authentication for more complex configurations such as LDAP failover.
You can use these parameters to define the identity provider during installation or after installation.
For initial advanced installations, the
Deny All identity provider is configured by default,
though it can be
overridden during installation using the
openshift_master_identity_providers
parameter, which is configurable in the inventory file.
Session options in the OAuth configuration are also configurable in the inventory file.
# htpasswd auth openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}] # Defining htpasswd users #openshift_master_htpasswd_users={'user1': '<pre-hashed password>', 'user2': '<pre-hashed password>'} # or #openshift_master_htpasswd_file=<path to local pre-generated htpasswd file> # Allow all auth #openshift_master_identity_providers=[{'name': 'allow_all', 'login': 'true', 'challenge': 'true', 'kind': 'AllowAllPasswordIdentityProvider'}] # LDAP auth #openshift_master_identity_providers=[{'name': 'my_ldap_provider', 'challenge': 'true', 'login': 'true', 'kind': 'LDAPPasswordIdentityProvider', 'attributes': {'id': ['dn'], 'email': ['mail'], 'name': ['cn'], 'preferredUsername': ['uid']}, 'bindDN': '', 'bindPassword': '', 'ca': '', 'insecure': 'false', 'url': 'ldap://ldap.example.com:389/ou=users,dc=example,dc=com?uid'}] # Configuring the ldap ca certificate (1) #openshift_master_ldap_ca=<ca text> # or #openshift_master_ldap_ca_file=<path to local ca file to use> # Available variables for configuring certificates for other identity providers: #openshift_master_openid_ca #openshift_master_openid_ca_file #openshift_master_request_header_ca #openshift_master_request_header_ca_file
1 | If you specify your CA certificate location in the
openshift_master_identity_providers parameter, do not specify a certificate
value in the openshift_master_ldap_ca parameter or path in the
openshift_master_ldap_ca_file parameter. |
You can configure the master host for authentication using your desired identity provider by modifying the master configuration file.
... oauthConfig: identityProviders: - name: htpasswd_auth challenge: true login: true mappingMethod: "claim" ...
When set to the default claim
value, OAuth will fail if the identity is
mapped to a previously-existing user name.
When using the lookup
mapping method, user provisioning is done by an external system, via the API.
Typically, identities are automatically mapped to users during login. The 'lookup' mapping method automatically
disables this automatic mapping, which requires you to provision users manually.
For more information on identity objects, see the Identity user API obejct.
If you are using the lookup
mapping method, use the following steps for each user after configuring
the identity provider:
Create an OpenShift Container Platform User, if not created already:
$ oc create user <username>
For example, the following command creates a OpenShift Container Platform User bob
:
$ oc create user bob
Create an OpenShift Container Platform Identity, if not created already. Use the name of the identity provider and the name that uniquely represents this identity in the scope of the identity provider:
$ oc create identity <identity-provider>:<user-id-from-identity-provider>
The <identity-provider>
is the name of the identity provider in the master configuration,
as shown in the appropriate identity provider section below.
For example, the following commands creates an Identity with identity provider ldap_provider
and the identity provider user name bob_s
.
$ oc create identity ldap_provider:bob_s
Create a user/identity mapping for the created user and identity:
$ oc create useridentitymapping <identity-provider>:<user-id-from-identity-provider> <username>
For example, the following command maps the identity to the user:
$ oc create useridentitymapping ldap_provider:bob_s bob
Set AllowAllPasswordIdentityProvider in the identityProviders
stanza to
allow any non-empty user name and password to log in.
oauthConfig: ... identityProviders: - name: my_allow_provider (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: AllowAllPasswordIdentityProvider
1 | This provider name is prefixed to provider user names to form an identity name. |
2 | When true, unauthenticated token requests from non-web clients (like
the CLI) are sent a WWW-Authenticate challenge header for this provider. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
Set DenyAllPasswordIdentityProvider in the identityProviders
stanza to
deny access for all user names and passwords.
oauthConfig: ... identityProviders: - name: my_deny_provider (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: DenyAllPasswordIdentityProvider
1 | This provider name is prefixed to provider user names to form an identity name. |
2 | When true, unauthenticated token requests from non-web clients (like the
CLI) are sent a WWW-Authenticate challenge header for this provider. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
Set HTPasswdPasswordIdentityProvider in the identityProviders
stanza to
validate user names and passwords against a flat file generated using
htpasswd
.
The # yum install httpd-tools |
OpenShift Container Platform supports the Bcrypt, SHA-1, and MD5 cryptographic hash
functions, and MD5 is the default for htpasswd
. Plaintext, encrypted text, and
other hash functions are not currently supported.
The flat file is reread if its modification time changes, without requiring a server restart.
To use the htpasswd command:
To create a flat file with a user name and hashed password, run:
$ htpasswd -c </path/to/users.htpasswd> <user_name>
Then, enter and confirm a clear-text password for the user. The command generates a hashed version of the password.
For example:
htpasswd -c users.htpasswd user1 New password: Re-type new password: Adding password for user user1
You can include the $ htpasswd -c -b <user_name> <password> For example: $ htpasswd -c -b file user1 MyPassword! Adding password for user user1 |
To add or update a login to the file, run:
$ htpasswd </path/to/users.htpasswd> <user_name>
To remove a login from the file, run:
$ htpasswd -D </path/to/users.htpasswd> <user_name>
oauthConfig: ... identityProviders: - name: my_htpasswd_provider (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: HTPasswdPasswordIdentityProvider file: /path/to/users.htpasswd (5)
1 | This provider name is prefixed to provider user names to form an identity name. |
2 | When true, unauthenticated token requests from non-web clients (like the
CLI) are sent a WWW-Authenticate challenge header for this provider. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | File generated using
htpasswd . |
Set KeystonePasswordIdentityProvider in the identityProviders
stanza to
validate user names and passwords against an OpenStack Keystone v3 server.
This enables shared authentication with an OpenStack server configured to store
users in an internal Keystone database.
oauthConfig: ... identityProviders: - name: my_keystone_provider (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: KeystonePasswordIdentityProvider domainName: default (5) url: http://keystone.example.com:5000 (6) ca: ca.pem (7) certFile: keystone.pem (8) keyFile: keystonekey.pem (9)
1 | This provider name is prefixed to provider user names to form an identity name. |
2 | When true, unauthenticated token requests from non-web clients (like the
CLI) are sent a WWW-Authenticate challenge header for this provider. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | Keystone domain name. In Keystone, usernames are domain-specific. Only a single domain is supported. |
6 | The URL to use to connect to the Keystone server (required). |
7 | Optional: Certificate bundle to use to validate server certificates for the configured URL. |
8 | Optional: Client certificate to present when making requests to the configured URL. |
9 | Key for the client certificate. Required if certFile is specified. |
Set LDAPPasswordIdentityProvider in the identityProviders
stanza to
validate user names and passwords against an LDAPv3 server, using simple bind
authentication.
If you require failover for your LDAP server, instead of following these steps, extend the basic authentication method by configuring SSSD for LDAP failover. |
During authentication, the LDAP directory is searched for an entry that matches the provided user name. If a single unique match is found, a simple bind is attempted using the distinguished name (DN) of the entry plus the provided password.
These are the steps taken:
Generate a search filter by combining the attribute and filter in the
configured url
with the user-provided user name.
Search the directory using the generated filter. If the search does not return exactly one entry, deny access.
Attempt to bind to the LDAP server using the DN of the entry retrieved from the search, and the user-provided password.
If the bind is unsuccessful, deny access.
If the bind is successful, build an identity using the configured attributes as the identity, email address, display name, and preferred user name.
The configured url
is an RFC 2255 URL, which specifies the LDAP host and
search parameters to use. The syntax of the URL is:
ldap://host:port/basedn?attribute?scope?filter
For the above example:
URL Component | Description |
---|---|
|
For regular LDAP, use the string |
|
The name and port of the LDAP server. Defaults to
|
|
The DN of the branch of the directory where all searches should start from. At the very least, this must be the top of your directory tree, but it could also specify a subtree in the directory. |
|
The attribute to search for. Although RFC 2255 allows a
comma-separated list of attributes, only the first attribute will be used, no
matter how many are provided. If no attributes are provided, the default is to
use |
|
The scope of the search. Can be either either |
|
A valid LDAP search filter. If not provided, defaults to
|
When doing searches, the attribute, filter, and provided user name are combined to create a search filter that looks like:
(&(<filter>)(<attribute>=<username>))
For example, consider a URL of:
ldap://ldap.example.com/o=Acme?cn?sub?(enabled=true)
When a client attempts to connect using a user name of bob
, the resulting
search filter will be (&(enabled=true)(cn=bob))
.
If the LDAP directory requires authentication to search, specify a bindDN
and
bindPassword
to use to perform the entry search.
oauthConfig: ... identityProviders: - name: "my_ldap_provider" (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: LDAPPasswordIdentityProvider attributes: id: (5) - dn email: (6) - mail name: (7) - cn preferredUsername: (8) - uid bindDN: "" (9) bindPassword: "" (10) ca: my-ldap-ca-bundle.crt (11) insecure: false (12) url: "ldap://ldap.example.com/ou=users,dc=acme,dc=com?uid" (13)
1 | This provider name is prefixed to the returned user ID to form an identity name. |
2 | When true, unauthenticated token requests from non-web clients (like the
CLI) are sent a WWW-Authenticate challenge header for this provider. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | List of attributes to use as the identity. First non-empty attribute is used. At least one attribute is required. If none of the listed attribute have a value, authentication fails. |
6 | List of attributes to use as the email address. First non-empty attribute is used. |
7 | List of attributes to use as the display name. First non-empty attribute is used. |
8 | List of attributes to use as the preferred user name when provisioning a user for this identity. First non-empty attribute is used. |
9 | Optional DN to use to bind during the search phase. |
10 | Optional password to use to bind during the search phase. This value may also be provided in an environment variable, external file, or encrypted file. |
11 | Certificate bundle to use to validate server certificates for the configured URL. If empty, system trusted roots are used. Only applies if insecure: false. |
12 | When true, no TLS connection is made to the server. When false,
ldaps:// URLs connect using TLS, and ldap:// URLs are upgraded to TLS. |
13 | An RFC 2255 URL which specifies the LDAP host and search parameters to use, as described above. |
To whitelist users for an LDAP integration, use the |
Basic Authentication is a generic backend integration mechanism that allows users to log in to OpenShift Container Platform with credentials validated against a remote identity provider.
Because basic authentication is generic, you can use this identity provider for advanced authentication configurations. You can configure LDAP failover or use the containerized basic authentication repository as a starting point for another advanced remote basic authentication configuration.
Basic authentication must use an HTTPS connection to the remote server to prevent potential snooping of the user ID and password and man-in-the-middle attacks. |
With BasicAuthPasswordIdentityProvider
configured, users send their user name
and password to OpenShift Container Platform, which then validates those credentials against
a remote server by making a server-to-server request, passing the credentials as
a Basic Auth header. This requires users to send their credentials to
OpenShift Container Platform during login.
Set BasicAuthPasswordIdentityProvider in the identityProviders
stanza to
validate user names and passwords against a remote server using a
server-to-server Basic authentication request. User names and passwords are
validated against a remote URL that is protected by Basic authentication and
returns JSON.
A 401
response indicates failed authentication.
A non-200
status, or the presence of a non-empty "error" key, indicates an
error:
{"error":"Error message"}
A 200
status with a sub
(subject) key indicates success:
{"sub":"userid"} (1)
1 | The subject must be unique to the authenticated user and must not be able to be modified. |
A successful response may optionally provide additional data, such as:
A display name using the name
key. For example:
{"sub":"userid", "name": "User Name", ...}
An email address using the email
key. For example:
{"sub":"userid", "email":"user@example.com", ...}
A preferred user name using the preferred_username
key. This is useful when
the unique, unchangeable subject is a database key or UID, and a more
human-readable name exists. This is used as a hint when provisioning the
OpenShift Container Platform user for the authenticated identity. For example:
{"sub":"014fbff9a07c", "preferred_username":"bob", ...}
oauthConfig: ... identityProviders: - name: my_remote_basic_auth_provider (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: BasicAuthPasswordIdentityProvider url: https://www.example.com/remote-idp (5) ca: /path/to/ca.file (6) certFile: /path/to/client.crt (7) keyFile: /path/to/client.key (8)
1 | This provider name is prefixed to the returned user ID to form an identity name. |
2 | When true, unauthenticated token requests from non-web clients (like the
CLI) are sent a WWW-Authenticate challenge header for this provider. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to a login page backed by this provider. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | URL accepting credentials in Basic authentication headers. |
6 | Optional: Certificate bundle to use to validate server certificates for the configured URL. |
7 | Optional: Client certificate to present when making requests to the configured URL. |
8 | Key for the client certificate. Required if certFile is specified. |
Set RequestHeaderIdentityProvider in the identityProviders
stanza to
identify users from request header values, such as X-Remote-User
. It is
typically used in combination with an authenticating proxy, which sets the
request header value. This is similar to how
the remote user plug-in in OpenShift Enterprise 2 allowed administrators to
provide Kerberos, LDAP, and many other forms of enterprise authentication.
You can also use the request header identity provider for advanced configurations such as SAML authentication.
For users to authenticate using this identity provider, they must access
https://<master>/oauth/authorize
(and subpaths) via an authenticating proxy.
To accomplish this, configure the OAuth server to redirect unauthenticated
requests for OAuth tokens to the proxy endpoint that proxies to https://<master>/oauth/authorize
.
To redirect unauthenticated requests from clients expecting browser-based login flows:
Set the login
parameter to true.
Set the provider.loginURL
parameter to the authenticating proxy URL that
will authenticate interactive clients and then proxy the request to https://<master>/oauth/authorize
.
To redirect unauthenticated requests from clients expecting WWW-Authenticate
challenges:
Set the challenge
parameter to true.
Set the provider.challengeURL
parameter to the authenticating proxy URL that
will authenticate clients expecting WWW-Authenticate
challenges and then proxy
the request to https://<master>/oauth/authorize
.
The provider.challengeURL
and provider.loginURL
parameters can include
the following tokens in the query portion of the URL:
${url}
is replaced with the current URL, escaped to be safe in a query parameter.
For example: https://www.example.com/sso-login?then=${url}
${query}
is replaced with the current query string, unescaped.
For example: https://www.example.com/auth-proxy/oauth/authorize?${query}
If you expect unauthenticated requests to reach the OAuth server, a |
oauthConfig: ... identityProviders: - name: my_request_header_provider (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: RequestHeaderIdentityProvider challengeURL: "https://www.example.com/challenging-proxy/oauth/authorize?${query}" (5) loginURL: "https://www.example.com/login-proxy/oauth/authorize?${query}" (6) clientCA: /path/to/client-ca.file (7) clientCommonNames: (8) - my-auth-proxy headers: (9) - X-Remote-User - SSO-User emailHeaders: (10) - X-Remote-User-Email nameHeaders: (11) - X-Remote-User-Display-Name preferredUsernameHeaders: (12) - X-Remote-User-Login
1 | This provider name is prefixed to the user name in the request header to form an identity name. |
2 | RequestHeaderIdentityProvider can only respond to clients that request
WWW-Authenticate challenges by redirecting to a configured challengeURL . The
configured URL should respond with a WWW-Authenticate challenge. |
3 | RequestHeaderIdentityProvider can only respond to clients requesting a
login flow by redirecting to a configured loginURL . The configured URL should
respond with a login flow. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | Optional: URL to redirect unauthenticated /oauth/authorize requests to,
that will authenticate browser-based clients and then proxy their request to https://<master>/oauth/authorize .
The URL that proxies to https://<master>/oauth/authorize must end with /authorize (with no trailing slash),
and also proxy subpaths, in order for OAuth approval flows to work properly.
${url} is replaced with the current URL, escaped to be safe in a query parameter.
${query} is replaced with the current query string. |
6 | Optional: URL to redirect unauthenticated /oauth/authorize requests to,
that will authenticate clients which expect WWW-Authenticate challenges, and then proxy them to https://<master>/oauth/authorize .
${url} is replaced with the current URL, escaped to be safe in a query parameter.
${query} is replaced with the current query string. |
7 | Optional: PEM-encoded certificate bundle. If set, a valid client certificate must be presented and validated against the certificate authorities in the specified file before the request headers are checked for user names. |
8 | Optional: list of common names (cn ). If set, a valid client certificate with
a Common Name (cn ) in the specified list must be presented before the request headers
are checked for user names. If empty, any Common Name is allowed. Can only be used in combination
with clientCA . |
9 | Header names to check, in order, for the user identity. The first header containing a value is used as the identity. Required, case-insensitive. |
10 | Header names to check, in order, for an email address. The first header containing a value is used as the email address. Optional, case-insensitive. |
11 | Header names to check, in order, for a display name. The first header containing a value is used as the display name. Optional, case-insensitive. |
12 | Header names to check, in order, for a preferred user name, if different than the immutable
identity determined from the headers specified in headers . The first header containing
a value is used as the preferred user name when provisioning. Optional, case-insensitive. |
This example configures an authentication proxy on the same host as the master. Having the proxy and master on the same host is merely a convenience and may not be suitable for your environment. For example, if you were already running a router on the master, port 443 would not be available.
It is also important to note that while this reference configuration uses Apache’s mod_auth_form, it is by no means required and other proxies can easily be used if the following requirements are met:
Block the X-Remote-User
header from client requests to prevent spoofing.
Enforce client certificate authentication in the RequestHeaderIdentityProvider configuration.
Require the X-Csrf-Token
header be set for all authentication request using the challenge flow.
Only the /oauth/authorize
endpoint and its subpaths should be proxied,
and redirects should not be rewritten to allow the backend server to send the client to the correct
location.
The URL that proxies to https://<master>/oauth/authorize
must end with /authorize
(with no trailing slash). For example:
https://proxy.example.com/login-proxy/authorize?…
→ https://<master>/oauth/authorize?…
Subpaths of the URL that proxies to https://<master>/oauth/authorize
must proxy to subpaths of https://<master>/oauth/authorize
. For example:
https://proxy.example.com/login-proxy/authorize/approve?…
→ https://<master>/oauth/authorize/approve?…
Installing the Prerequisites
The mod_auth_form module is shipped as part of the mod_session package that is found in the Optional channel:
# yum install -y httpd mod_ssl mod_session apr-util-openssl
Generate a CA for validating requests that submit the trusted header. This CA
should be used as the file name for clientCA
in the
master’s identity provider configuration.
# oc adm ca create-signer-cert \ --cert='/etc/origin/master/proxyca.crt' \ --key='/etc/origin/master/proxyca.key' \ --name='openshift-proxy-signer@1432232228' \ --serial='/etc/origin/master/proxyca.serial.txt'
The oc adm ca create-signer-cert
command generates a certificate that is valid
for five years. This can be altered with the --expire-days
option, but for
security reasons, it is recommended to not make it greater than this
value.
Run oc adm
commands only from the first master listed in the Ansible host inventory file,
by default /etc/ansible/hosts.
Generate a client certificate for the proxy. This can be done using any x509
certificate tooling. For convenience, the oc adm
CLI can be used:
# oc adm create-api-client-config \ --certificate-authority='/etc/origin/master/proxyca.crt' \ --client-dir='/etc/origin/master/proxy' \ --signer-cert='/etc/origin/master/proxyca.crt' \ --signer-key='/etc/origin/master/proxyca.key' \ --signer-serial='/etc/origin/master/proxyca.serial.txt' \ --user='system:proxy' (1) # pushd /etc/origin/master # cp master.server.crt /etc/pki/tls/certs/localhost.crt (2) # cp master.server.key /etc/pki/tls/private/localhost.key # cp ca.crt /etc/pki/CA/certs/ca.crt # cat proxy/system\:proxy.crt \ proxy/system\:proxy.key > \ /etc/pki/tls/certs/authproxy.pem # popd
1 | The user name can be anything, however it is useful to give it a descriptive name as it will appear in logs. |
2 | When running the authentication proxy on a different host name than the
master, it is important to generate a certificate that matches the host name
instead of using the default master certificate as shown above. The value for
masterPublicURL in the /etc/origin/master/master-config.yaml file
must be included in the X509v3 Subject Alternative Name in the certificate
that is specified for SSLCertificateFile . If a new certificate needs to be
created, the oc adm ca create-server-cert command can be used. |
The oc adm create-api-client-config
command generates a certificate that is
valid for two years. This can be altered with the --expire-days
option, but
for security reasons, it is recommended to not make it greater than
this value.
Run oc adm
commands only from the first master listed in the Ansible host inventory file,
by default /etc/ansible/hosts.
Configuring Apache
This proxy does not need to reside on the same
host as the master. It uses a client certificate to connect to the master, which
is configured to trust the X-Remote-User
header.
Create the certificate for the Apache configuration. The certificate that you
specify as the SSLProxyMachineCertificateFile
parameter value is the proxy’s
client cert that is used to authenticate the proxy to the server. It must use
TLS Web Client Authentication
as the extended key type.
Configure Apache per the following:
LoadModule auth_form_module modules/mod_auth_form.so LoadModule session_module modules/mod_session.so LoadModule request_module modules/mod_request.so # Nothing needs to be served over HTTP. This virtual host simply redirects to # HTTPS. <VirtualHost *:80> DocumentRoot /var/www/html RewriteEngine On RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R,L] </VirtualHost> <VirtualHost *:443> # This needs to match the certificates you generated. See the CN and X509v3 # Subject Alternative Name in the output of: # openssl x509 -text -in /etc/pki/tls/certs/localhost.crt ServerName www.example.com DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key SSLCACertificateFile /etc/pki/CA/certs/ca.crt SSLProxyEngine on SSLProxyCACertificateFile /etc/pki/CA/certs/ca.crt # It's critical to enforce client certificates on the Master. Otherwise # requests could spoof the X-Remote-User header by accessing the Master's # /oauth/authorize endpoint directly. SSLProxyMachineCertificateFile /etc/pki/tls/certs/authproxy.pem # Send all requests to the console RewriteEngine On RewriteRule ^/console(.*)$ https://%{HTTP_HOST}:8443/console$1 [R,L] # In order to using the challenging-proxy an X-Csrf-Token must be present. RewriteCond %{REQUEST_URI} ^/challenging-proxy RewriteCond %{HTTP:X-Csrf-Token} ^$ [NC] RewriteRule ^.* - [F,L] <Location /challenging-proxy/oauth/authorize> # Insert your backend server name/ip here. ProxyPass https://[MASTER]:8443/oauth/authorize AuthType basic </Location> <Location /login-proxy/oauth/authorize> # Insert your backend server name/ip here. ProxyPass https://[MASTER]:8443/oauth/authorize # mod_auth_form providers are implemented by mod_authn_dbm, mod_authn_file, # mod_authn_dbd, mod_authnz_ldap and mod_authn_socache. AuthFormProvider file AuthType form AuthName openshift ErrorDocument 401 /login.html </Location> <ProxyMatch /oauth/authorize> AuthUserFile /etc/origin/master/htpasswd AuthName openshift Require valid-user RequestHeader set X-Remote-User %{REMOTE_USER}s env=REMOTE_USER # For ldap: # AuthBasicProvider ldap # AuthLDAPURL "ldap://ldap.example.com:389/ou=People,dc=my-domain,dc=com?uid?sub?(objectClass=*)" # It's possible to remove the mod_auth_form usage and replace it with # something like mod_auth_kerb, mod_auth_gssapi or even mod_auth_mellon. # The former would be able to support both the login and challenge flows # from the Master. Mellon would likely only support the login flow. # For Kerberos # yum install mod_auth_gssapi # AuthType GSSAPI # GssapiCredStore keytab:/etc/httpd.keytab </ProxyMatch> </VirtualHost> RequestHeader unset X-Remote-User
Additional mod_auth_form Requirements
A sample login page is available from the
openshift_extras
repository. This file should be placed in the DocumentRoot
location
(/var/www/html by default).
Creating Users
At this point, you can create the users in the system Apache is using to store accounts information. In this example, file-backed authentication is used:
# yum -y install httpd-tools # touch /etc/origin/master/htpasswd # htpasswd /etc/origin/master/htpasswd <user_name>
Configuring the Master
The identityProviders
stanza in the
/etc/origin/master/master-config.yaml file must be updated as well:
identityProviders: - name: requestheader challenge: true login: true provider: apiVersion: v1 kind: RequestHeaderIdentityProvider challengeURL: "https://[MASTER]/challenging-proxy/oauth/authorize?${query}" loginURL: "https://[MASTER]/login-proxy/oauth/authorize?${query}" clientCA: /etc/origin/master/proxyca.crt headers: - X-Remote-User
Restarting Services
Finally, restart the following services:
# systemctl restart httpd # systemctl restart atomic-openshift-master-api atomic-openshift-master-controllers
Verifying the Configuration
Test by bypassing the proxy. You should be able to request a token if you supply the correct client certificate and header:
# curl -L -k -H "X-Remote-User: joe" \ --cert /etc/pki/tls/certs/authproxy.pem \ https://[MASTER]:8443/oauth/token/request
If you do not supply the client certificate, the request should be denied:
# curl -L -k -H "X-Remote-User: joe" \ https://[MASTER]:8443/oauth/token/request
This should show a redirect to the configured challengeURL
(with
additional query parameters):
# curl -k -v -H 'X-Csrf-Token: 1' \ '<masterPublicURL>/oauth/authorize?client_id=openshift-challenging-client&response_type=token'
This should show a 401 response with a WWW-Authenticate
basic challenge:
# curl -k -v -H 'X-Csrf-Token: 1' \ '<redirected challengeURL from step 3 +query>'
This should show a redirect with an access token:
# curl -k -v -u <your_user>:<your_password> \ -H 'X-Csrf-Token: 1' '<redirected_challengeURL_from_step_3 +query>'
Set GitHubIdentityProvider in the identityProviders
stanza to use
GitHub as an identity provider, using the
OAuth integration.
Using GitHub as an identity provider requires users to get a token using
|
Using GitHub as an identity provider allows any GitHub user to authenticate to your server.
You can limit authentication to members of specific GitHub organizations with the
|
oauthConfig: ... identityProviders: - name: github (1) challenge: false (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: GitHubIdentityProvider clientID: ... (5) clientSecret: ... (6) organizations: (7) - myorganization1 - myorganization2 teams: (8) - myorganization1/team-a - myorganization2/team-b
1 | This provider name is prefixed to the GitHub numeric user ID to form an identity name. It is also used to build the callback URL. |
2 | GitHubIdentityProvider cannot be used to send WWW-Authenticate
challenges. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to GitHub to log in. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | The client ID of a
registered GitHub OAuth
application. The application must be configured with a callback URL of
<master>/oauth2callback/<identityProviderName> . |
6 | The client secret issued by GitHub. This value may also be provided in an environment variable, external file, or encrypted file. |
7 | Optional list of organizations. If specified, only GitHub users that are members of
at least one of the listed organizations will be allowed to log in. If the GitHub OAuth
application configured in clientID is not owned by the organization, an organization
owner must grant third-party access in order to use this option. This can be done during
the first GitHub login by the organization’s administrator, or from the GitHub organization settings.
Cannot be used in combination with the teams field. |
8 | Optional list of teams. If specified, only GitHub users that are members of
at least one of the listed teams will be allowed to log in. If the GitHub OAuth
application configured in clientID is not owned by the team’s organization, an organization
owner must grant third-party access in order to use this option. This can be done during
the first GitHub login by the organization’s administrator, or from the GitHub organization settings.
Cannot be used in combination with the organizations field. |
Set GitLabIdentityProvider in the identityProviders
stanza to use
GitLab.com or any other GitLab instance as an identity provider, using the
OAuth integration.
The OAuth provider feature requires GitLab version 7.7.0 or higher.
oauthConfig: ... identityProviders: - name: gitlab (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: GitLabIdentityProvider url: ... (5) clientID: ... (6) clientSecret: ... (7) ca: ... (8)
1 | This provider name is prefixed to the GitLab numeric user ID to form an identity name. It is also used to build the callback URL. |
2 | When true, unauthenticated token requests from non-web clients (like
the CLI) are sent a WWW-Authenticate challenge header for this provider.
This uses the Resource Owner Password Credentials
grant flow to obtain an access token from GitLab. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to GitLab to log in. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | The host URL of a GitLab OAuth provider. This could either be https://gitlab.com/
or any other self hosted instance of GitLab. |
6 | The client ID of a
registered GitLab OAuth
application. The application must be configured with a callback URL of
<master>/oauth2callback/<identityProviderName> . |
7 | The client secret issued by GitLab. This value may also be provided in an environment variable, external file, or encrypted file. |
8 | CA is an optional trusted certificate authority bundle to use when making requests to the GitLab instance. If empty, the default system roots are used. |
Set GoogleIdentityProvider in the identityProviders
stanza to use Google
as an identity provider, using
Google’s OpenID
Connect integration.
Using Google as an identity provider requires users to get a token using
|
Using Google as an identity provider allows any Google user to authenticate to your server.
You can limit authentication to members of a specific hosted domain with the
|
oauthConfig: ... identityProviders: - name: google (1) challenge: false (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: GoogleIdentityProvider clientID: ... (5) clientSecret: ... (6) hostedDomain: "" (7)
1 | This provider name is prefixed to the Google numeric user ID to form an identity name. It is also used to build the redirect URL. |
2 | GoogleIdentityProvider cannot be used to send WWW-Authenticate
challenges. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to Google to log in. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | The client ID of a registered
Google project. The project must be configured with a redirect URI of
<master>/oauth2callback/<identityProviderName> . |
6 | The client secret issued by Google. This value may also be provided in an environment variable, external file, or encrypted file. |
7 | Optional hosted domain to restrict sign-in accounts to. If empty, any Google account is allowed to authenticate. |
Set OpenIDIdentityProvider in the identityProviders
stanza to integrate
with an OpenID Connect identity provider using an
Authorization Code Flow.
ID Token and UserInfo decryptions are not supported. |
By default, the openid scope is requested. If required, extra scopes can be
specified in the extraScopes
field.
Claims are read from the JWT id_token
returned from the OpenID identity
provider and, if specified, from the JSON returned by the UserInfo
URL.
At least one claim must be configured to use as the user’s identity. The
standard identity claim is sub
.
You can also indicate which claims to use as the user’s preferred user name, display name, and email address. If multiple claims are specified, the first one with a non-empty value is used. The standard claims are:
sub
|
Short for "subject identifier." The remote identity for the user at the issuer. |
preferred_username
|
The preferred user name when provisioning a user. A
shorthand name that the user wants to be referred to as, such as |
email
|
Email address. |
name
|
Display name. |
See the OpenID claims documentation for more information.
Using an OpenID Connect identity provider requires users to get a token using
|
oauthConfig: ... identityProviders: - name: my_openid_connect (1) challenge: true (2) login: true (3) mappingMethod: claim (4) provider: apiVersion: v1 kind: OpenIDIdentityProvider clientID: ... (5) clientSecret: ... (6) claims: id: (7) - sub preferredUsername: - preferred_username name: - name email: - email urls: authorize: https://myidp.example.com/oauth2/authorize (8) token: https://myidp.example.com/oauth2/token (9)
1 | This provider name is prefixed to the value of the identity claim to form an identity name. It is also used to build the redirect URL. |
2 | When true, unauthenticated token requests from non-web clients (like
the CLI) are sent a WWW-Authenticate challenge header for this provider.
This requires the OpenID provider to support the
Resource Owner Password Credentials grant flow. |
3 | When true, unauthenticated token requests from web clients (like the web console) are redirected to the authorize URL to log in. |
4 | Controls how mappings are established between this provider’s identities and user objects, as described above. |
5 | The client ID of a client registered with the OpenID provider. The client
must be allowed to redirect to <master>/oauth2callback/<identityProviderName> . |
6 | The client secret. This value may also be provided in an environment variable, external file, or encrypted file. |
7 | List of claims to use as the identity. First non-empty claim is used. At
least one claim is required. If none of the listed claims have a value,
authentication fails. For example, this uses the value of the sub claim in the returned id_token as the user’s identity. |
8 | Authorization Endpoint
described in the OpenID spec. Must use https . |
9 | Token Endpoint
described in the OpenID spec. Must use https . |
A custom certificate bundle, extra scopes, extra authorization request
parameters, and userInfo
URL can also be specified:
oauthConfig: ... identityProviders: - name: my_openid_connect challenge: false login: true mappingMethod: claim provider: apiVersion: v1 kind: OpenIDIdentityProvider clientID: ... clientSecret: ... ca: my-openid-ca-bundle.crt (1) extraScopes: (2) - email - profile extraAuthorizeParameters: (3) include_granted_scopes: "true" claims: id: (4) - custom_id_claim - sub preferredUsername: (5) - preferred_username - email name: (6) - nickname - given_name - name email: (7) - custom_email_claim - email urls: authorize: https://myidp.example.com/oauth2/authorize token: https://myidp.example.com/oauth2/token userInfo: https://myidp.example.com/oauth2/userinfo (8)
1 | Certificate bundle to use to validate server certificates for the configured URLs. If empty, system trusted roots are used. |
2 | Optional list of scopes to request, in addition to the openid scope, during the authorization token request. |
3 | Optional map of extra parameters to add to the authorization token request. |
4 | List of claims to use as the identity. First non-empty claim is used. At least one claim is required. If none of the listed claims have a value, authentication fails. |
5 | List of claims to use as the preferred user name when provisioning a user for this identity. First non-empty claim is used. |
6 | List of claims to use as the display name. First non-empty claim is used. |
7 | List of claims to use as the email address. First non-empty claim is used. |
8 | UserInfo Endpoint described in the OpenID spec. Must use https . |
The OAuth server generates two kinds of tokens:
Access tokens |
Longer-lived tokens that grant access to the API. |
Authorize codes |
Short-lived tokens whose only use is to be exchanged for an access token. |
Use the tokenConfig
stanza to set token options:
oauthConfig: ... tokenConfig: accessTokenMaxAgeSeconds: 86400 (1) authorizeTokenMaxAgeSeconds: 300 (2)
1 | Set accessTokenMaxAgeSeconds to control the lifetime of access tokens.
The default lifetime is 24 hours. |
2 | Set authorizeTokenMaxAgeSeconds to control the lifetime of authorize
codes. The default lifetime is five minutes. |
You can override the |
When the OAuth server receives token requests for a client to which the user has not previously granted permission, the action that the OAuth server takes is dependent on the OAuth client’s grant strategy.
When the OAuth client requesting token does not provide its own grant strategy,
the server-wide default strategy is used. To configure the default strategy,
set the method
value in the grantConfig
stanza. Valid values for
method
are:
auto
|
Auto-approve the grant and retry the request. |
prompt
|
Prompt the user to approve or deny the grant. |
deny
|
Auto-deny the grant and return a failure error to the client. |
oauthConfig: ... grantConfig: method: auto
The OAuth server uses a signed and encrypted cookie-based session during login and redirect flows.
Use the sessionConfig
stanza to set session options:
oauthConfig: ... sessionConfig: sessionMaxAgeSeconds: 300 (1) sessionName: ssn (2) sessionSecretsFile: "..." (3)
1 | Controls the maximum age of a session; sessions auto-expire once a token request is complete. If auto-grant is not enabled, sessions must last as long as the user is expected to take to approve or reject a client authorization request. |
2 | Name of the cookie used to store the session. |
3 | File name containing serialized SessionSecrets object. If empty, a
random signing and encryption secret is generated at each server start. |
If no sessionSecretsFile
is specified, a random signing and encryption
secret is generated at each start of the master server. This means that any
logins in progress will have their sessions invalidated if the master is
restarted. It also means they will not
be able to decode sessions generated by one of the other masters.
To specify the signing and encryption secret to use, specify a
sessionSecretsFile
. This allows you separate secret values from the
configuration file and keep the configuration file distributable, for example
for debugging purposes.
Multiple secrets can be specified in the sessionSecretsFile
to enable
rotation. New sessions are signed and encrypted using the first secret in the
list. Existing sessions are decrypted and authenticated by each secret until one
succeeds.
apiVersion: v1 kind: SessionSecrets secrets: (1) - authentication: "..." (2) encryption: "..." (3) - authentication: "..." encryption: "..." ...
1 | List of secrets used to authenticate and encrypt cookie sessions. At least one secret must be specified. Each secret must set an authentication and encryption secret. |
2 | Signing secret, used to authenticate sessions using HMAC. Recommended to use a secret with 32 or 64 bytes. |
3 | Encrypting secret, used to encrypt sessions. Must be 16, 24, or 32 characters long, to select AES-128, AES-192, or AES-256. |
OpenShift Container Platform implements a user agent that can be used to prevent an application developer’s CLI accessing the OpenShift Container Platform API.
User agents for the OpenShift Container Platform CLI are constructed from a set of values within OpenShift Container Platform:
<command>/<version> (<platform>/<architecture>) <client>/<git_commit>
So, for example, when:
<command> = oc
<version> = The client version. For example, v3.3.0
. Requests made against the Kubernetes
API at /api
receive the Kubernetes version, while requests made against the
OpenShift Container Platform API at /oapi
receive the OpenShift Container Platform version (as specified
by oc version
)
<platform> = linux
<architecture> = amd64
<client> = openshift
, or kubernetes
depending on if the request is made against the Kubernetes API at /api
, or the OpenShift Container Platform API at /oapi
<git_commit> = The Git commit of the client version (for example, f034127
)
the user agent will be:
oc/v3.3.0 (linux/amd64) openshift/f034127
As an OpenShift Container Platform administrator, you can prevent clients from accessing the
API with the userAgentMatching
configuration setting of a master
configuration. So, if a client is using a particular library or
binary, they will be prevented from accessing the API.
The following user agent example denies the Kubernetes 1.2 client binary, OpenShift Origin 1.1.3 binary, and the POST and PUT httpVerbs:
policyConfig: userAgentMatchingConfig: defaultRejectionMessage: "Your client is too old. Go to https://example.org to update it." deniedClients: - regex: '\w+/v(?:(?:1\.1\.1)|(?:1\.0\.1)) \(.+/.+\) openshift/\w{7}' - regex: '\w+/v(?:1\.1\.3) \(.+/.+\) openshift/\w{7}' httpVerbs: - POST - PUT - regex: '\w+/v1\.2\.0 \(.+/.+\) kubernetes/\w{7}' httpVerbs: - POST - PUT requiredClients: null
Administrators can also deny clients that do not exactly match the expected clients:
policyConfig: userAgentMatchingConfig: defaultRejectionMessage: "Your client is too old. Go to https://example.org to update it." deniedClients: [] requiredClients: - regex: '\w+/v1\.1\.3 \(.+/.+\) openshift/\w{7}' - regex: '\w+/v1\.2\.0 \(.+/.+\) kubernetes/\w{7}' httpVerbs: - POST - PUT
When the client’s user agent mismatches the configuration, errors occur. To ensure that mutating requests match, enforce a whitelist. Rules are mapped to specific verbs, so you can ban mutating requests while allowing non-mutating requests. |