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

Create Azimuth user outside of image build #251

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
os_user_metadata: "{{ os_metadata.get('meta', {}) }}"
os_project_id: "{{ os_metadata.project_id }}"
tasks:
- name: Ensure data mountpoint has the correct permissions
file:
path: "/data"
state: directory
owner: "podman"
group: "podman"
mode: '0755'

- name: Make Jupyter data directory
# Have to make this here not in the base image
# because the data volume has to be mounted first
Expand Down
4 changes: 0 additions & 4 deletions ansible/roles/jupyter-repo2docker/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@
- metadata_var: zenith_volume_id
mountpoint: /etc/zenith/ssh
opts: "defaults,nofail"
owner: podman
group: podman
- metadata_var: data_volume_id
mountpoint: /data
opts: "defaults,nofail"
owner: podman
group: podman

- include_tasks: repo2docker.yml

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,3 @@
state: mounted
fstype: "{{ data_volume.get('fs_type', 'ext4') }}"
opts: "{{ data_volume.get('opts', omit) }}"

- name: Ensure mountpoint permissions
ansible.builtin.file:
state: directory
owner: "{{ data_volume.owner }}"
group: "{{ data_volume.group }}"
path: "{{ data_volume.mountpoint }}"
mode: "{{ data_volume.get('mode', '0755') }}"
2 changes: 1 addition & 1 deletion ansible/roles/linux-data-volumes/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
loop:
- data-volumes-configure-volume.yml

- name: Install ansible-init vars
- name: Install ansible-init vars for volumes
copy:
content: "{{ { 'data_volumes': data_volumes } | to_nice_yaml }}"
dest: /etc/ansible-init/vars/data-volumes.yml
Expand Down
8 changes: 8 additions & 0 deletions ansible/roles/linux-rdp-gateway/files/guacamole-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
vars:
openstack_metadata: "{{ (lookup('url', 'http://169.254.169.254/openstack/latest/meta_data.json') | from_json).get('meta', {}) }}"
tasks:
- name: Ensure data mount has the correct permissions
file:
path: "/data"
state: directory
owner: "podman"
group: "podman"
mode: '0755'

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RDP gateway doesn't have a /data mount

- name: Write Guacamole user mapping file
copy:
content: |
Expand Down
2 changes: 0 additions & 2 deletions ansible/roles/linux-rdp-gateway/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
- metadata_var: zenith_volume_id
mountpoint: /etc/zenith/ssh
opts: "defaults,nofail"
owner: podman
group: podman

- include_role:
name: linux-guacamole
Expand Down
8 changes: 8 additions & 0 deletions ansible/roles/linux-rstudio/files/rstudio-server-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
os_user_metadata: "{{ os_metadata.get('meta', {}) }}"
os_project_id: "{{ os_metadata.project_id }}"
tasks:
- name: Ensure data mount has the correct permissions
file:
path: "/data"
state: directory
owner: "podman"
group: "podman"
mode: '0755'

- name: Ensure rstudio-server service is enabled and started
service:
name: rstudio-server
Expand Down
4 changes: 0 additions & 4 deletions ansible/roles/linux-rstudio/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@
- metadata_var: zenith_volume_id
mountpoint: /etc/zenith/ssh
opts: "defaults,nofail"
owner: podman
group: podman
- metadata_var: data_volume_id
mountpoint: /data
opts: "defaults,nofail"
owner: podman
group: podman

- include_tasks: rstudio.yml

Expand Down
89 changes: 89 additions & 0 deletions ansible/roles/linux-user/files/user-create-playbook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---

- hosts: localhost
gather_facts: true
vars:
openstack_metadata: "{{ (lookup('url', 'http://169.254.169.254/openstack/latest/meta_data.json') | from_json).get('meta', {}) }}"
openstack_userdata: "{{ (lookup('url', 'http://169.254.169.254/openstack/latest/user_data', split_lines=false) | from_yaml) }}"
vars_files:
- /etc/ansible-init/vars/user.yml
tasks:
- name: Get Azimuth user metadata
ansible.builtin.set_fact:
azimuth_username: "azimuth"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workstation playbook is setting a metadata item for this that I think we should respect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, I changed it because of #251 (comment)

