Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenID Connect Support #524

Merged
merged 31 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
388c103
First parts of airflow OIDC
Maleware Oct 22, 2024
82e514d
Add integration test for OIDC
siegfriedweber Oct 22, 2024
d2c07fa
Document OIDC support
siegfriedweber Oct 22, 2024
6bf5d04
Update wip
Maleware Oct 23, 2024
5acbb55
Merge branch 'feature/tls-oidc' of https://github.com/stackabletech/a…
Maleware Oct 23, 2024
816e1cb
Adapt module tests in operator-binary/src/config.rs
siegfriedweber Oct 23, 2024
c79ce8a
Adding unit tests
Maleware Oct 24, 2024
ec14d14
WIP before merge
Maleware Oct 24, 2024
df9cba2
Merge branch 'main' into feature/tls-oidc
Maleware Oct 24, 2024
bffe076
WIP compiling operator
Maleware Oct 28, 2024
b1d2d2f
Fixng auth tests
Maleware Oct 28, 2024
5a8e0e7
Update the OIDC integration test
siegfriedweber Oct 28, 2024
18412e1
Env vars oidc
Maleware Oct 28, 2024
72bb1e9
Cleaning up
Maleware Oct 29, 2024
08a1019
Adding changelog
Maleware Oct 29, 2024
b67e026
Remove reference
Maleware Oct 29, 2024
c2abb38
Regenerate charts and Nix files
siegfriedweber Oct 29, 2024
963518e
making pre-commit happy
Maleware Oct 29, 2024
4fd1086
Merge branch 'feature/tls-oidc' of https://github.com/stackabletech/a…
Maleware Oct 29, 2024
f5e55f7
fixing typo
Maleware Oct 29, 2024
fcda6ea
again pre-commit
Maleware Oct 29, 2024
39d4c23
pre-commit nr3
Maleware Oct 29, 2024
2205779
pre-commit nr4
Maleware Oct 29, 2024
52de18a
pre-commit nr5
Maleware Oct 29, 2024
9d7e2e7
Env var set by operator rather then envoverrides
Maleware Oct 29, 2024
15aeef7
Merge branch 'main' into feature/tls-oidc
Maleware Oct 29, 2024
908f111
Removing TODO, sort toml alphabetically
Maleware Oct 30, 2024
9fe2bc6
Merge branch 'feature/tls-oidc' of https://github.com/stackabletech/a…
Maleware Oct 30, 2024
467c8c6
Andrew comments
Maleware Oct 31, 2024
f28c382
Specify every arm rather then just matching all
Maleware Oct 31, 2024
df3cbae
Merge branch 'feature/tls-oidc' of https://github.com/stackabletech/a…
Maleware Oct 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Use the env var `KUBERNETES_CLUSTER_DOMAIN` or the operator Helm chart property `kubernetesClusterDomain` to set a non-default cluster domain ([#518]).
- Support for `2.9.3` ([#494]).
- Experimental Support for `2.10.2` ([#512]).
- Add support for OpenID Connect ([#524])

### Changed

Expand All @@ -30,6 +31,7 @@
[#494]: https://github.com/stackabletech/airflow-operator/pull/494
[#518]: https://github.com/stackabletech/airflow-operator/pull/518
[#520]: https://github.com/stackabletech/airflow-operator/pull/520
[#524]: https://github.com/stackabletech/airflow-operator/pull/524

## [24.7.0] - 2024-07-24

Expand Down
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions Cargo.nix

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ built = { version = "0.7", features = ["chrono", "git2"] }
clap = "4.5"
fnv = "1.0"
futures = { version = "0.3", features = ["compat"] }
indoc = "2.0"
product-config = { git = "https://github.com/stackabletech/product-config.git", tag = "0.7.0" }
rstest = "0.23"
semver = "1.0"
Expand Down
22 changes: 19 additions & 3 deletions deploy/helm/airflow-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -452,13 +452,27 @@ spec:
properties:
authentication:
default: []
description: The Airflow [authentication](https://docs.stackable.tech/home/nightly/airflow/usage-guide/security.html) settings. Currently the underlying Flask App Builder only supports one authentication mechanism at a time. This means the operator will error out if multiple references to an AuthenticationClass are provided.
items:
properties:
authenticationClass:
description: Name of the [AuthenticationClass](https://docs.stackable.tech/home/nightly/concepts/authentication.html#authenticationclass) used to authenticate the users. At the moment only LDAP is supported. If not specified the default authentication (AUTH_DB) will be used.
nullable: true
description: Name of the [AuthenticationClass](https://docs.stackable.tech/home/nightly/concepts/authentication) used to authenticate users.
type: string
oidc:
description: This field contains OIDC-specific configuration. It is only required in case OIDC is used.
nullable: true
properties:
clientCredentialsSecret:
description: A reference to the OIDC client credentials secret. The secret contains the client id and secret.
type: string
extraScopes:
default: []
description: An optional list of extra scopes which get merged with the scopes defined in the [`AuthenticationClass`].
items:
type: string
type: array
required:
- clientCredentialsSecret
type: object
syncRolesAt:
default: Registration
description: If we should replace ALL the user's roles each login, or only on registration. Gets mapped to `AUTH_ROLES_SYNC_AT_LOGIN`
Expand All @@ -474,6 +488,8 @@ spec:
default: Public
description: This role will be given in addition to any AUTH_ROLES_MAPPING. Gets mapped to `AUTH_USER_REGISTRATION_ROLE`
type: string
required:
- authenticationClass
type: object
type: array
credentialsSecret:
Expand Down
115 changes: 109 additions & 6 deletions docs/modules/airflow/pages/usage-guide/security.adoc
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
= Security
:description: Secure Apache Airflow by configuring user authentication and authorization, either with built-in methods or LDAP.
:description: Secure Apache Airflow by configuring user authentication and authorization.
:airflow-access-control-docs: https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html
:keycloak: https://www.keycloak.org/

Secure Apache Airflow by configuring user authentication and authorization.
Airflow provides built-in user and role management, but can also connect to a LDAP server to manage users centrally instead.
Airflow provides built-in user and role management, but can also connect to an LDAP server or an OIDC provider to manage users centrally instead.

== Authentication

Users need to authenticate themselves before using Airflow, and there are two ways to configure users:
The built-in user management or LDAP.
Users need to authenticate themselves before using Airflow, and there are several ways in which this can be set up.
[IMPORTANT]
.Multiple authentication methods
adwk67 marked this conversation as resolved.
Show resolved Hide resolved
====
Only one authentication method is supported at a time, and in case of LDAP, only one authentication class is allowed.
This means, it is not possible to configure both LDAP and OIDC authentication methods at the same time, but *it is* possible to configure multiple OIDC classes *or* one LDAP authentication class.
====

=== Built-in user management

Expand All @@ -19,7 +26,7 @@ image::airflow_security.png[Airflow Security menu]

=== LDAP

Airflow supports xref:concepts:authentication.adoc[user authentication] via LDAP.
Airflow supports xref:concepts:authentication.adoc[user authentication] against a single LDAP server.
Set up an AuthenticationClass for the LDAP server and reference it in the Airflow Stacklet resource as shown:

[source,yaml]
Expand All @@ -30,7 +37,7 @@ metadata:
name: airflow-with-ldap
spec:
image:
productVersion: 2.9.3
productVersion: 2.10.2
clusterConfig:
authentication:
- authenticationClass: ldap # <1>
Expand All @@ -48,6 +55,79 @@ The users and roles can be viewed as before in the Webserver UI, but the blue "+

image::airflow_security_ldap.png[Airflow Security menu]

=== [[oidc]]OpenID Connect

An OpenID Connect provider can be used for authentication.
Unfortunately, there is no generic support for OpenID Connect built into Airflow.
This means that only specific OpenID Connect providers can be configured.

IMPORTANT: Airflow deployments on the Stackable Data Platform only support {keycloak}[Keycloak].

[source,yaml]
----
apiVersion: airflow.stackable.tech/v1alpha1
kind: AirflowCluster
metadata:
name: airflow-with-oidc
spec:
image:
productVersion: 2.10.2
clusterConfig:
authentication:
- authenticationClass: keycloak # <1>
oidc:
clientCredentialsSecret: airflow-keycloak-client # <2>
userRegistrationRole: User # <3>
----

<1> The reference to an AuthenticationClass called `keycloak`
<2> The reference to the Secret containing the Airflow client credentials
<3> The default role to which all users are assigned

Users that log in with OpenID Connect are assigned to a default {airflow-access-control-docs}[role] which is specified with the `userRegistrationRole` property.

The Secret containing the Airflow client credentials:

[source,yaml]
----
apiVersion: v1
kind: Secret
metadata:
name: airflow-keycloak-client
stringData:
clientId: airflow # <1>
clientSecret: airflow_client_secret # <2>
----

<1> The client ID of Airflow as defined in Keycloak
<2> The client secret as defined in Keycloak

A minimum client configuration in Keycloak for this example looks like this:

[source,json]
----
{
"clientId": "airflow",
"enabled": true,
"clientAuthenticatorType": "client-secret", # <1>
"secret": "airflow_client_secret",
"redirectUris": [
"*"
],
"webOrigins": [
"*"
],
"standardFlowEnabled": true, # <2>
"protocol": "openid-connect" # <3>
}
----

<1> Sets the OIDC type to confidential access type.
<2> Enables the OAuth2 "Authorization Code Flow".
<3> Enables OpenID Connect and OAuth2 support.

Further information for specifying an AuthenticationClass for an OIDC provider can be found at the xref:concepts:authentication.adoc#_oidc[concepts page].

== Authorization
The Airflow Webserver delegates the {airflow-access-control-docs}[handling of user access control] to https://flask-appbuilder.readthedocs.io/en/latest/security.html[Flask AppBuilder].

Expand All @@ -74,3 +154,26 @@ spec:

<1> The reference to an AuthenticationClass called `ldap`
<2> All users are assigned to the `Admin` role

=== OpenID Connect

The mechanism for assigning roles to users described in the LDAP section also applies to OpenID Connect.
Airflow supports assigning {airflow-access-control-docs}[Roles] to users based on their OpenID Connect scopes, though this is not yet supported by the Stackable operator.
All the users logging in via OpenID Connect get assigned to the same role which you can configure via the attribute `authentication[*].userRegistrationRole` on the `AirflowCluster` object:

[source,yaml]
----
apiVersion: airflow.stackable.tech/v1alpha1
kind: AirflowCluster
metadata:
name: airflow-with-oidc
spec:
clusterConfig:
authentication:
- authenticationClass: keycloak
oidc:
clientCredentialsSecret: airflow-keycloak-client
userRegistrationRole: Admin # <1>
----

<1> All users are assigned to the `Admin` role
4 changes: 3 additions & 1 deletion rust/crd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ repository.workspace = true
publish = false

[dependencies]
indoc.workspace = true
product-config.workspace = true
serde.workspace = true
serde_json.workspace = true
snafu.workspace = true
stackable-operator.workspace = true
product-config.workspace = true
strum.workspace = true
tokio.workspace = true
tracing.workspace = true

[dev-dependencies]
Expand Down
Loading
Loading