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

Cloud 1996 #30

Merged
merged 23 commits into from
Nov 29, 2023
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ A role to setup a node with a jupyterhub that spawns jupyterlab with or without
Requirements
------------

There are no requirements. This role will setup all the necessary dependencies.
This role needs a working IAM Client in order to configure the JupyterHub authentication plugin.
If you are using this role as it is and not through [INFN PaaS orchestrator](https://my.cloud.infn.it), you should provide `iam_url`, `iam_client_id` and `iam_token` variables.

Role Variables
--------------
Expand Down Expand Up @@ -34,10 +35,12 @@ Variable for the monitoring service:
- `jupyterlab_collaborative`: bool, if to deploy the collaborative service (default: `no`)
- `jupyterlab_collaborative_use_gpu`: bool, if to enable the collaborative service to use the GPU (default: `no`)
- `jupyterlab_collaborative_image`: string, the collaborative Docker image (default: `"dodasts/snj-base-jlabc:v1.1.1-snj"`)
- `iam_url`: URL of the IAM service
- `iam_url`: URL of the IAM service (`Mandatory`)
- `iam_groups`: string with the name of the IAM groups allowed (space separated)
- `iam_admin_groups`: string with the name of the IAM groups that will be admin (space separated)
- `iam_subject` : token subject of the user deploying the service
- `iam_subject` : string, token subject of the user deploying the service
- `iam_client_id`: string, IAM client id (`Mandatory`)
- `iam_token` : string, token needed to interact with the IAM Issuer (`Mandatory`)
- `server_ip`: string with the ip of the current server
- `monitoring`: bool, if to deploy the Grafana monitoring service (default: `yes`)
- `grafana_port`: int, the grafana service port
Expand Down Expand Up @@ -86,6 +89,8 @@ Including an example of how to use your role (for instance, with variables passe
run_jupyter: no
iam_url: https://iam.example.service.it
iam_groups: groupA
iam_client_id: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
iam_token: <TOKEN>

```

Expand Down
2 changes: 2 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ iam_admin_groups: "" # group1 group2
server_ip: "" # 192.168.1.42
dns_name: ""
iam_subject: ""
iam_client_id: ""
iam_token: ""

# monitoring
monitoring: yes
Expand Down
64 changes: 64 additions & 0 deletions tasks/iam-client.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
- name: Retrieve registration endpoint from OpenID configuration
uri:
url: "{{ iam_url }}/.well-known/openid-configuration"
method: GET
return_content: yes
register: openid_config
- name: Set registration endpoint variable
set_fact:
registration_endpoint: "{{ openid_config.json.registration_endpoint }}"

- name: Retrieve the IAM client info
uri:
url: "{{ registration_endpoint }}/{{ iam_client_id }}"
method: GET
headers:
Authorization: "Bearer {{ iam_token }}"
status_code: 200
return_content: yes
register: iam_client_get_response

- name: Save the IAM Client info locally
ansible.builtin.copy:
content: "{{ iam_client_get_response.json | to_nice_json }}"
dest: /usr/local/share/dodasts/jupyterhub/cookies/.client-iam.json

- name: Define the new redirect_uri variable
ansible.builtin.set_fact:
redirect_uri: "https://{{ dns_name }}:{{ jupyter_port }}/hub/oauth_callback"

- name: Import the local IAM Client info file
ansible.builtin.set_fact:
iam_client_info: "{{ lookup('file', '/usr/local/share/dodasts/jupyterhub/cookies/.client-iam.json') }}"

- name: Update the redirect_uris field
ansible.builtin.set_fact:
updated_iam_client_info: "{{ iam_client_info | combine({'redirect_uris': [redirect_uri]}) }}"

- name: Save the updated IAM Client info locally
ansible.builtin.copy:
content: "{{ updated_iam_client_info | to_json }}"
dest: /tmp/updated-iam-client.json

- name: Import the local updated IAM Client info file
ansible.builtin.slurp:
src: /tmp/updated-iam-client.json
register: iam_client_file

- name: Update the IAM client info remotely
uri:
url: "{{ registration_endpoint }}/{{ iam_client_id }}"
method: PUT
headers:
Authorization: "Bearer {{ iam_token }}"
Content-Type: application/json
body_format: json
body: "{{ iam_client_file.content | b64decode | from_json }}"
status_code: 200
register: iam_response

- name: Delete local IAM Client info file
ansible.builtin.file:
path: /tmp/updated-iam-client.json
state: absent
79 changes: 15 additions & 64 deletions tasks/prepare-jupyter-hub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,70 +167,19 @@
cacheable: yes
when: (jupyter_use_gpu | bool)

- block:
- name: Retrieve registration endpoint from OpenID configuration
uri:
url: "{{ iam_url }}/.well-known/openid-configuration"
method: GET
return_content: yes
register: openid_config
- name: Set registration endpoint variable
set_fact:
registration_endpoint: "{{ openid_config.json.registration_endpoint }}"

- name: Collect the IAM client info
uri:
url: "{{ registration_endpoint }}/{{ iam_client_id }}"
method: GET
headers:
Authorization: "Bearer {{ iam_token }}"
status_code: 200
return_content: yes
register: iam_client_get_response

- name: Save the IAM Client info locally
ansible.builtin.copy:
content: "{{ iam_client_get_response.json | to_nice_json }}"
dest: /usr/local/share/dodasts/jupyterhub/cookies/.client-iam.json

- name: Define the new redirect_uri variable
ansible.builtin.set_fact:
redirect_uri: "https://{{ dns_name }}:{{ jupyter_port }}/hub/oauth_callback"

- name: Import the local IAM Client info file
ansible.builtin.set_fact:
iam_client_info: "{{ lookup('file', '/usr/local/share/dodasts/jupyterhub/cookies/.client-iam.json') }}"

- name: Update the redirect_uris field
ansible.builtin.set_fact:
updated_iam_client_info: "{{ iam_client_info | combine({'redirect_uris': [redirect_uri]}) }}"

- name: Save the updated IAM Client info locally
ansible.builtin.copy:
content: "{{ updated_iam_client_info | to_json }}"
dest: /tmp/updated-iam-client.json

- name: Import the local updated IAM Client info file
ansible.builtin.slurp:
src: /tmp/updated-iam-client.json
register: iam_client_file

- name: Update the IAM client info remotely
uri:
url: "{{ registration_endpoint }}/{{ iam_client_id }}"
method: PUT
headers:
Authorization: "Bearer {{ iam_token }}"
Content-Type: application/json
body_format: json
body: "{{ iam_client_file.content | b64decode | from_json }}"
status_code: 200
register: iam_response

- name: Delete local IAM Client info file
ansible.builtin.file:
path: /tmp/updated-iam-client.json
state: absent
# ---------- IAM Client retrieving, updating and local saving ----------
- name: Check vars before interacting with the IAM issuer
assert:
that:
- iam_url | length > 0
- iam_client_id | length > 0
- iam_token | length > 0
- dns_name | length > 0
- jupyter_port | length > 0
fail_msg: Not defined variable among iam_url, iam_client_id, iam_token, dns_name and jupyter_port.

- name: Collect, Update and store locally the IAM Client info
include_tasks: iam-client.yml

# ---------- Collect MIG GPU UUIDs from nvidia-smi ----------
- name: Collect MIG GPU UUIDs
Expand Down Expand Up @@ -260,6 +209,7 @@
iam_client_id: "{{ iam_response.json.client_id }}"
iam_client_secret: "{{ iam_response.json.client_secret }}"
when: cert_manager_type != "self-signed"

- name: prepare compose file (private network)
template:
src: jupyter_hub_priv-compose.j2
Expand All @@ -275,3 +225,4 @@
with_items: "{{ jupyter_images.split() + [ jupyterlab_collaborative_image, compose_base_jhub_image, compose_base_http_proxy_image, compose_base_collab_http_proxy_image ] }}"
async: 1800 # 30 min
poll: 0

Loading