Copy link
Collaborator

@mkjpryor mkjpryor Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we either respect the metadata item here or we don't pretend to support it in the workstation patch. I don't really mind which.

azimuth_uid: "{{ openstack_metadata['azimuth_workstation_uid'] | default('1006') }}"
azimuth_gid: "{{ openstack_metadata['azimuth_workstation_gid'] | default('1006') }}"
Comment on lines +14 to +15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These defaults are different to the workstation playbook - is that on purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, I think we're only setting defaults here anyway to get this to work without the metadata.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the idea is to allow this to continue to work without the playbook patch, then the defaults should match the user in the Packer file that is being removed, i.e. 1005.

azimuth_is_sudo: "{{ openstack_metadata['azimuth_workstation_is_sudo'] | default(true) }}"
azimuth_ssh_keys: "{{ openstack_userdata.azimuth_users[0].ssh_authorized_keys | default([]) }}"

- name: Setup Azimuth home directory
ansible.builtin.file:
path: "{{ user_mountpoint }}/{{ azimuth_username }}-home"
state: directory
become: true

- name: Setup bind mount for Azimuth home directory
ansible.posix.mount:
src: "{{ user_mountpoint }}/{{ azimuth_username }}-home"
path: "/home/{{ azimuth_username }}"
opts: bind
fstype: none
state: mounted
become: true

- name: Ensure the Azimuth user is created
ansible.builtin.user:
name: "{{ azimuth_username }}"
uid: "{{ azimuth_uid }}"
shell: "/bin/bash"
become: true

- name: Ensure the Azimuth group has the correct GID
ansible.builtin.group:
name: "{{ azimuth_username }}"
gid: "{{ azimuth_gid }}"
become: true

- name: Ensure Azimuth home directory has the correct permissions
ansible.builtin.file:
path: "{{ user_mountpoint }}"
state: directory
owner: "{{ azimuth_username }}"
group: "{{ azimuth_username }}"
mode: '750'
recurse: true
become: true

- name: Setup public keys for the Azimuth user
ansible.posix.authorized_key:
user: "{{ azimuth_username }}"
state: present
key: "{{ item }}"
with_items: "{{ azimuth_ssh_keys }}"

- name: Add the Azimuth user to sudoers
ansible.builtin.user:
name: "{{ azimuth_username }}"
groups: sudo
when: azimuth_is_sudo | bool

- name: Make sudo without password for users
ansible.builtin.copy:
dest: /etc/sudoers.d/80-ansible-sudo-user
content: "{{ azimuth_username }} ALL=(ALL) NOPASSWD:ALL"
mode: 0440
when: azimuth_is_sudo | bool

- name: Setup MOTD for user
ansible.builtin.blockinfile:
path: /etc/motd
create: true
block: |
This Azimuth user is mounted at {{ user_mountpoint }}/{{ azimuth_username }}-home

Note that this user storage is EPHEMERAL and is removed on platform deletion, use
/platform for persistent storage between workstations.

More information is available in the Azimuth user documentation:
https://azimuth-cloud.github.io/azimuth-user-docs/platforms/linux-workstation/
become: true
21 changes: 21 additions & 0 deletions ansible/roles/linux-user/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---

- name: Ensure ansible-init directories exist
file:
path: "/etc/ansible-init/{{ item }}"
state: directory
loop:
- includes
- playbooks
- vars

- name: Install ansible-init vars for users
copy:
content: "{{ { 'user_mountpoint': user_mountpoint } | to_nice_yaml }}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stylistic choice, but I like having this as a nicely formatted variable under vars like the other places where this is done, as I think it is easier to read.

dest: /etc/ansible-init/vars/user.yml

- name: Install ansible-init playbook
copy:
src: user-create-playbook.yml
# Leave some numbers for playbooks to execute before
dest: /etc/ansible-init/playbooks/15-user-create.yml
27 changes: 18 additions & 9 deletions ansible/roles/linux-webconsole/files/guacamole-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,26 @@
# generating ]]>, which will still break XML. Therefore remove ">" from special
# characters.
special_chars: '!"#$%&()*+,-./:;<=?@[\]^_`{|}~'

