SovereignCloudStack / issues

This repository is used for issues that are cross-repository or not bound to a specific repository.
https://github.com/orgs/SovereignCloudStack/projects/6
2 stars 1 forks source link

Setup example customer domain/realm for federation #596

Open reqa opened 6 months ago

reqa commented 6 months ago

As a SCS Operator, I want to see an example of how to setup Keycloak and Keystone mapping so that a new customer domain/realm can onboard it's federated users.

Acceptance Criteria:

Definition of Ready:

Definition of Done:

JuanPTM commented 6 months ago

I got some notes about what should we make:

I think I didn't forget anything.

JuanPTM commented 5 months ago

MR created, still in draft status until we figure out how to modify the requirements status of the steps in the login flow.

https://github.com/osism/ansible-playbooks/pull/403

JuanPTM commented 5 months ago

Added an initial version to the docs. https://github.com/SovereignCloudStack/docs/pull/190

JuanPTM commented 5 months ago

Currently there is a small problem to finish the ansible-playbook: To change the requirement status of a step inside a login flow, the keycloak CLI tool needs a json file. I've tried to create the file inside the keycloak pod to use it on the next step to modify each step, but I've failed.

Here is a snippet of what I've tried. The main idea is to create the json file and then use it on the next call.

# TODO: Fix subflow ALTERNATIVE status
    - name: JSONs ALTERNATIVE status
      copy: >-
        kubectl exec -n {{ keycloak_namespace }} {{ keycloak_service_container_name }} --
          cat "{\"id\":\"{{ item }}\",\"requirement\":\"ALTERNATIVE\"}" >> "{{ item }}.json"
      environment:
        KUBECONFIG: /share/kubeconfig
      loop: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true

# TODO: Fix subflow ALTERNATIVE status
    - name: Update subflow ALTERNATIVE status
      ansible.builtin.command: >-
        kubectl exec -n {{ keycloak_namespace }} {{ keycloak_service_container_name }} --
          {{ keycloak_kcadm_binary }}
          update authentication/flows/{{ idp_login_flow }}/executions
            --target-realm "{{ keycloak_proxy_realm }}"
            -f "{{ item }}.json"
      environment:
        KUBECONFIG: /share/kubeconfig
      loop: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true
JuanPTM commented 5 months ago

Currently there is a small problem to finish the ansible-playbook: To change the requirement status of a step inside a login flow, the keycloak CLI tool needs a json file. I've tried to create the file inside the keycloak pod to use it on the next step to modify each step, but I've failed.

Here is a snippet of what I've tried. The main idea is to create the json file and then use it on the next call.

# TODO: Fix subflow ALTERNATIVE status
    - name: JSONs ALTERNATIVE status
      copy: >-
        kubectl exec -n {{ keycloak_namespace }} {{ keycloak_service_container_name }} --
          cat "{\"id\":\"{{ item }}\",\"requirement\":\"ALTERNATIVE\"}" >> "{{ item }}.json"
      environment:
        KUBECONFIG: /share/kubeconfig
      loop: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true

# TODO: Fix subflow ALTERNATIVE status
    - name: Update subflow ALTERNATIVE status
      ansible.builtin.command: >-
        kubectl exec -n {{ keycloak_namespace }} {{ keycloak_service_container_name }} --
          {{ keycloak_kcadm_binary }}
          update authentication/flows/{{ idp_login_flow }}/executions
            --target-realm "{{ keycloak_proxy_realm }}"
            -f "{{ item }}.json"
      environment:
        KUBECONFIG: /share/kubeconfig
      loop: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true

My current approach is to create the files, create a task that does the kubectl cp into the kc pod and finally run the kcadmin command

berendt commented 5 months ago

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html

You have to do it this way:

- name: Copy using inline content
  ansible.builtin.copy:
    content: '# This file was moved to /etc/other.conf'
    dest: "{{ item }}.json

You try to use a shell command. If you want to do it this way (ansible.builtin.copy is better) you have to use the ansible.builtin.shell task.

JuanPTM commented 5 months ago

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html

You have to do it this way:

- name: Copy using inline content
  ansible.builtin.copy:
    content: '# This file was moved to /etc/other.conf'
    dest: "{{ item }}.json

You try to use a shell command. If you want to do it this way (ansible.builtin.copy is better) you have to use the ansible.builtin.shell task.

I've tried that but the file created ends up on the osism-ansible container, then I try to kubectl cp it into the keycloak pod, but it doesn't work

# TODO: Fix subflow ALTERNATIVE status
    - name: Create JSONs ALTERNATIVE status
      ansible.builtin.copy:
        dest: "/tmp/{{ item }}.json"
        content: '{"id": {{ item }},"requirement":"ALTERNATIVE"}'
      with_items: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true

    - name: Copy JSONs ALTERNATIVE status into KC
      ansible.builtin.command: >-
        kubectl cp /tmp/{{ item }}.json
        {{ keycloak_namespace }}/{{ keycloak_service_container_name }}:/tmp/{{ item }}.json
      environment:
        KUBECONFIG: /share/kubeconfig
      loop: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true

