.. _oauth2: ============== OAuth2 Support ============== Kubernetes Web View support OAuth2 for protecting its web frontend. Use the following environment variables to enable it: ``OAUTH2_AUTHORIZE_URL`` OAuth 2 authorization endpoint URL, e.g. https://oauth2.example.org/authorize ``OAUTH2_ACCESS_TOKEN_URL`` Token endpoint URL for the OAuth 2 Authorization Code Grant flow, e.g. https://oauth2.example.org/token ``OAUTH2_CLIENT_ID`` OAuth 2 client ID ``OAUTH2_CLIENT_ID_FILE`` Path to file containing the client ID. Use this instead of ``OAUTH2_CLIENT_ID`` to read the client ID dynamically from file. ``OAUTH2_CLIENT_SECRET`` OAuth 2 client secret ``OAUTH2_CLIENT_SECRET_FILE`` Path to file containing the client secret. Use this instead of ``OAUTH2_CLIENT_SECRET`` to read the client secret dynamically from file. ``SESSION_SECRET_KEY`` Secret to encrypt the session cookie. Must be 32 bytes base64-encoded. Use ``cryptography.fernet.Fernet.generate_key()`` to generate such a key. ``OAUTH2_SCOPE`` Scope for the OAuth 2 Authorization eg: 'email openid profile' for open ID or Azure AD, 'https://www.googleapis.com/auth/userinfo.email' Note: this field is mandatory for Azure Active Directory The OAuth2 login flow will (by default) just protect the web frontend, the configured credentials (in-cluster Service Account, Kubeconfig, or Cluster Registry) will be used to access the cluster(s). This behavior can be changed and the session's OAuth2 access token can be used for cluster authentication instead of using configured credentials. Enable this operation mode via ``--cluster-auth-use-session-token``. The OAuth redirect flow will not do any extra authorization by default, i.e. everybody who can login with your OAuth provider can use Kubernetes Web View! You can plug in a custom Python hook function (coroutine) via ``--oauth2-authorized-hook`` to validate the login or do any extra work (store extra info in the session, deny access, log user ID, etc). Note that the hook needs to be a coroutine function with signature like ``async def authorized(data, session)``. The result should be boolean true if the login is successful, and false otherwise. Examples of such hooks are provided in the `examples directory `_. A minimal ``hooks.py`` would look like: .. code-block:: python import logging async def oauth2_authorized(data: dict, session): access_token = data["access_token"] # TODO: do something with the access token, e.g. look up user info logging.info("New OAuth login!") # TODO: validate whether login is allowed or not return True # allow all OAuth logins This file would need to be in the Python search path, e.g. as ``hooks.py`` in the root ("/") of the Docker image. Pass the hook function as ``--oauth2-authorized-hook=hooks.oauth2_authorized`` to Kubernetes Web View. Google OAuth Provider ===================== This section explains how to use the Google OAuth 2.0 provider with Kubernetes Web View: * follow the instructions on https://developers.google.com/identity/protocols/OAuth2 to obtain OAuth 2.0 credentials such as client ID and client secret * use ``https://{my-kube-web-view-host}/oauth2/callback`` as one of the **Authorized redirect URIs** in the Google API Console * use "https://accounts.google.com/o/oauth2/v2/auth?scope=email" for ``OAUTH2_AUTHORIZE_URL`` * use "https://oauth2.googleapis.com/token" for ``OAUTH2_ACCESS_TOKEN_URL`` * pass the obtained client ID in the ``OAUTH2_CLIENT_ID`` environment variable * pass the obtained client secret in the ``OAUTH2_CLIENT_SECRET`` environment variable GitHub OAuth Provider ===================== How to use GitHub as the OAuth provider with Kubernetes Web View: * create a new OAuth app in the GitHub UI * use ``https://{my-kube-web-view-host}/oauth2/callback`` as the **Authorization callback URL** in the GitHub UI * use "https://github.com/login/oauth/authorize" for ``OAUTH2_AUTHORIZE_URL`` * use "https://github.com/login/oauth/access_token" for the ``OAUTH2_ACCESS_TOKEN_URL`` * pass the obtained client ID in the ``OAUTH2_CLIENT_ID`` environment variable * pass the obtained client secret in the ``OAUTH2_CLIENT_SECRET`` environment variable Note that any GitHub user can now login to your deployment of Kubernetes Web View! You have to configure a ``--oauth2-authorized-hook`` function to validate the GitHub login and only allow certain usernames: * copy ``hooks.py`` from ``examples/oauth2-validate-github-token/hooks.py`` (see `examples dir `_) to a new folder * customize the username in ``hooks.py`` to match your allowed GitHub user logins * create a new ``Dockerfile`` in the same folder * edit the ``Dockerfile`` to have two lines: 1) ``FROM hjacobs/kube-web-view:{version}`` (replace "{version}"!) as the first line, and 2) ``COPY hooks.py /`` to copy our OAuth validation function * build the Docker image * configure your kube-web-view deployment and add ``--oauth2-authorized-hook=hooks.oauth2_authorized`` as argument * deploy kube-web-view with the new Docker image and CLI option AWS Cognito Provider ===================== Setting up Cognito ------------------- A number of steps need to be taken to setup `Amazon Cognito `_ for OAuth2. These instructions are correct as of August 2019. Create User Pool ^^^^^^^^^^^^^^^^^^ 1. Create a User Pool 2. Choose how you want End Users to sign in (for example via Email, Username or otherwise) 3. Once you have gone through all the settings (customise to your liking) for creating a user pool, add an App Client Create an App Client ^^^^^^^^^^^^^^^^^^^^^ 1. Choose a Name that is relevant to the application (eg kube-web-view) 2. Make sure the **Generate client secret** option is selected, and set your **Refresh token expiration** time to whatever you are comfortable with. The App Client will then generate a Client ID and Client Secret, wich will be used later App Client Settings ^^^^^^^^^^^^^^^^^^^^ 1. Select the previously created client 2. Fill in the **Callback URL(s)** section with ``https://{my-kube-web-view-host}/oauth2/callback`` 3. Under **OAuth 2.0**, choose the relevant **Allowed OAuth Flows** (eg *Authorization Code Grant*, *Implicit Grant*) 4. Choose the **Allowed OAuth Scopes** you want to include. *email* is the minimum you will need IMPORTANT: Domain Name ^^^^^^^^^^^^^^^^^^^^^^^^ You must create a domain name for OAuth to function against AWS Cognito, otherwise the required Authorization and Token URLs will not be exposed. You can choose whether to use an AWS-hosted Cognito Domain (eg ``https://{your-chosen-domain}.auth.us-east-1.amazoncognito.com``), or to use your own domain. Update Deployment ^^^^^^^^^^^^^^^^^^^ You can now update your Deployment with the relevant Environment variables. If you have chosen to use an AWS Cognito Domain, then the ``{FQDN}`` variable in the below section will be ``https://{your-chosen-domain}.auth.{aws-region}.amazoncognito.com``. Otherwise, replace it with your domain * use "https://{FQDN}/oauth2/authorize" for ``OAUTH2_AUTHORIZE_URL`` * use "https://{FQDN}/oauth2/token" for ``OAUTH2_ACCESS_TOKEN_URL`` * Use the App Client ID generated during "Create an App Client" in the ``OAUTH2_CLIENT_ID`` environment variable * Use the App Client secret in the ``OAUTH2_CLIENT_SECRET`` environment variable. If you cannot see the secret, press "Show Details" in the AWS Console Terraform ----------- An example Terraform deployment of the above is below: .. code-block:: text # Create the User Pool resource "aws_cognito_user_pool" "kube-web-view" { name = "userpool-kube-web-view" alias_attributes = [ "email", "preferred_username" ] auto_verified_attributes = [ "email" ] schema { attribute_data_type = "String" developer_only_attribute = false mutable = true name = "name" required = true string_attribute_constraints { min_length = 3 max_length = 70 } } admin_create_user_config { allow_admin_create_user_only = true } tags = { "Name" = "userpool-kube-web-view" } } # Create the oauth2 Domain resource "aws_cognito_user_pool_domain" "kube-web-view" { domain = "oauth-kube-web-view" user_pool_id = aws_cognito_user_pool.kube-web-view.id } # kube-web-view Client resource "aws_cognito_user_pool_client" "kube-web-view" { name = "kube-web-view" user_pool_id = aws_cognito_user_pool.kube-web-view.id allowed_oauth_flows = [ "code", "implicit" ] allowed_oauth_scopes = [ "email", "openid", "profile", ] supported_identity_providers = [ "COGNITO" ] generate_secret = true allowed_oauth_flows_user_pool_client = true callback_urls = [ "https://{my-kube-web-view-host}/oauth2/callback" ] } # Outputs output "kube-web-view-id" { description = "Kube Web View App ID" value = aws_cognito_user_pool_client.kube-web-view.id } output "kube-web-view-secret" { description = "Kube Web View App Secret" value = aws_cognito_user_pool_client.kube-web-view.client_secret