Skip to content

Commit

Permalink
Move configuration from kube_oidc to own top-level configuration. Exp…
Browse files Browse the repository at this point in the history
…and the entire Struct-Auth configuration and only create the configurations if the feature gate is activated.
  • Loading branch information
Payback159 committed Jan 2, 2025
1 parent 521f471 commit 8296a06
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 56 deletions.
8 changes: 0 additions & 8 deletions inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ credentials_dir: "{{ inventory_dir }}/credentials"

## It is possible to activate / deactivate selected authentication methods (oidc, static token auth)
# kube_oidc_auth: false
# kube_oidc_structured_auth: false
# kube_token_auth: false

## Variables for OpenID Connect Configuration https://kubernetes.io/docs/admin/authentication/
Expand All @@ -55,13 +54,6 @@ credentials_dir: "{{ inventory_dir }}/credentials"
# kube_oidc_groups_claim: groups
# kube_oidc_groups_prefix: 'oidc:'

# Variables are only valid if kube_oidc_structured_auth is set to true
# kube_oidc_uid_clam: "sub"
# kube_oidc_audiences: []
# kube_oidc_additional_user_validation_rules:
# - expression: "!user.username.startsWith('system:')"
# error_message: "username cannot used reserved system: prefix"

## Variables to control webhook authn/authz
# kube_webhook_token_auth: false
# kube_webhook_token_auth_url: https://...
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
kube_apiserver_structured_auth_jwt_issuers: []
# Example JWT issuer configuration:
# kube_apiserver_structured_auth_jwt_issuers:
# - issuer:
# url: "https://issuer1.example.com"
# audiences:
# - audience1
# - audience2
# audienceMatchPolicy: MatchAny
# claimMappings:
# username:
# expression: "claims.username"
# groups:
# expression: "claims.groups"
# uid:
# expression: "claims.uid"
# userValidationRules:
# - expression: "!user.username.startsWith('system:')"
# message: "username cannot use reserved system: prefix"
# - issuer:
# url: "https://issuer2.example.com"
# discoveryURL: "https://discovery.example.com/.well-known/openid-configuration"
# audiences:
# - audience3
# - audience4
# audienceMatchPolicy: MatchAny
# claimMappings:
# username:
# expression: "claims.username"
# groups:
# expression: "claims.groups"
# uid:
# expression: "claims.uid"
# userValidationRules:
# - expression: "!user.username.startsWith('kubespray:')"
# message: "username cannot use reserved kubespray: prefix"
11 changes: 3 additions & 8 deletions roles/kubernetes/control-plane/defaults/main/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ kube_api_runtime_config: []
## Enable/Disable Kube API Server Authentication Methods
kube_token_auth: false
kube_oidc_auth: false
kube_oidc_structured_auth: false

## Variables for webhook token auth https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication
kube_webhook_token_auth: false
Expand All @@ -163,19 +162,15 @@ kube_apiserver_admission_plugins_podnodeselector_default_node_selector: ""
# kube_oidc_client_id: kubernetes
## Optional settings for OIDC
# kube_oidc_username_claim: sub
kube_oidc_username_prefix: "oidc:"
# kube_oidc_username_prefix: "oidc:"
# kube_oidc_groups_claim: groups
kube_oidc_groups_prefix: "oidc:"
kube_oidc_uid_claim: "sub"
# kube_oidc_groups_prefix: "oidc:"
# kube_oidc_uid_claim: "sub"
# Copy oidc CA file to the following path if needed
# kube_oidc_ca_file: {{ kube_cert_dir }}/ca.pem
# Optionally include a base64-encoded oidc CA cert
# kube_oidc_ca_cert: c3RhY2thYnVzZS5jb20...

# Variables are only valid if kube_oidc_structured_auth is true
kube_oidc_audiences: []
kube_oidc_additional_user_validation_rules: []

# List of the preferred NodeAddressTypes to use for kubelet connections.
kubelet_preferred_address_types: 'InternalDNS,InternalIP,Hostname,ExternalDNS,ExternalIP'

