---
# mc URL-embedded credentials (`MC_HOST_<alias>=https://USER:PASS@host`)
# are NOT URL-decoded by mc when read from the environment, while the
# MinIO server stores the URL-decoded password. With administrator
# credentials containing $ / β¬ / ! / ' the two sides disagree and every
# admin call fails with "request signature we calculated does not
# match". Authenticate via `mc alias set` with explicit args instead;
# mc applies the credentials verbatim, matching the server.
# MinIO finishes booting its IAM subsystem (where policies and the
# OIDC IdP live) AFTER `mc admin info` already reports the server
# as up. Probing IAM directly via `mc admin policy ls` is the only
# readiness signal that matches what the policy admin API needs;
# `mc admin info` returns rc=0 in a window where the very next
# `mc admin policy info` still fails with `Server not initialized
# yet, please try again.`.
- name: "β³ Wait for MinIO IAM subsystem to finish initializing"
environment:
MINIO_ROOT_USER: "{{ lookup('users', 'platform_administrator').username }}"
MINIO_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
shell: |
set -euo pipefail
container run --rm \
-e MINIO_ROOT_USER \
-e MINIO_ROOT_PASSWORD \
--entrypoint /bin/sh \
{{ MINIO_MC_IMAGE }} \
-c 'mc alias set minio {{ MINIO_API_URL | quote }} "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null \
&& mc admin policy ls minio'
args: { executable: /bin/bash }
register: mc_admin_policy_ls
retries: 60
delay: 5
until: mc_admin_policy_ls.rc == 0
changed_when: false
- name: "π Register Keycloak as named OIDC IdP on MinIO"
environment:
MINIO_ROOT_USER: "{{ lookup('users', 'platform_administrator').username }}"
MINIO_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
MINIO_OIDC_CONFIG_URL: "{{ OIDC.CLIENT.DISCOVERY_DOCUMENT }}"
MINIO_OIDC_CLIENT_ID: "{{ OIDC.CLIENT.ID }}"
MINIO_OIDC_CLIENT_SECRET: "{{ OIDC.CLIENT.SECRET }}"
MINIO_OIDC_DISPLAY_NAME: "{{ OIDC.BUTTON_TEXT }}"
MINIO_OIDC_CLAIM_NAME: "{{ RBAC.GROUP.CLAIM }}"
shell: |
set -euo pipefail
container run --rm \
-e MINIO_ROOT_USER \
-e MINIO_ROOT_PASSWORD \
-e MINIO_OIDC_CONFIG_URL \
-e MINIO_OIDC_CLIENT_ID \
-e MINIO_OIDC_CLIENT_SECRET \
-e MINIO_OIDC_DISPLAY_NAME \
-e MINIO_OIDC_CLAIM_NAME \
--entrypoint /bin/sh \
{{ MINIO_MC_IMAGE }} \
-c 'mc alias set minio {{ MINIO_API_URL | quote }} "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null \
&& mc idp openid add minio keycloak \
"config_url=$MINIO_OIDC_CONFIG_URL" \
"client_id=$MINIO_OIDC_CLIENT_ID" \
"client_secret=$MINIO_OIDC_CLIENT_SECRET" \
"display_name=$MINIO_OIDC_DISPLAY_NAME" \
"claim_name=$MINIO_OIDC_CLAIM_NAME" \
scopes=openid,profile,email,groups \
redirect_uri_dynamic=on'
args: { executable: /bin/bash }
register: mc_idp_add
changed_when: '"Successfully" in mc_idp_add.stdout or "Successfully" in mc_idp_add.stderr'
failed_when:
- mc_idp_add.rc != 0
- '"already exists" not in (mc_idp_add.stderr | default(""))'
- name: "π Restart MinIO so the new OIDC IdP takes effect"
when: mc_idp_add.changed | bool
block:
- name: "π Restart MinIO so the named OIDC IdP is picked up by the Console"
environment:
MINIO_ROOT_USER: "{{ lookup('users', 'platform_administrator').username }}"
MINIO_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
shell: |
set -euo pipefail
container run --rm \
-e MINIO_ROOT_USER \
-e MINIO_ROOT_PASSWORD \
--entrypoint /bin/sh \
{{ MINIO_MC_IMAGE }} \
-c 'mc alias set minio {{ MINIO_API_URL | quote }} "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null \
&& mc admin service restart minio --json'
args: { executable: /bin/bash }
register: mc_admin_service_restart
changed_when: mc_admin_service_restart.rc == 0
- name: "β³ Wait for MinIO IAM subsystem to come back after restart"
environment:
MINIO_ROOT_USER: "{{ lookup('users', 'platform_administrator').username }}"
MINIO_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
shell: |
set -euo pipefail
container run --rm \
-e MINIO_ROOT_USER \
-e MINIO_ROOT_PASSWORD \
--entrypoint /bin/sh \
{{ MINIO_MC_IMAGE }} \
-c 'mc alias set minio {{ MINIO_API_URL | quote }} "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null \
&& mc admin policy ls minio'
args: { executable: /bin/bash }
register: mc_admin_policy_ls_after_restart
retries: 60
delay: 5
until: mc_admin_policy_ls_after_restart.rc == 0
changed_when: false
- name: "π Check policy (RAW with slash) exists"
environment:
MINIO_ROOT_USER: "{{ lookup('users', 'platform_administrator').username }}"
MINIO_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
shell: |
set -euo pipefail
container run --rm \
-e MINIO_ROOT_USER \
-e MINIO_ROOT_PASSWORD \
--entrypoint /bin/sh \
{{ MINIO_MC_IMAGE }} \
-c 'mc alias set minio {{ MINIO_API_URL | quote }} "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null \
&& mc admin policy info minio {{ MINIO_OIDC_POLICY_NAME | quote }}'
args: { executable: /bin/bash }
register: mc_policy_info_raw
failed_when: false
changed_when: false
- name: "π Create policy (RAW with slash) if missing"
environment:
MINIO_ROOT_USER: "{{ lookup('users', 'platform_administrator').username }}"
MINIO_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
shell: |
set -euo pipefail
printf '%s' '{{ (MINIO_OIDC_POLICY_CONTENT | from_yaml | to_json) | b64encode }}' \
| base64 -d \
| container run --rm -i \
-e MINIO_ROOT_USER \
-e MINIO_ROOT_PASSWORD \
--entrypoint /bin/sh \
{{ MINIO_MC_IMAGE }} \
-c 'mc alias set minio {{ MINIO_API_URL | quote }} "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null \
&& mc admin policy create minio {{ MINIO_OIDC_POLICY_NAME | quote }} /dev/stdin'
args: { executable: /bin/bash }
register: minio_policy_create
changed_when: false
# rationale: async; consumed only by the STS playwright spec, reaped at the end of this file
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
when:
- mc_policy_info_raw.rc != 0
- name: "β³ Reap the MinIO policy job"
ansible.builtin.include_tasks: utils/async/reap.yml
vars:
async_reap_jobs: "{{ minio_policy_create.results | default([minio_policy_create]) }}"
async_reap_label: "MinIO OIDC policy"
async_reap_tolerate: []