Authenticating in Flyte#

Tags: Authentication, Infrastructure, Advanced

Flyte ships with a canonical implementation of OpenIDConnect client and OAuth2 Server, integrating seamlessly into an organization’s existing identity provider.

The following video will demo an example of how to set up Flyte Autherntication.

Overview#

The Flyte system consists of multiple components. Securing communication between each components is crucial to ensure the security of the overall system.

In abstract, Flyte supports OAuth2 and OpenId Connect (built on top of OAuth2) to secure the various connections:

  • OpenId Connect: Used to secure user’s authentication to flyteadmin service.

  • OAuth2: Used to secure communication between clients (i.e. pyflyte, flytectl and flytepropeller) and flyteadmin service.

Identity Providers Support#

Support for these protocols varies per IdP, checkout the following table to understand the available support level for your IdP.

Feature

Okta

Google free

GC Identity Service

Azure AD

Auth0

KeyCloak

Github

OpenIdConnect

Yes

Yes

Yes

Yes

Yes

Yes

No

Custom Relying Party

Yes

No

Yes

Yes

?

Yes

No

Authentication Setup#

Prerequisites#

The following is required for non-sandbox deployments:

  • A public domain name (e.g. example.foobar.com)

  • Routing of traffic from that domain name to the Kubernetes Flyte Ingress IP address

Note

Flyte’s Ingress routes traffic to either Flyte Console or FlyteAdmin based on the url path.

# determine Flyte Ingress IP
kubectl get ingress -n flyte flyte

IdP Configuration#

FlyteAdmin requires that the application in your identity provider be configured as a web client (i.e. with a client secret). We recommend allowing the application to be issued a refresh token to avoid interrupting the user’s flow by frequently redirecting to the IdP.

Example Flyte Configurations#

Below are some canonical examples of how to set up some of the common IdPs to secure your Flyte services. OpenID Connect enables users to authenticate, in the browser, with an existing IdP. Flyte also allows connecting to an external OAuth2 Authorization Server to allow centrally managed third party app access.

OpenID Connect#

OpenID Connect allows users to authenticate to Flyte in their browser using a familiar authentication provider (perhaps an organization-wide configured IdP). Flyte supports connecting with external OIdC providers. Here are some examples for how to set these up:

Follow Google Docs on how to configure the IdP for OpenIDConnect.

Note

Make sure to create an OAuth2 Client Credential. The client_id and client_secret will be needed in the following steps.

Apply Configuration#

Store the client_secret in a k8s secret as follows:

kubectl edit secret -n flyte flyte-admin-secrets

Add a new key under stringData:

stringData:
  oidc_client_secret: <client_secret from the previous step>
data:
  ...

Save and close your editor.

Edit FlyteAdmin config to add client_id and configure auth as follows:

kubectl edit configmap -n flyte flyte-admin-base-config

Follow the inline comments to make the necessary changes:

server:
  ...
  security:
    secure: false
    # 1. Enable Auth by turning useAuth to true
    useAuth: true
    ...
auth:
  userAuth:
    openId:
      # 2. Put the URL of the OpenID Connect provider.
      #    baseUrl: https://<keycloak-url>/auth/realms/<keycloak-realm> # Uncomment for Keycloak and update with your installation host and realm name
      #    baseUrl: https://accounts.google.com # Uncomment for Google
      baseUrl: https://dev-14186422.okta.com/oauth2/default # Okta with a custom Authorization Server
      scopes:
        - profile
        - openid
        # - offline_access # Uncomment if OIdC supports issuing refresh tokens.
      # 3. Replace with the client ID created for Flyte.
      clientId: 0oakkheteNjCMERst5d6
  authorizedUris:
    # 4. Update with a public domain name (for non-sandbox deployments).
    # - https://example.foobar.com
    # Or uncomment this line for sandbox deployment
    # - http://localhost:30081
    - http://flyteadmin:80
    - http://flyteadmin.flyte.svc.cluster.local:80

Save and exit your editor.

Restart flyteadmin for the changes to take effect:

kubectl rollout restart deployment/flyteadmin -n flyte

Restart flytepropeller to start using authenticated requests:

kubectl rollout restart deployment/flytepropeller -n flyte