- block:
- name: Get Guacamole user info
getent:
database: passwd
key: "{{ guacamole_user }}"

- name: Get Guacamole user info
getent:
database: passwd
key: "{{ guacamole_user }}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the guacamole_user to use the username specified in metadata?

The way this is currently set up, it will use the username baked into the vars file at build time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, although I'm not sure if we're going to be using this outside of the case where the user is 'azimuth'.

I suppose we should decide on whether to set the user in metadata or assume the user is always azimuth.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, I don't care which we do but we need to be consistent between the image and the playbook. Probably using a fixed azimuth username is easier for now, but don't pretend it can be changed in the playbook patch.


- name: Set Guacamole user home directory
set_fact:
guacamole_user_home: "{{ ansible_facts.getent_passwd[guacamole_user][4] }}"

- name: Set Guacamole user home directory
set_fact:
guacamole_user_home: "{{ ansible_facts.getent_passwd[guacamole_user][4] }}"
- name: Configure user for systemd unit
copy:
dest: /etc/systemd/system/vncserver@:1.service.d/user.conf
content: |
[Service]
Environment=VNCSERVER_PASSWD_FILE={{ guacamole_user_home }}/.vnc/passwd
User={{ guacamole_user }}
become: true

- block:
- name: Generate VNC password
command: vncpasswd -f
args:
Expand Down
27 changes: 14 additions & 13 deletions ansible/roles/linux-webconsole/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,30 @@
name: apptainer
state: present

- block:
- include_tasks: desktop.yml
- include_tasks: vnc_server.yml
when: desktop_enabled is defined and desktop_enabled

- include_role:
name: linux-podman
tasks_from: install.yml

- include_role:
name: linux-data-volumes
vars:
data_volumes:
- metadata_var: zenith_volume_id
mountpoint: /etc/zenith/ssh
opts: "defaults,nofail"
owner: podman
group: podman
- metadata_var: data_volume_id
mountpoint: /data
opts: "defaults,nofail"
owner: azimuth
group: azimuth

- include_role:
name: linux-user
vars:
user_mountpoint: /data

- block:
- include_tasks: desktop.yml
- include_tasks: vnc_server.yml
when: desktop_enabled is defined and desktop_enabled

- include_role:
name: linux-podman
tasks_from: install.yml

- include_role:
name: linux-zenith-ssh
Expand Down
18 changes: 0 additions & 18 deletions ansible/roles/linux-webconsole/tasks/vnc_server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,7 @@
- start_order.conf
- restart.conf

- name: Get guacamole user info
user:
name: "{{ guacamole_user }}"
state: present
register: guacamole_user_info

- name: Set VNC server user facts for guacamole user
set_fact:
guacamole_user_vnc_config_dir: "{{ guacamole_user_info.home }}/.vnc"

- name: Ensure systemd overrides directory exists
file:
path: /etc/systemd/system/vncserver@:1.service.d
state: directory

- name: Configure user for systemd unit
copy:
dest: /etc/systemd/system/vncserver@:1.service.d/user.conf
content: |
[Service]
Environment=VNCSERVER_PASSWD_FILE={{ guacamole_user_vnc_config_dir }}/passwd
User={{ guacamole_user }}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
"zenith_sshd_port" not in os_user_metadata or
zenith_registrar_token_metadata_key not in os_user_metadata

- name: Ensure Zenith SSH mount has the correct permissions
file:
path: "/etc/zenith/ssh/"
state: directory
owner: "podman"
group: "podman"
mode: '0755'

- name: Set Zenith facts
set_fact:
zenith_client_registrar_url: "{{ os_user_metadata.zenith_registrar_url }}"
Expand Down
14 changes: 0 additions & 14 deletions packer/linux-desktop.pkr.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,6 @@ source "openstack" "linux-desktop" {
communicator = "ssh"
ssh_username = var.ssh_username
ssh_clear_authorized_keys = true

user_data = <<-EOF
#cloud-config
users:
- default
# create a new default-type user matching Slurm platform:
- name: azimuth
uid: 1005
lock_passwd: true
gecos: Azimuth User
groups: [adm, systemd-journal]
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
shell: /bin/bash
EOF
}

build {
Expand Down
Loading