# TODO: Fix subflow ALTERNATIVE status
    - name: Update subflow ALTERNATIVE status
      ansible.builtin.command: >-
        kubectl exec -n {{ keycloak_namespace }} {{ keycloak_service_container_name }} --
          {{ keycloak_kcadm_binary }}
          update authentication/flows/{{ idp_login_flow }}/executions
            --target-realm "{{ keycloak_proxy_realm }}"
            -f "/tmp/{{ item }}.json"
      environment:
        KUBECONFIG: /share/kubeconfig
      loop: "{{ available_executions_json.stdout | from_json | map(attribute='id') | list }}"
      run_once: true
      no_log: false
      changed_when: true

Currently I have the files correctly created on /tmp/{id}.json

berendt commented 5 months ago

What means "but it doesn't work"? Can you please paste the error message of the failed task. The file /tmp/{{ item }}.json should be available inside the osism-ansible container after the Create JSONs ALTERNATIVE status task. After the Copy JSONs ALTERNATIVE status into KC task it should be available at the same location inside the keycloak_service_container_name container.

JuanPTM commented 5 months ago
TASK [Copy JSONs ALTERNATIVE status into KC] ***********************************                                                                                                                            
Tuesday 14 May 2024  20:23:49 +0000 (0:00:06.012)       0:02:45.132 ***********    

failed: [localhost] (item=c15c44ad-b759-41f0-a7b9-96474950fc5c) => {"ansible_loop_var": "item", "changed": true, "cmd": ["kubectl", "cp", "/tmp/c15c44ad-b759-41f0-a7b9-96474950fc5c.json", "keycloak/keyclo
ak-keycloakx-0:/tmp/c15c44ad-b759-41f0-a7b9-96474950fc5c.json"], "delta": "0:00:00.371678", "end": "2024-05-14 20:23:50.283330", "item": "c15c44ad-b759-41f0-a7b9-96474950fc5c", "msg": "non-zero return cod
e", "rc": 1, "start": "2024-05-14 20:23:49.911652", "stderr": "Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)\nerror: Internal error occurred: error executing command
 in container: failed to exec in container: failed to start exec \"5e3257bf66f1474e938b9cc12408ce9fb677659db65058055a6ee3ec7a6f5d92\": OCI runtime exec failed: exec failed: unable to start container proce
ss: exec: \"tar\": executable file not found in $PATH: unknown", "stderr_lines": ["Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)", "error: Internal error occurred: e
rror executing command in container: failed to exec in container: failed to start exec \"5e3257bf66f1474e938b9cc12408ce9fb677659db65058055a6ee3ec7a6f5d92\": OCI runtime exec failed: exec failed: unable to
 start container process: exec: \"tar\": executable file not found in $PATH: unknown"], "stdout": "", "stdout_lines": []}                                                                                   

failed: [localhost] (item=4f9fb730-8949-47d4-8a91-a85c122d39b5) => {"ansible_loop_var": "item", "changed": true, "cmd": ["kubectl", "cp", "/tmp/4f9fb730-8949-47d4-8a91-a85c122d39b5.json", "keycloak/keyclo
ak-keycloakx-0:/tmp/4f9fb730-8949-47d4-8a91-a85c122d39b5.json"], "delta": "0:00:00.352358", "end": "2024-05-14 20:23:51.059038", "item": "4f9fb730-8949-47d4-8a91-a85c122d39b5", "msg": "non-zero return cod
e", "rc": 1, "start": "2024-05-14 20:23:50.706680", "stderr": "Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)\nerror: Internal error occurred: error executing command
 in container: failed to exec in container: failed to start exec \"f7901d1170861e6f073053d93c66e0c2ca992ea6df3cf67fa1d56ae5b1133b64\": OCI runtime exec failed: exec failed: unable to start container proce
ss: exec: \"tar\": executable file not found in $PATH: unknown", "stderr_lines": ["Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)", "error: Internal error occurred: e
rror executing command in container: failed to exec in container: failed to start exec \"f7901d1170861e6f073053d93c66e0c2ca992ea6df3cf67fa1d56ae5b1133b64\": OCI runtime exec failed: exec failed: unable to
 start container process: exec: \"tar\": executable file not found in $PATH: unknown"], "stdout": "", "stdout_lines": []}                                                                                   

