From dc58a257499f4e6653664f78e2853034c15f3101 Mon Sep 17 00:00:00 2001 From: wtripp180901 <78219569+wtripp180901@users.noreply.github.com> Date: Wed, 8 Jan 2025 16:58:23 +0000 Subject: [PATCH] Change defaults so a cookiecutter environment is fully functional (#473) * cookiecutter environment now has working defaults * updated docs * refactored ood demo user into cookiecutter * updated docs * changed secret name * Doc changes Co-authored-by: Steve Brasier <33413598+sjpb@users.noreply.github.com> * rename * replaced testuser with demo_user * selinux now defaults to disabled * bump images * updated readme * moved files and removed redundant ood config * environments now have grafana anonymous auth by default * docs update Co-authored-by: Steve Brasier <33413598+sjpb@users.noreply.github.com> --------- Co-authored-by: Steve Brasier <33413598+sjpb@users.noreply.github.com> --- .github/workflows/stackhpc.yml | 10 +++++----- README.md | 1 + ansible/roles/passwords/defaults/main.yml | 1 + ansible/roles/passwords/tasks/validate.yml | 2 +- docs/{openondemand.README.md => openondemand.md} | 12 +++++++----- docs/production.md | 4 ++++ .../.caas/inventory/group_vars/all/selinux.yml | 1 - .../inventory/group_vars/all/basic_users.yml | 6 +++--- .../.stackhpc/inventory/group_vars/all/freeipa.yml | 4 ++-- .../{grafana/overrides.yml => all/grafana.yml} | 0 .../{openhpc/overrides.yml => all/openhpc.yml} | 0 .../inventory/group_vars/all/openondemand.yml | 9 ++++++++- .../inventory/group_vars/openondemand/overrides.yml | 8 -------- .../inventory/group_vars/selinux/overrides.yml | 1 - .../common/inventory/group_vars/all/openondemand.yml | 7 ++++++- .../common/inventory/group_vars/all/selinux.yml | 2 +- environments/common/layouts/everything | 6 ++++-- .../inventory/group_vars/all/basic_users.yml | 4 ++++ .../inventory/group_vars/all/grafana.yml | 1 + .../terraform/variables.tf | 2 +- 20 files changed, 49 insertions(+), 32 deletions(-) rename docs/{openondemand.README.md => openondemand.md} (76%) delete mode 100644 environments/.caas/inventory/group_vars/all/selinux.yml rename environments/.stackhpc/inventory/group_vars/{grafana/overrides.yml => all/grafana.yml} (100%) rename environments/.stackhpc/inventory/group_vars/{openhpc/overrides.yml => all/openhpc.yml} (100%) delete mode 100644 environments/.stackhpc/inventory/group_vars/openondemand/overrides.yml delete mode 100644 environments/.stackhpc/inventory/group_vars/selinux/overrides.yml create mode 100644 environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/basic_users.yml create mode 100644 environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/grafana.yml diff --git a/.github/workflows/stackhpc.yml b/.github/workflows/stackhpc.yml index b08854adb..eaca3a3ae 100644 --- a/.github/workflows/stackhpc.yml +++ b/.github/workflows/stackhpc.yml @@ -99,9 +99,9 @@ jobs: . venv/bin/activate . environments/.stackhpc/activate ansible-playbook ansible/adhoc/generate-passwords.yml - echo vault_testuser_password: "$TESTUSER_PASSWORD" > $APPLIANCES_ENVIRONMENT_ROOT/inventory/group_vars/all/test_user.yml + echo vault_demo_user_password: "$DEMO_USER_PASSWORD" > $APPLIANCES_ENVIRONMENT_ROOT/inventory/group_vars/all/test_user.yml env: - TESTUSER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }} + DEMO_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }} - name: Provision nodes using fat image id: provision_servers @@ -163,12 +163,12 @@ jobs: --spider \ --server-response \ --no-check-certificate \ - --http-user=testuser \ - --http-password=${TESTUSER_PASSWORD} https://${openondemand_servername} \ + --http-user=demo_user \ + --http-password=${DEMO_USER_PASSWORD} https://${openondemand_servername} \ 2>&1) (echo $statuscode | grep "200 OK") || (echo $statuscode && exit 1) env: - TESTUSER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }} + DEMO_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }} # - name: Build environment-specific compute image # id: packer_build diff --git a/README.md b/README.md index f66441915..593837ccd 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ To deploy this infrastructure, ensure the venv and the environment are [activate export OS_CLOUD=openstack cd environments/$ENV/terraform/ + tofu init tofu apply and follow the prompts. Note the OS_CLOUD environment variable assumes that OpenStack credentials are defined using a [clouds.yaml](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#clouds-yaml) file in a default location with the default cloud name of `openstack`. diff --git a/ansible/roles/passwords/defaults/main.yml b/ansible/roles/passwords/defaults/main.yml index 2587e8499..929aac465 100644 --- a/ansible/roles/passwords/defaults/main.yml +++ b/ansible/roles/passwords/defaults/main.yml @@ -10,6 +10,7 @@ slurm_appliance_secrets: vault_freeipa_admin_password: "{{ vault_freeipa_admin_password | default(lookup('password', '/dev/null')) }}" vault_k3s_token: "{{ vault_k3s_token | default(lookup('ansible.builtin.password', '/dev/null', length=64)) }}" vault_pulp_admin_password: "{{ vault_pulp_admin_password | default(lookup('password', '/dev/null', chars=['ascii_letters', 'digits'])) }}" + vault_demo_user_password: "{{ vault_demo_user_password | default(lookup('password', '/dev/null')) }}" secrets_openhpc_mungekey_default: content: "{{ lookup('pipe', 'dd if=/dev/urandom bs=1 count=1024 2>/dev/null | base64') }}" diff --git a/ansible/roles/passwords/tasks/validate.yml b/ansible/roles/passwords/tasks/validate.yml index 9279ffdbf..b30b0696e 100644 --- a/ansible/roles/passwords/tasks/validate.yml +++ b/ansible/roles/passwords/tasks/validate.yml @@ -1,4 +1,4 @@ - name: Assert secrets created assert: - that: (hostvars[inventory_hostname].keys() | select('contains', 'vault_') | length) > 1 # 1 as may have vault_testuser_password defined in dev + that: (hostvars[inventory_hostname].keys() | select('contains', 'vault_') | length) > 1 # 1 as may have vault_demo_user_password defined in dev fail_msg: "No inventory variables 'vault_*' found: Has ansible/adhoc/generate-passwords.yml been run?" diff --git a/docs/openondemand.README.md b/docs/openondemand.md similarity index 76% rename from docs/openondemand.README.md rename to docs/openondemand.md index 5daba3408..3bd6c9e9f 100644 --- a/docs/openondemand.README.md +++ b/docs/openondemand.md @@ -30,11 +30,10 @@ The above functionality is configured by running the `ansible/portal.yml` playbo See the [ansible/roles/openondemand/README.md](../ansible/roles/openondemand/README.md) for more details on the variables described below. -At minimum the following must be defined: -- `openondemand_servername` - this must be defined for both `openondemand` and `grafana` hosts (when Grafana is enabled). It is suggested to place it groupvars for `all`. -- `openondemand_auth` and any corresponding options. -- `openondemand_desktop_partition` and `openondemand_jupyter_partition` if the corresponding inventory groups are defined. -- `openondemand_host_regex` if `openondemand_desktop` or `openondemand_jupyter` inventory groups are defined and/or proxying Grafana via Open Ondemand is required. +The following variables have been given default values to allow Open Ondemand to work in a newly created environment without additional configuration, but generally should be overridden in `environment/site/inventory/group_vars/all/` with site-specific values: +- `openondemand_servername` - this must be defined for both `openondemand` and `grafana` hosts (when Grafana is enabled). Default is `ansible_host` (i.e. the IP address) of the first host in the `openondemand` group. +- `openondemand_auth` and any corresponding options. Defaults to `basic_pam`. +- `openondemand_desktop_partition` and `openondemand_jupyter_partition` if the corresponding inventory groups are defined. Defaults to the first compute group defined in the `compute` Terraform variable in `environments/$ENV/terraform`. It is also recommended to set: - `openondemand_dashboard_support_url` @@ -45,3 +44,6 @@ If shared filesystems other than `$HOME` are available, add paths to `openondema The appliance automatically configures Open Ondemand to proxy Grafana and adds a link to it on the Open Ondemand dashboard. This means no external IP (or SSH proxying etc) is required to access Grafana (which by default is deployed on the control node). To allow users to authenticate to Grafana, the simplest option is to enable anonymous (View-only) login by setting `grafana_auth_anonymous` (see [environments/common/inventory/group_vars/all/grafana.yml](../environments/common/inventory/group_vars/all/grafana.yml)[^1]). [^1]: Note that if `openondemand_auth` is `basic_pam` and anonymous Grafana login is enabled, the appliance will (by default) configure Open Ondemand's Apache server to remove the Authorisation header from proxying of all `node/` addresses. This is done as otherwise Grafana tries to use this header to authenticate, which fails with the default configuration where only the admin Grafana user `grafana` is created. Note that the removal of this header in this configuration means it cannot be used to authenticate proxied interactive applications - however the appliance-deployed remote desktop and Jupyter Notebook server applications use other authentication methods. An alternative if using `basic_pam` is not to enable anonymous Grafana login and to create Grafana users matching the local users (e.g. in `environments//hooks/post.yml`). + +# Access +By default the appliance authenticates against OOD with basic auth through PAM. When creating a new environment, a new user with username `demo_user` will be created. Its password is found under `vault_openondemand_default_user` in the appliance secrets store in `environments/{ENV}/inventory/group_vars/all/secrets.yml`. Other users can be defined by overriding the `basic_users_users` variable in your environment (templated into `environments/{ENV}/inventory/group_vars/all/basic_users.yml` by default). diff --git a/docs/production.md b/docs/production.md index c1b139994..5190ecae6 100644 --- a/docs/production.md +++ b/docs/production.md @@ -98,6 +98,10 @@ and referenced from the `site` and `production` environments, e.g.: - Configure Open OpenOndemand - see [specific documentation](openondemand.README.md). +- Remove the `demo_user` user from `environments/$ENV/inventory/group_vars/all/basic_users.yml` + +- Consider whether having (read-only) access to Grafana without login is OK. If not, remove `grafana_auth_anonymous` in `environments/$ENV/inventory/group_vars/all/grafana.yml` + - Modify `environments/site/terraform/nodes.tf` to provide fixed IPs for at least the control node, and (if not using FIPs) the login node(s): diff --git a/environments/.caas/inventory/group_vars/all/selinux.yml b/environments/.caas/inventory/group_vars/all/selinux.yml deleted file mode 100644 index 1f1098126..000000000 --- a/environments/.caas/inventory/group_vars/all/selinux.yml +++ /dev/null @@ -1 +0,0 @@ -selinux_state: disabled \ No newline at end of file diff --git a/environments/.stackhpc/inventory/group_vars/all/basic_users.yml b/environments/.stackhpc/inventory/group_vars/all/basic_users.yml index ae416cf72..e2088ffd9 100644 --- a/environments/.stackhpc/inventory/group_vars/all/basic_users.yml +++ b/environments/.stackhpc/inventory/group_vars/all/basic_users.yml @@ -1,6 +1,6 @@ -test_user_password: "{{ lookup('env', 'TESTUSER_PASSWORD') | default(vault_testuser_password, true) }}" # CI uses env, debug can set vault_testuser_password +test_demo_user_password: "{{ lookup('env', 'DEMO_USER_PASSWORD') | default(vault_demo_user_password, true) }}" # CI uses env, debug can set vault_demo_user_password basic_users_users: - - name: testuser # can't use rocky as $HOME isn't shared! - password: "{{ test_user_password | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}" # idempotent + - name: demo_user # can't use rocky as $HOME isn't shared! + password: "{{ test_demo_user_password | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}" # idempotent uid: 1005 diff --git a/environments/.stackhpc/inventory/group_vars/all/freeipa.yml b/environments/.stackhpc/inventory/group_vars/all/freeipa.yml index 4b3750650..9a979ab16 100644 --- a/environments/.stackhpc/inventory/group_vars/all/freeipa.yml +++ b/environments/.stackhpc/inventory/group_vars/all/freeipa.yml @@ -2,8 +2,8 @@ # NB: Users defined this way have expired passwords freeipa_users: - - name: testuser # can't use rocky as $HOME isn't shared! - password: "{{ test_user_password }}" + - name: demo_user # can't use rocky as $HOME isn't shared! + password: "{{ test_demo_user_password }}" givenname: test sn: test diff --git a/environments/.stackhpc/inventory/group_vars/grafana/overrides.yml b/environments/.stackhpc/inventory/group_vars/all/grafana.yml similarity index 100% rename from environments/.stackhpc/inventory/group_vars/grafana/overrides.yml rename to environments/.stackhpc/inventory/group_vars/all/grafana.yml diff --git a/environments/.stackhpc/inventory/group_vars/openhpc/overrides.yml b/environments/.stackhpc/inventory/group_vars/all/openhpc.yml similarity index 100% rename from environments/.stackhpc/inventory/group_vars/openhpc/overrides.yml rename to environments/.stackhpc/inventory/group_vars/all/openhpc.yml diff --git a/environments/.stackhpc/inventory/group_vars/all/openondemand.yml b/environments/.stackhpc/inventory/group_vars/all/openondemand.yml index 11d475664..72b6cf476 100644 --- a/environments/.stackhpc/inventory/group_vars/all/openondemand.yml +++ b/environments/.stackhpc/inventory/group_vars/all/openondemand.yml @@ -1 +1,8 @@ -openondemand_servername: "{{ hostvars[ groups['openondemand'] | first].ansible_host }}" # Use a SOCKS proxy to acccess +openondemand_auth: basic_pam +openondemand_jupyter_partition: standard +openondemand_desktop_partition: standard +#openondemand_dashboard_support_url: +#openondemand_dashboard_docs_url: +#openondemand_filesapp_paths: +ondemand_package: ondemand-"{{ ondemand_package_version }}" +ondemand_package_version: '3.1.10' diff --git a/environments/.stackhpc/inventory/group_vars/openondemand/overrides.yml b/environments/.stackhpc/inventory/group_vars/openondemand/overrides.yml deleted file mode 100644 index 72b6cf476..000000000 --- a/environments/.stackhpc/inventory/group_vars/openondemand/overrides.yml +++ /dev/null @@ -1,8 +0,0 @@ -openondemand_auth: basic_pam -openondemand_jupyter_partition: standard -openondemand_desktop_partition: standard -#openondemand_dashboard_support_url: -#openondemand_dashboard_docs_url: -#openondemand_filesapp_paths: -ondemand_package: ondemand-"{{ ondemand_package_version }}" -ondemand_package_version: '3.1.10' diff --git a/environments/.stackhpc/inventory/group_vars/selinux/overrides.yml b/environments/.stackhpc/inventory/group_vars/selinux/overrides.yml deleted file mode 100644 index c3b28b913..000000000 --- a/environments/.stackhpc/inventory/group_vars/selinux/overrides.yml +++ /dev/null @@ -1 +0,0 @@ -selinux_state: disabled diff --git a/environments/common/inventory/group_vars/all/openondemand.yml b/environments/common/inventory/group_vars/all/openondemand.yml index 5e85392ca..cce923fcc 100644 --- a/environments/common/inventory/group_vars/all/openondemand.yml +++ b/environments/common/inventory/group_vars/all/openondemand.yml @@ -5,7 +5,12 @@ # NB: Variables prefixed ood_ are all from https://github.com/OSC/ood-ansible -# openondemand_servername: '' # Must be defined when using openondemand +openondemand_servername: "{{ hostvars[groups['openondemand'].0].ansible_host if groups['openondemand'] else '' }}" + +openondemand_auth: basic_pam + +openondemand_jupyter_partition: "{{ openhpc_slurm_partitions[0]['name'] }}" +openondemand_desktop_partition: "{{ openhpc_slurm_partitions[0]['name'] }}" # Regex defining hosts which openondemand can proxy; the default regex is compute nodes (for apps) and grafana host, # e.g. if the group `compute` has hosts `compute-{0,1,2,..}` this will be '(compute-\d+)|(control)'. diff --git a/environments/common/inventory/group_vars/all/selinux.yml b/environments/common/inventory/group_vars/all/selinux.yml index 25fbbd68f..fef5c3f58 100644 --- a/environments/common/inventory/group_vars/all/selinux.yml +++ b/environments/common/inventory/group_vars/all/selinux.yml @@ -1,4 +1,4 @@ --- -selinux_state: permissive +selinux_state: disabled selinux_policy: targeted diff --git a/environments/common/layouts/everything b/environments/common/layouts/everything index 878bebbf3..ad9fa536a 100644 --- a/environments/common/layouts/everything +++ b/environments/common/layouts/everything @@ -36,8 +36,9 @@ login [block_devices:children] # Environment-specific so not defined here -[basic_users] +[basic_users:children] # Add `openhpc` group to add Slurm users via creation of users on each node. +openhpc [openondemand:children] # Host to run Open Ondemand server on - subset of login @@ -51,8 +52,9 @@ compute # Subset of compute to run a Jupyter Notebook servers on via Open Ondemand compute -[etc_hosts] +[etc_hosts:children] # Hosts to manage /etc/hosts e.g. if no internal DNS. See ansible/roles/etc_hosts/README.md +cluster [cuda] # Hosts to install NVIDIA CUDA on - see ansible/roles/cuda/README.md diff --git a/environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/basic_users.yml b/environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/basic_users.yml new file mode 100644 index 000000000..dc993c3b8 --- /dev/null +++ b/environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/basic_users.yml @@ -0,0 +1,4 @@ +basic_users_users: + - name: demo_user + password: "{% raw %}{{ vault_demo_user_password | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}{% endraw %}" # idempotent + uid: 1005 diff --git a/environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/grafana.yml b/environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/grafana.yml new file mode 100644 index 000000000..521616a1b --- /dev/null +++ b/environments/skeleton/{{cookiecutter.environment}}/inventory/group_vars/all/grafana.yml @@ -0,0 +1 @@ +grafana_auth_anonymous: true \ No newline at end of file diff --git a/environments/skeleton/{{cookiecutter.environment}}/terraform/variables.tf b/environments/skeleton/{{cookiecutter.environment}}/terraform/variables.tf index 0f5eefa18..0a5dde56b 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/terraform/variables.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/terraform/variables.tf @@ -6,7 +6,7 @@ variable "cluster_name" { variable "cluster_domain_suffix" { type = string description = "Domain suffix for cluster" - default = "invalid" + default = "internal" } variable "cluster_net" {