|
| 1 | +--- |
| 2 | +layout: blog |
| 3 | +title: "Kubernetes 1.30: Structured Authentication Configuration Moves to Beta" |
| 4 | +date: 2024-04-25 |
| 5 | +slug: structured-authentication-moves-to-beta |
| 6 | +--- |
| 7 | + |
| 8 | +**Author:** [Anish Ramasekar](https://github.com/aramase) (Microsoft) |
| 9 | + |
| 10 | +With Kubernetes 1.30, we (SIG Auth) are moving Structured Authentication Configuration to beta. |
| 11 | + |
| 12 | +Today's article is about _authentication_: finding out who's performing a task, and checking |
| 13 | +that they are who they say they are. Check back in tomorrow to find about what's new in |
| 14 | +Kubernetes v1.30 around _authorization_ (deciding what someone can and can't access). |
| 15 | + |
| 16 | +## Motivation |
| 17 | +Kubernetes has had a long-standing need for a more flexible and extensible |
| 18 | +authentication system. The current system, while powerful, has some limitations |
| 19 | +that make it difficult to use in certain scenarios. For example, it is not |
| 20 | +possible to use multiple authenticators of the same type (e.g., multiple JWT |
| 21 | +authenticators) or to change the configuration without restarting the API server. The |
| 22 | +Structured Authentication Configuration feature is the first step towards |
| 23 | +addressing these limitations and providing a more flexible and extensible way |
| 24 | +to configure authentication in Kubernetes. |
| 25 | + |
| 26 | +## What is structured authentication configuration? |
| 27 | +Kubernetes v1.30 builds on the experimental support for configurating authentication based on |
| 28 | +a file, that was added as alpha in Kubernetes v1.30. At this beta stage, Kubernetes only supports configuring JWT |
| 29 | +authenticators, which serve as the next iteration of the existing OIDC |
| 30 | +authenticator. JWT authenticator is an authenticator to |
| 31 | +authenticate Kubernetes users using JWT compliant tokens. The authenticator |
| 32 | +will attempt to parse a raw ID token, verify it's been signed by the configured |
| 33 | +issuer. |
| 34 | + |
| 35 | +The Kubernetes project added configuration from a file so that it can provide more |
| 36 | +flexibility than using command line options (which continue to work, and are still supported). |
| 37 | +Supporting a configuration file also makes it easy to deliver further improvements in upcoming |
| 38 | +releases. |
| 39 | + |
| 40 | +### Benefits of structured authentication configuration |
| 41 | +Here's why using a configuration file to configure cluster authentication is a benefit: |
| 42 | +1. **Multiple JWT authenticators**: You can configure multiple JWT authenticators |
| 43 | + simultaneously. This allows you to use multiple identity providers (e.g., |
| 44 | + Okta, Keycloak, GitLab) without needing to use an intermediary like Dex |
| 45 | + that handles multiplexing between multiple identity providers. |
| 46 | +2. **Dynamic configuration**: You can change the configuration without |
| 47 | + restarting the API server. This allows you to add, remove, or modify |
| 48 | + authenticators without disrupting the API server. |
| 49 | +3. **Any JWT-compliant token**: You can use any JWT-compliant token for |
| 50 | + authentication. This allows you to use tokens from any identity provider that |
| 51 | + supports JWT. The minimum valid JWT payload must contain the claims documented |
| 52 | + in [structured authentication configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration) |
| 53 | + page in the Kubernetes documentation. |
| 54 | +4. **CEL (Common Expression Language) support**: You can use [CEL](/docs/reference/using-api/cel/) |
| 55 | + to determine whether the token's claims match the user's attributes in Kubernetes (e.g., |
| 56 | + username, group). This allows you to use complex logic to determine whether a |
| 57 | + token is valid. |
| 58 | +5. **Multiple audiences**: You can configure multiple audiences for a single |
| 59 | + authenticator. This allows you to use the same authenticator for multiple |
| 60 | + audiences, such as using a different OAuth client for `kubectl` and dashboard. |
| 61 | +6. **Using identity providers that don't support OpenID connect discovery**: You |
| 62 | + can use identity providers that don't support [OpenID Connect |
| 63 | + discovery](https://openid.net/specs/openid-connect-discovery-1_0.html). The only |
| 64 | + requirement is to host the discovery document at a different location than the |
| 65 | + issuer (such as locally in the cluster) and specify the `issuer.discoveryURL` in |
| 66 | + the configuration file. |
| 67 | + |
| 68 | +## How to use Structured Authentication Configuration |
| 69 | +To use structured authentication configuration, you specify |
| 70 | +the path to the authentication configuration using the `--authentication-config` |
| 71 | +command line argument in the API server. The configuration file is a YAML file |
| 72 | +that specifies the authenticators and their configuration. Here is an example |
| 73 | +configuration file that configures two JWT authenticators: |
| 74 | + |
| 75 | +```yaml |
| 76 | +apiVersion: apiserver.config.k8s.io/v1beta1 |
| 77 | +kind: AuthenticationConfiguration |
| 78 | +# Someone with a valid token from either of these issuers could authenticate |
| 79 | +# against this cluster. |
| 80 | +jwt: |
| 81 | +- issuer: |
| 82 | + url: https://issuer1.example.com |
| 83 | + audiences: |
| 84 | + - audience1 |
| 85 | + - audience2 |
| 86 | + audienceMatchPolicy: MatchAny |
| 87 | + claimValidationRules: |
| 88 | + expression: 'claims.hd == "example.com"' |
| 89 | + message: "the hosted domain name must be example.com" |
| 90 | + claimMappings: |
| 91 | + username: |
| 92 | + expression: 'claims.username' |
| 93 | + groups: |
| 94 | + expression: 'claims.groups' |
| 95 | + uid: |
| 96 | + expression: 'claims.uid' |
| 97 | + extra: |
| 98 | + - key: 'example.com/tenant' |
| 99 | + expression: 'claims.tenant' |
| 100 | + userValidationRules: |
| 101 | + - expression: "!user.username.startsWith('system:')" |
| 102 | + message: "username cannot use reserved system: prefix" |
| 103 | +# second authenticator that exposes the discovery document at a different location |
| 104 | +# than the issuer |
| 105 | +- issuer: |
| 106 | + url: https://issuer2.example.com |
| 107 | + discoveryURL: https://discovery.example.com/.well-known/openid-configuration |
| 108 | + audiences: |
| 109 | + - audience3 |
| 110 | + - audience4 |
| 111 | + audienceMatchPolicy: MatchAny |
| 112 | + claimValidationRules: |
| 113 | + expression: 'claims.hd == "example.com"' |
| 114 | + message: "the hosted domain name must be example.com" |
| 115 | + claimMappings: |
| 116 | + username: |
| 117 | + expression: 'claims.username' |
| 118 | + groups: |
| 119 | + expression: 'claims.groups' |
| 120 | + uid: |
| 121 | + expression: 'claims.uid' |
| 122 | + extra: |
| 123 | + - key: 'example.com/tenant' |
| 124 | + expression: 'claims.tenant' |
| 125 | + userValidationRules: |
| 126 | + - expression: "!user.username.startsWith('system:')" |
| 127 | + message: "username cannot use reserved system: prefix" |
| 128 | +``` |
| 129 | +
|
| 130 | +## Migration from command line arguments to configuration file |
| 131 | +The Structured Authentication Configuration feature is designed to be |
| 132 | +backwards-compatible with the existing approach, based on command line options, for |
| 133 | +configuring the JWT authenticator. This means that you can continue to use the existing |
| 134 | +command-line options to configure the JWT authenticator. However, we (Kubernetes SIG Auth) |
| 135 | +recommend migrating to the new configuration file-based approach, as it provides more |
| 136 | +flexibility and extensibility. |
| 137 | +
|
| 138 | +{{% alert title="Note" color="primary" %}} |
| 139 | +If you specify `--authentication-config` along with any of the `--oidc-*` command line arguments, this is |
| 140 | +a misconfiguration. In this situation, the API server reports an error and then immediately exits. |
| 141 | + |
| 142 | +If you want to switch to using structured authentication configuration, you have to remove the `--oidc-*` |
| 143 | +command line arguments, and use the configuration file instead. |
| 144 | +{{% /alert %}} |
| 145 | + |
| 146 | +Here is an example of how to migrate from the command-line flags to the |
| 147 | +configuration file: |
| 148 | + |
| 149 | +### Command-line arguments |
| 150 | +```bash |
| 151 | +--oidc-issuer-url=https://issuer.example.com |
| 152 | +--oidc-client-id=example-client-id |
| 153 | +--oidc-username-claim=username |
| 154 | +--oidc-groups-claim=groups |
| 155 | +--oidc-username-prefix=oidc: |
| 156 | +--oidc-groups-prefix=oidc: |
| 157 | +--oidc-required-claim="hd=example.com" |
| 158 | +--oidc-required-claim="admin=true" |
| 159 | +--oidc-ca-file=/path/to/ca.pem |
| 160 | +``` |
| 161 | + |
| 162 | +There is no equivalent in the configuration file for the `--oidc-signing-algs`. |
| 163 | +For Kubernetes v1.30, the authenticator supports all the asymmetric algorithms listed in |
| 164 | +[`oidc.go`](https://github.com/kubernetes/kubernetes/blob/b4935d910dcf256288694391ef675acfbdb8e7a3/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go#L222-L233). |
| 165 | + |
| 166 | +### Configuration file |
| 167 | +```yaml |
| 168 | +apiVersion: apiserver.config.k8s.io/v1beta1 |
| 169 | +kind: AuthenticationConfiguration |
| 170 | +jwt: |
| 171 | +- issuer: |
| 172 | + url: https://issuer.example.com |
| 173 | + audiences: |
| 174 | + - example-client-id |
| 175 | + certificateAuthority: <value is the content of file /path/to/ca.pem> |
| 176 | + claimMappings: |
| 177 | + username: |
| 178 | + claim: username |
| 179 | + prefix: "oidc:" |
| 180 | + groups: |
| 181 | + claim: groups |
| 182 | + prefix: "oidc:" |
| 183 | + claimValidationRules: |
| 184 | + - claim: hd |
| 185 | + requiredValue: "example.com" |
| 186 | + - claim: admin |
| 187 | + requiredValue: "true" |
| 188 | +``` |
| 189 | + |
| 190 | +## What's next? |
| 191 | +For Kubernetes v1.31, we expect the feature to stay in beta while we get more |
| 192 | +feedback. In the coming releases, we want to investigate: |
| 193 | +- Making distributed claims work via CEL expressions. |
| 194 | +- Egress selector configuration support for calls to `issuer.url` and |
| 195 | + `issuer.discoveryURL`. |
| 196 | + |
| 197 | +You can learn more about this feature on the [structured authentication |
| 198 | +configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration) |
| 199 | +page in the Kubernetes documentation. You can also follow along on the |
| 200 | +[KEP-3331](https://kep.k8s.io/3331) to track progress across the coming |
| 201 | +Kubernetes releases. |
| 202 | + |
| 203 | +## Try it out |
| 204 | +In this post, I have covered the benefits the Structured Authentication |
| 205 | +Configuration feature brings in Kubernetes v1.30. To use this feature, you must specify the path to the |
| 206 | +authentication configuration using the `--authentication-config` command line |
| 207 | +argument. From Kubernetes v1.30, the feature is in beta and enabled by default. |
| 208 | +If you want to keep using command line arguments instead of a configuration file, |
| 209 | +those will continue to work as-is. |
| 210 | + |
| 211 | +We would love to hear your feedback on this feature. Please reach out to us on the |
| 212 | +[#sig-auth-authenticators-dev](https://kubernetes.slack.com/archives/C04UMAUC4UA) |
| 213 | +channel on Kubernetes Slack (for an invitation, visit [https://slack.k8s.io/](https://slack.k8s.io/)). |
| 214 | + |
| 215 | +## How to get involved |
| 216 | +If you are interested in getting involved in the development of this feature, |
| 217 | +share feedback, or participate in any other ongoing SIG Auth projects, please |
| 218 | +reach out on the [#sig-auth](https://kubernetes.slack.com/archives/C0EN96KUY) |
| 219 | +channel on Kubernetes Slack. |
| 220 | + |
| 221 | +You are also welcome to join the bi-weekly [SIG Auth |
| 222 | +meetings](https://github.com/kubernetes/community/blob/master/sig-auth/README.md#meetings) |
| 223 | +held every-other Wednesday. |
0 commit comments