failed: [localhost] (item=076b60d8-1d43-4db8-91ed-2dd0773207ab) => {"ansible_loop_var": "item", "changed": true, "cmd": ["kubectl", "cp", "/tmp/076b60d8-1d43-4db8-91ed-2dd0773207ab.json", "keycloak/keyclo
ak-keycloakx-0:/tmp/076b60d8-1d43-4db8-91ed-2dd0773207ab.json"], "delta": "0:00:00.300320", "end": "2024-05-14 20:23:51.778021", "item": "076b60d8-1d43-4db8-91ed-2dd0773207ab", "msg": "non-zero return cod
e", "rc": 1, "start": "2024-05-14 20:23:51.477701", "stderr": "Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)\nerror: Internal error occurred: error executing command
 in container: failed to exec in container: failed to start exec \"43b4ddb1a6997e4c4229e4ea973632a18901fb6229f33ccf1e6818a6bc87c3f4\": OCI runtime exec failed: exec failed: unable to start container proce
ss: exec: \"tar\": executable file not found in $PATH: unknown", "stderr_lines": ["Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)", "error: Internal error occurred: e
rror executing command in container: failed to exec in container: failed to start exec \"43b4ddb1a6997e4c4229e4ea973632a18901fb6229f33ccf1e6818a6bc87c3f4\": OCI runtime exec failed: exec failed: unable to
 start container process: exec: \"tar\": executable file not found in $PATH: unknown"], "stdout": "", "stdout_lines": []}                                                                                   

failed: [localhost] (item=3adb956c-bb67-44da-a751-7e99852cdfe1) => {"ansible_loop_var": "item", "changed": true, "cmd": ["kubectl", "cp", "/tmp/3adb956c-bb67-44da-a751-7e99852cdfe1.json", "keycloak/keyclo
ak-keycloakx-0:/tmp/3adb956c-bb67-44da-a751-7e99852cdfe1.json"], "delta": "0:00:00.345875", "end": "2024-05-14 20:23:52.517528", "item": "3adb956c-bb67-44da-a751-7e99852cdfe1", "msg": "non-zero return cod
e", "rc": 1, "start": "2024-05-14 20:23:52.171653", "stderr": "Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)\nerror: Internal error occurred: error executing command
 in container: failed to exec in container: failed to start exec \"9fc4e83e745f07aecac141ec74c46395763ba75f9812624a895a4f01e9ea176d\": OCI runtime exec failed: exec failed: unable to start container proce
ss: exec: \"tar\": executable file not found in $PATH: unknown", "stderr_lines": ["Defaulted container \"keycloak\" out of: keycloak, keycloak-update-truststore (init)", "error: Internal error occurred: e
rror executing command in container: failed to exec in container: failed to start exec \"9fc4e83e745f07aecac141ec74c46395763ba75f9812624a895a4f01e9ea176d\": OCI runtime exec failed: exec failed: unable to
 start container process: exec: \"tar\": executable file not found in $PATH: unknown"], "stdout": "", "stdout_lines": []}

The files exists in the osism-ansible container:

dragon@testbed-manager:~$ docker exec -tiu0 osism-ansible /bin/bash

 _____  ___  ____  ___  __  __
(  _  )/ __)(_  _)/ __)(  \/  )
 )(_)( \__ \ _)(_ \__ \ )    (
(_____)(___/(____)(___/(_/\/\_)

Ansible version: 2.16.5
Container version: latest

root@bfbb68b1134d:/ansible# ls /tmp/
002be4f4-3e30-4aaa-8136-45ae8066d3fe.json  4f9fb730-8949-47d4-8a91-a85c122d39b5.json  k8srcp-19495da30542e163558f5bd65593743033a17706048dec15a065a3cfd7af9082.json
076b60d8-1d43-4db8-91ed-2dd0773207ab.json  7a020e52-f314-407a-abdd-1f572345bb4d.json  keycloak
0a59c82d-ab21-4b62-8de4-2f28e71c9011.json  86aca7e3-5bf5-428d-9bec-c1633675225c.json  pymp-1ruxw1v2
1b1c7ba9-36d4-4681-9763-c145bd57a675.json  88c855e9-df12-4339-8b8f-1f459eb0634d.json  pymp-aototh44
3adb956c-bb67-44da-a751-7e99852cdfe1.json  c15c44ad-b759-41f0-a7b9-96474950fc5c.json
482d584f-cad3-4751-9583-2a465cc138cd.json  f2e29ccf-c020-4adf-b7b5-ebbffd83f2dd.json
berendt commented 5 months ago

This is your issue: exec: \"tar\": executable file not found in $PATH: unknown"]

For me it looks like the kubectl cp command tries to call tar inside the keycloak_service_container_name container.

berendt commented 5 months ago
  # Requires that the 'tar' binary is present in your container
  # image.  If 'tar' is not present, 'kubectl cp' will fail.
JuanPTM commented 4 months ago

Found a suitable solution, I'll bake into the scs-keycloak container a script that creates the required files, so it can be called from the playbook. My PoC has worked today so tomorrow there will be a MR to the container repo.

The playbook MR still needs some fixes, but its on a good state right now.