Expand Down
26 changes: 18 additions & 8 deletions roles/kubernetes/control-plane/tasks/kubeadm-setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,32 @@
when: kube_apiserver_tracing

- name: Kubeadm | Configure Structured Authentication
vars:
all_kube_apiserver_feature_gates: "{{ kube_apiserver_feature_gates + kube_feature_gates }}"
when:
- kube_oidc_auth
- kube_oidc_structured_auth
- not kube_oidc_auth
- ("StructuredAuthenticationConfiguration=true" in all_kube_apiserver_feature_gates and kube_version | regex_replace("^v", "") is version("1.30.0", "<", version_type="semver"))
or
("StructuredAuthenticationConfiguration=false" not in all_kube_apiserver_feature_gates and kube_version | regex_replace("^v", "") is version("1.30.0", ">=", version_type="semver"))
block:
- name: Kubeadm | Check if Structured Authentication Configuration is supported
fail:
msg: "OIDC structured auth is supported only from Kubernetes 1.30.0"
when:
- kube_version is version('1.30.0', '<')

- name: Kubeadm | Create apiserver authentication config directory
file:
path: "{{ kube_config_dir }}/authentication"
state: directory
mode: "0640"

- name: Merge additional userValidationRules
set_fact:
kube_apiserver_structured_auth_jwt_issuers: >-
{{
kube_apiserver_structured_auth_jwt_issuers | map('combine', {
'userValidationRules': item.userValidationRules + additional_user_validation_rules
}) | list
}}
loop: "{{ kube_apiserver_structured_auth_jwt_issuers }}"
loop_control:
loop_var: item