Restart flytescheduler` to start using authenticated requests:

kubectl rollout restart deployment/flytescheduler -n flyte

Note

Congratulations!

It should now be possible to go to flyte UI (https://<your domain>/console) and be prompted for authentication. Flytectl should automatically pickup the change and start prompting for authentication as well. If you want to use an external OAuth2 provider for App authentication, please continue reading into the next section.

OAuth2 Authorization Server#

An OAuth2 Authorization Server allows external clients to request to authenticate and act on behalf of users (or as their own identities). Having an OAuth2 Authorization Server enables Flyte administrators control over which apps can be installed and what scopes they are allowed to request or be granted (i.e. what privileges can they assume).

Flyte comes with a built-in authorization server that can be statically configured with a set of clients to request and act on behalf of the user. The default clients are defined here and the corresponding section can be modified through configs.

Hence, it is not necessary to set up an external Authorization Server. However, it is recommended to do so to maintain the security of the configured apps in a secure location and to be manage (add, modify, delete) apps using the external authorization server.

To set up an external OAuth2 Authorization Server, follow the instructions below:

Note

Google IdP

Google IdP does not offer an OAuth2 Authorization Server that could be used to protect external services (For example Flyte). In this case, Google offers a separate Cloud Product called Google Cloud Identity. Configuration for Cloud Identity is not included in this guide. If unavailable, setup can stop here and FlyteAdmin BuiltIn OAuth2 Authorization Server can be used instead.

Okta’s custom authorization servers are available through an add-on license. The free developer accounts do include access, which you can use to test before rolling out the configuration more broadly.

  1. Under security -> API, click Add Authorization Server. Set the audience to the public URL of FlyteAdmin (e.g. https://example.foobar.com).

    Note

    The audience must exactly match one of the URIs in the authorizedUris section above

  2. Note down the Issuer URI; this will be used for all the baseUrl settings in the Flyte config.

  3. Under Access Policies, click Add New Access Policy and walk through the wizard to allow access to the authorization server. Then, add a rule to the policy with the default settings (you can fine-tune these later).

  4. Under Scopes, click Add Scope. Set the name to all (required) and check Require user consent for this scope (recommended).

  5. Add another scope, named offline. Check the consent option, and Include in public metadata.

  6. Navigate back to the Applications section

  7. Create an integration for Flytectl; it should be created with the OIDC - OpenID Connect sign-on method, and the Native Application type.

  8. Add http://localhost:53593/callback to the sign-in redirect URIs. The other options can remain as default.

  9. Assign this integration to any Okta users or groups who should be able to use the Flytectl tool.

  10. Note down the client ID; there will not be a secret.

  11. Create an integration for Flytepropeller; it should be created with the OIDC - OpenID Connect sign-on method and Web Application type.

  12. Check the Client acting on behalf of itself - Client Credentials option.

  13. This app does not need a specific redirect URI; nor does it need to be assigned to any users.

  14. Note down the client ID and secret; you will need these later.

You shoule have three integrations total - one for the web interface, one for Flytectl, and one for Flytepropeller.

Apply Configuration#

It is possible to direct FlyteAdmin to use an external authorization server. To do so, edit the same config map once more and follow these changes:

auth:
   appAuth:
      # 1. Choose External if you will use an external Authorization Server (e.g. a Custom Authorization server in Okta)
      #    Choose Self (or omit the value) to use FlyteAdmin's internal (albeit limited) Authorization Server.
      authServerType: External

      # 2. Optional: Set external auth server baseUrl if different from OpenId baseUrl.
      externalAuthServer:
         baseUrl: https://dev-14186422.okta.com/oauth2/auskngnn7uBViQq6b5d6

      thirdPartyConfig:
         flyteClient:
               # 3. Replace with a new Native/Public Client ID provisioned in the custom authorization server.
               clientId: flytectl
               # This should not change
               redirectUri: http://localhost:53593/callback
               # 4. "all" is a required scope and must be configured in the custom authorization server.
               scopes:
               - offline
               - all

   userAuth:
      openId:
         baseUrl: https://dev-14186422.okta.com/oauth2/auskngnn7uBViQq6b5d6 # Okta with a custom Authorization Server
         scopes:
         - profile
         - openid
         # - offline_access # Uncomment if OIdC supports issuing refresh tokens.
         clientId: <client id>

Add flytepropeller client ID and client secret provided by the OAuth2 Authorization Server above to your values.yaml:

secrets:
  adminOauthClientCredentials:
      enabled: true
      # Replace with the client_secret provided by the OAuth2 Authorization Server above.
      clientSecret: <client_secret>
      # Replace with the client_id provided by the OAuth2 Authorization Server above.
      clientId: <client_id>

Alternatively you can instruct helm not to create and manage the kubernetes secret containing your client secret:

secrets:
  adminOauthClientCredentials:
      enabled: false
      # Replace with the client_id provided by the OAuth2 Authorization Server above.
      clientId: <client_id>

In that case you have to create the secret yourself:

apiVersion: v1
kind: Secret
metadata:
  name: flyte-secret-auth
  namespace: flyte
type: Opaque
stringData:
  # Replace with the client_secret provided by the OAuth2 Authorization Server above.
  client_secret: <client_secret>

Continuous Integration - CI#

If your organization does any automated registration, then you’ll need to authenticate with the client credentials flow. After retrieving an access token from the IDP, you can send it along to FlyteAdmin as usual.

Flytectl’s config.yaml can be configured to use either PKCE (Proof key for code exchange) or Client Credentials (Client Credentials) flows.

Update config.yaml as follows:

admin:
    # Update with the Flyte's ingress endpoint (e.g. flyteIngressIP for sandbox or example.foobar.com)
    # You must keep the 3 forward-slashes after dns:
    endpoint: dns:///<Flyte ingress url>

    # Update auth type to `Pkce` or `ClientSecret`
    authType: Pkce

    # Set to the clientId (will be used for both Pkce and ClientSecret flows)
    # Leave empty to use the value discovered through flyteAdmin's Auth discovery endpoint.
    clientId: <Id>

    # Set to the location where the client secret is mounted.
    # Only needed/used for `ClientSecret` flow.
    clientSecretLocation: </some/path/to/key>

    # If required, set the scopes needed here. Otherwise, flytectl will discover scopes required for OpenID
    # Connect through flyteAdmin's Auth discovery endpoint.
    # scopes: [ "scope1", "scope2" ]

To read further about the available config options, please visit here

References#

This collection of RFCs may be helpful to those who wish to investigate the implementation in more depth.

There’s also a lot more detailed information into the authentication flows in the Understanding Authentication.