- name: Kubeadm | Write apiserver authentication config yaml
template:
src: apiserver-authentication-config.yaml.j2
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,48 @@
---
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthenticationConfiguration
{% if kube_apiserver_structured_auth_jwt_issuers | length > 0 %}
jwt:
- issuer:
audiences: {{ ([kube_oidc_client_id] + kube_oidc_audiences) | to_json }}
audienceMatchPolicy: MatchAny
{% if kube_oidc_ca_file is defined %}
certificateAuthority: "{{ kube_oidc_ca_file }}"
{% for issuer in kube_apiserver_structured_auth_jwt_issuers %}
- issuer:
url: "{{ issuer.issuer.url }}"
{% if issuer.issuer.discoveryURL is defined %}
discoveryURL: "{{ issuer.issuer.discoveryURL }}"
{% endif %}
url: "{{ kube_oidc_url }}"
claimMappings:
{% if kube_oidc_username_claim is defined %}
username:
claim: "{{ kube_oidc_username_claim }}"
prefix: "{{ kube_oidc_username_prefix }}"
audiences:
{% for audience in issuer.issuer.audiences %}
- {{ audience }}
{% endfor %}
audienceMatchPolicy: {{ issuer.issuer.audienceMatchPolicy }}
{% if issuer.claimValidationRules is defined %}
claimValidationRules:
{% for validationRule in issuer.claimValidationRules %}
expression: "{{ validationRule.expression }}"
message: "{{ validationRule.message }}"
{% endfor %}
{% endif %}
{% if kube_oidc_groups_claim is defined %}
groups:
claim: "{{ kube_oidc_groups_claim }}"
prefix: "{{ kube_oidc_groups_prefix }}"
claimMappings:
username:
expression: "{{ issuer.claimMappings.username.expression }}"
groups:
expression: "{{ issuer.claimMappings.groups.expression }}"
uid:
expression: "{{ issuer.claimMappings.uid.expression }}"
{% if issuer.claimMappings.extra is defined %}
extra:
{% for extra in issuer.claimMappings.extra %}
- key: "{{ extra.key }}"
expression: "{{ extra.expression }}"
{% endfor %}
{% endif %}
{% if kube_oidc_uid_claim is defined %}
uid:
claim: "{{ kube_oidc_uid_claim }}"
{% if issuer.userValidationRules | length > 0 %}
userValidationRules:
{% for rule in issuer.userValidationRules %}
- expression: "{{ rule.expression }}"
message: "{{ rule.message }}"
{% endfor %}
{% endif %}
userValidationRules:
{% for rule in kube_oidc_user_validation_rules + kube_oidc_additional_user_validation_rules %}
- expression: "{{ rule.expression }}"
message: "{{ rule.message }}"
{% endfor %}
{% else %}
jwt:
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ apiServer:
{% if kube_apiserver_service_account_lookup %}
service-account-lookup: "{{ kube_apiserver_service_account_lookup }}"
{% endif %}
{% if kube_oidc_auth and kube_oidc_url is defined and kube_oidc_client_id is defined and not kube_oidc_structured_auth %}
{% if kube_oidc_auth and kube_oidc_url is defined and kube_oidc_client_id is defined %}
oidc-issuer-url: "{{ kube_oidc_url }}"
oidc-client-id: "{{ kube_oidc_client_id }}"
{% if kube_oidc_ca_file is defined %}
Expand All @@ -173,7 +173,7 @@ apiServer:
oidc-groups-prefix: "{{ kube_oidc_groups_prefix }}"
{% endif %}
{% endif %}
{% if kube_oidc_auth and kube_oidc_url is defined and kube_oidc_client_id is defined and kube_oidc_structured_auth %}
{% if not kube_oidc_auth %}
authentication-config: {{ kube_config_dir }}/authentication/apiserver-authentication-config.yaml
{% endif %}
{% if kube_webhook_token_auth | default(false) %}
Expand Down Expand Up @@ -264,7 +264,7 @@ apiServer:
readOnly: false
pathType: DirectoryOrCreate
{% endif %}
{% if kube_oidc_structured_auth %}
{% if not kube_oidc_auth %}
- name: structauth
hostPath: {{ kube_config_dir }}/authentication
mountPath: {{ kube_config_dir }}/authentication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ apiServer:
- name: service-account-lookup
value: "{{ kube_apiserver_service_account_lookup }}"
{% endif %}
{% if kube_oidc_auth | default(false) and kube_oidc_url is defined and kube_oidc_client_id is defined %}
{% if kube_oidc_auth and kube_oidc_url is defined and kube_oidc_client_id is defined %}
- name: oidc-issuer-url
value: "{{ kube_oidc_url }}"
- name: oidc-client-id
Expand All @@ -208,6 +208,10 @@ apiServer:
value: "{{ kube_oidc_groups_prefix }}"
{% endif %}
{% endif %}
{% if not kube_oidc_auth %}
- name: authentication-config
value: "{{ kube_config_dir }}/authentication/apiserver-authentication-config.yaml"
{% endif %}
{% if kube_webhook_token_auth | default(false) %}
- name: authentication-token-webhook-config-file
value: "{{ kube_config_dir }}/webhook-token-auth-config.yaml"
Expand Down Expand Up @@ -317,6 +321,13 @@ apiServer:
readOnly: false
pathType: DirectoryOrCreate
{% endif %}
{% if not kube_oidc_auth %}
- name: structauth
hostPath: {{ kube_config_dir }}/authentication
mountPath: {{ kube_config_dir }}/authentication
readOnly: true
pathType: DirectoryOrCreate
{% endif %}
{% if kube_apiserver_tracing %}
- name: tracing
hostPath: {{ kube_config_dir }}/tracing
Expand Down
11 changes: 5 additions & 6 deletions roles/kubernetes/control-plane/vars/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ kube_apiserver_admission_plugins_needs_configuration:
- PodSecurity
- PodNodeSelector
- ResourceQuota
# default user validation rules for OIDC
kube_oidc_user_validation_rules:
- expression: "!user.username.startsWith('system:')"
message: "username cannot used reserved system: prefix"
- expression: "user.groups.all(group, !group.startsWith('system:'))"
message: "groups cannot used reserved system: prefix"
additional_user_validation_rules:
- expression: "!user.username.startsWith('system:')"
message: "username cannot used reserved system: prefix"
- expression: "user.groups.all(group, !group.startsWith('system:'))"
message: "groups cannot used reserved system: prefix"

0 comments on commit 8296a06

Please sign in to comment.