From 3cc930fa971b387f5c64e1febc35850f2bed2b0c Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 25 Mar 2025 11:28:48 +0000 Subject: [PATCH] feat: implement RFC 16 to allow emergency node access (#3557) --- .github/actions/e2e_emergency_ssh/action.yml | 68 +++++++++++++++++++ .github/actions/e2e_test/action.yml | 12 +++- .github/workflows/e2e-test-weekly.yml | 30 +++++++- .github/workflows/e2e-test.yml | 1 + cli/internal/cmd/ssh.go | 29 +++----- cli/internal/cmd/ssh_test.go | 31 ++------- docs/docs/reference/cli.md | 8 +-- docs/docs/workflows/troubleshooting.md | 49 +++++++++++++ image/base/mkosi.conf | 1 + .../system-preset/30-constellation.preset | 1 + .../system/create-host-ssh-key.service | 10 +++ image/mirror/SHA256SUMS | 28 ++++---- image/mirror/packages.txt | 1 + image/sysroot-tree/etc/ssh/sshd_config | 4 ++ rfc/016-node-access.md | 4 -- terraform/infrastructure/aws/main.tf | 1 + terraform/infrastructure/aws/outputs.tf | 5 ++ terraform/infrastructure/aws/variables.tf | 6 ++ terraform/infrastructure/azure/main.tf | 1 + terraform/infrastructure/azure/outputs.tf | 5 ++ terraform/infrastructure/azure/variables.tf | 6 ++ terraform/infrastructure/gcp/main.tf | 1 + terraform/infrastructure/gcp/outputs.tf | 5 ++ terraform/infrastructure/gcp/variables.tf | 6 ++ terraform/infrastructure/openstack/main.tf | 1 + terraform/infrastructure/openstack/outputs.tf | 5 ++ .../infrastructure/openstack/variables.tf | 6 ++ 27 files changed, 256 insertions(+), 69 deletions(-) create mode 100644 .github/actions/e2e_emergency_ssh/action.yml create mode 100644 image/base/mkosi.skeleton/usr/lib/systemd/system/create-host-ssh-key.service create mode 100644 image/sysroot-tree/etc/ssh/sshd_config diff --git a/.github/actions/e2e_emergency_ssh/action.yml b/.github/actions/e2e_emergency_ssh/action.yml new file mode 100644 index 000000000..81712956a --- /dev/null +++ b/.github/actions/e2e_emergency_ssh/action.yml @@ -0,0 +1,68 @@ +name: Emergency ssh +description: "Verify that an emergency ssh connection can be established." + +inputs: + kubeconfig: + description: "The kubeconfig file for the cluster." + required: true + +runs: + using: "composite" + steps: + - name: Test emergency ssh + shell: bash + env: + KUBECONFIG: ${{ inputs.kubeconfig }} + run: | + set -euo pipefail + + # Activate emergency ssh access to the cluster + pushd ./constellation-terraform + echo "emergency_ssh = true" >> terraform.tfvars + terraform apply -auto-approve + lb="$(terraform output -raw loadbalancer_address)" + popd + + # write ssh config + cat > ssh_config < '.\nYou can obtain the private node IP via the web UI of your CSP.\n", constants.TerraformWorkingDir) + cmd.Printf("You can now connect to a node using the \"constellation_cert.pub\" certificate.\nLook at the documentation for a how-to guide:\n\n\thttps://docs.edgeless.systems/constellation/workflows/troubleshooting#emergency-ssh-access\n") return nil } diff --git a/cli/internal/cmd/ssh_test.go b/cli/internal/cmd/ssh_test.go index 7f5fe566d..1150b1105 100644 --- a/cli/internal/cmd/ssh_test.go +++ b/cli/internal/cmd/ssh_test.go @@ -8,7 +8,6 @@ package cmd import ( "bytes" - "fmt" "testing" "github.com/edgelesssys/constellation/v2/internal/constants" @@ -29,18 +28,6 @@ func TestSSH(t *testing.T) { "salt": "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAK" } ` - - newFsWithDirectory := func() file.Handler { - require := require.New(t) - fh := file.NewHandler(afero.NewMemMapFs()) - require.NoError(fh.MkdirAll(constants.TerraformWorkingDir)) - return fh - } - newFsNoDirectory := func() file.Handler { - fh := file.NewHandler(afero.NewMemMapFs()) - return fh - } - testCases := map[string]struct { fh file.Handler pubKey string @@ -48,38 +35,32 @@ func TestSSH(t *testing.T) { wantErr bool }{ "everything exists": { - fh: newFsWithDirectory(), + fh: file.NewHandler(afero.NewMemMapFs()), pubKey: someSSHPubKey, masterSecret: someMasterSecret, }, "no public key": { - fh: newFsWithDirectory(), + fh: file.NewHandler(afero.NewMemMapFs()), masterSecret: someMasterSecret, wantErr: true, }, "no master secret": { - fh: newFsWithDirectory(), + fh: file.NewHandler(afero.NewMemMapFs()), pubKey: someSSHPubKey, wantErr: true, }, "malformed public key": { - fh: newFsWithDirectory(), + fh: file.NewHandler(afero.NewMemMapFs()), pubKey: "asdf", masterSecret: someMasterSecret, wantErr: true, }, "malformed master secret": { - fh: newFsWithDirectory(), + fh: file.NewHandler(afero.NewMemMapFs()), masterSecret: "asdf", pubKey: someSSHPubKey, wantErr: true, }, - "directory does not exist": { - fh: newFsNoDirectory(), - pubKey: someSSHPubKey, - masterSecret: someMasterSecret, - wantErr: true, - }, } for name, tc := range testCases { @@ -104,7 +85,7 @@ func TestSSH(t *testing.T) { assert.Error(err) } else { assert.NoError(err) - cert, err := tc.fh.Read(fmt.Sprintf("%s/ca_cert.pub", constants.TerraformWorkingDir)) + cert, err := tc.fh.Read("constellation_cert.pub") require.NoError(err) _, _, _, _, err = ssh.ParseAuthorizedKey(cert) require.NoError(err) diff --git a/docs/docs/reference/cli.md b/docs/docs/reference/cli.md index 7bb4d5b40..2ce14ef34 100644 --- a/docs/docs/reference/cli.md +++ b/docs/docs/reference/cli.md @@ -39,7 +39,7 @@ Commands: * [apply](#constellation-iam-upgrade-apply): Apply an upgrade to an IAM profile * [version](#constellation-version): Display version of this CLI * [init](#constellation-init): Initialize the Constellation cluster -* [ssh](#constellation-ssh): Prepare your cluster for emergency ssh access +* [ssh](#constellation-ssh): Generate a certificate for emergency SSH access ## constellation config @@ -845,11 +845,11 @@ constellation init [flags] ## constellation ssh -Prepare your cluster for emergency ssh access +Generate a certificate for emergency SSH access ### Synopsis -Prepare your cluster for emergency ssh access and sign a given key pair for authorization. +Generate a certificate for emergency SSH access to your SSH-enabled constellation cluster. ``` constellation ssh [flags] @@ -859,7 +859,7 @@ constellation ssh [flags] ``` -h, --help help for ssh - --key string the path to an existing ssh public key + --key string the path to an existing SSH public key ``` ### Options inherited from parent commands diff --git a/docs/docs/workflows/troubleshooting.md b/docs/docs/workflows/troubleshooting.md index 195bce1cc..903c829e0 100644 --- a/docs/docs/workflows/troubleshooting.md +++ b/docs/docs/workflows/troubleshooting.md @@ -149,3 +149,52 @@ Debugging via a shell on a node is [directly supported by Kubernetes](https://ku ```bash kubectl delete pod node-debugger-constell-worker-xksa0-000000-bjthj ``` + +### Emergency SSH access + +Emergency SSH access to nodes can be useful to diagnose issues or download important data even if the Kubernetes API isn't reachable anymore. + +1. Enter the `constellation-terraform` directory in your Constellation workspace and enable emergency SSH access to the cluster: + + ```bash + cd constellation-terraform + echo "emergency_ssh = true" >> ./terraform.tfvars + terraform apply + ``` + +2. Sign an existing SSH key with your master secret: + + ```bash + cd ../ # go back to your Constellation workspace + constellation ssh --key your_public_key.pub + ``` + + A certificate is written to `constellation_cert.pub`. + + The certificate is valid for 24 hours and enables you to access your Constellation nodes using + [certificate based authentication](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Certificate-based_Authentication). + +3. Now you can connect to any Constellation node using your certificate and your private key. + + ```bash + ssh -o CertificateFile=constellation_cert.pub -i root@ + ``` + + Normally, you don't have access to the Constellation nodes since they reside in a private network. + To access those nodes anyways, you can use your Constellation load balancer as a proxy jump host. + For this, use something along the following SSH client configuration: + + ```text + Host + ProxyJump none + + Host * + IdentityFile + PreferredAuthentications publickey + CertificateFile=constellation_cert.pub + User root + ProxyJump + ``` + + With this configuration you can connect to a Constellation node using `ssh -F `. + You can obtain the private node IP and the domain name of the load balancer using your CSP's web UI. diff --git a/image/base/mkosi.conf b/image/base/mkosi.conf index 5deab82c8..9201a05ff 100644 --- a/image/base/mkosi.conf +++ b/image/base/mkosi.conf @@ -41,6 +41,7 @@ Packages=containerd # Network Packages=iproute dbus + openssh-server systemd-networkd systemd-resolved diff --git a/image/base/mkosi.skeleton/usr/lib/systemd/system-preset/30-constellation.preset b/image/base/mkosi.skeleton/usr/lib/systemd/system-preset/30-constellation.preset index dcabbedd9..493434d54 100644 --- a/image/base/mkosi.skeleton/usr/lib/systemd/system-preset/30-constellation.preset +++ b/image/base/mkosi.skeleton/usr/lib/systemd/system-preset/30-constellation.preset @@ -10,3 +10,4 @@ enable measurements.service enable export_constellation_debug.service enable systemd-timesyncd enable udev-trigger.service +enable create-host-ssh-key.service diff --git a/image/base/mkosi.skeleton/usr/lib/systemd/system/create-host-ssh-key.service b/image/base/mkosi.skeleton/usr/lib/systemd/system/create-host-ssh-key.service new file mode 100644 index 000000000..28a0862e7 --- /dev/null +++ b/image/base/mkosi.skeleton/usr/lib/systemd/system/create-host-ssh-key.service @@ -0,0 +1,10 @@ +[Unit] +Description=Create a host SSH key +Before=network-pre.target + +[Service] +Type=oneshot +ExecStart=/bin/bash -c "mkdir -p /run/ssh; ssh-keygen -t ecdsa -q -N '' -f /run/ssh/ssh_host_ecdsa_key" + +[Install] +WantedBy=network-pre.target diff --git a/image/mirror/SHA256SUMS b/image/mirror/SHA256SUMS index 0c4139a48..1273c65a3 100644 --- a/image/mirror/SHA256SUMS +++ b/image/mirror/SHA256SUMS @@ -1,4 +1,3 @@ -37abef83e8927b4b48f69fcbdcc249d349c6029cc669401676d01f0ea326999e WALinuxAgent-udev-2.10.0.8-2.fc40.noarch.rpm 03b5889fecc19101fe5c5eb6105bded5705e16a7af957f92b6cc6a7a96e829a8 aardvark-dns-1.14.0-1.fc40.x86_64.rpm ac860c52abbc65af5835d1bd97400c531a5635d39bc1d68e36a1fe54863385ea alternatives-1.27-1.fc40.x86_64.rpm b28e7d90ed3aeb6ca10ecb235b70534665011af35bd3677fb836b1e3cfa602a7 audit-libs-4.0.3-1.fc40.i686.rpm @@ -15,11 +14,11 @@ a9af8b72483b4ad6489e6d2492161120809453373edaf24722cffb394bd1cd15 catatonit-0.2. 5935816e8d377d0385e5287ca12e4d3b43e3c3cdc9cc4deafa653a6dba78611a composefs-libs-1.0.6-1.fc40.x86_64.rpm db246f6445469b5a71e965a081685471768393cf04181e7250ce0ddcb8a9c3d4 conmon-2.1.12-2.fc40.x86_64.rpm adf4b75cdd9fae9d2d37fb71d9f0bf625a6705c0f0a7784569ab21463fe22152 conntrack-tools-1.4.7-7.fc40.x86_64.rpm -4f69d382decd37f53edf1ccf1093a122f209294128038d642beba5f0021131d3 container-selinux-2.235.0-2.fc40.noarch.rpm bbe29e0c7b4ca076d50b4ac3954eb383459230d96b13f353ee71ebd5de33b6d1 containerd-1.6.23-5.fc40.x86_64.rpm 0705251ea64b1558098016b2120f202c5aba77470093cb8f89ce6adb2a0b46b6 containernetworking-plugins-1.5.1-1.fc40.x86_64.rpm fd81f5d57a5feba4658d3ab1c6ab0a1a9551cff5c73263acf960bd7d41acaf25 containers-common-0.62.0-1.fc40.noarch.rpm 1472f71479fed6eb2103bd9653845609c7523523d06c36565a37d818fc144284 containers-common-extra-0.62.0-1.fc40.noarch.rpm +4f69d382decd37f53edf1ccf1093a122f209294128038d642beba5f0021131d3 container-selinux-2.235.0-2.fc40.noarch.rpm 299d3e7e1cbc110d9ae8a47f6ca95142c3e3783cb1464bfbd6bc550c414b97ec coreutils-single-9.4-9.fc40.x86_64.rpm d941a78ffb6e2e0b4c24d0097d0351ced8796edde90208b4bddee459bce0a949 cpio-2.15-1.fc40.x86_64.rpm faa23cb6a7a612c0a6e874c788c5add967c5e193bd38c2e6093b82b38a162f81 cracklib-2.9.11-5.fc40.i686.rpm @@ -68,11 +67,11 @@ a6f2098fc2ed16df92c9325bd7459cc41479e17306a4f9cddfd5df8a1b80d0f8 file-5.45-4.fc f76684ee78408660db83ab9932978a1346b280f4210cd744524b00b2e5891fe1 file-libs-5.45-4.fc40.x86_64.rpm 063af3db3808bea0d5c07dbb2d8369b275e1d05ad0850c80a8fec0413f47cd64 filesystem-3.18-8.fc40.x86_64.rpm 21725de2a93e1ea19f8d298e32a2428a3a08b9c98f22561cc778a807ed43639f findutils-4.9.0-9.fc40.x86_64.rpm +2d6631d65e3b5c91afdb100a51ee8e50294f0e074a944c1662008d878d47456e fuse3-3.16.2-3.fc40.x86_64.rpm +a9c6502a5b190aaf169e93afd337c009e0b2e235e31f3da23d29c7d063ad2ff9 fuse3-libs-3.16.2-3.fc40.x86_64.rpm f4c2d51c7b4577f7b7ef498f8e2afb1b007da2de00cca28e220f50129c40a48c fuse-common-3.16.2-3.fc40.x86_64.rpm f94315e447afb7442033b7b82e43a4ed62754f603afda53930280300855e46c7 fuse-libs-2.9.9-21.fc40.x86_64.rpm 8fe84b7e0319afcc9c9eb28130b74e0cd7c675667a6ce075eb7ee2ec1b0014c2 fuse-overlayfs-1.13-1.fc40.x86_64.rpm -2d6631d65e3b5c91afdb100a51ee8e50294f0e074a944c1662008d878d47456e fuse3-3.16.2-3.fc40.x86_64.rpm -a9c6502a5b190aaf169e93afd337c009e0b2e235e31f3da23d29c7d063ad2ff9 fuse3-libs-3.16.2-3.fc40.x86_64.rpm 6c80dfdaf7b27ea92c1276856b8b2ae5fde1ae5c391b773805be725515fdc1ac gawk-5.3.0-3.fc40.x86_64.rpm c4cc69bf3a2655b9ee9ac23492d377bac57811c5b4f81fbf43537520ee33c7af gawk-all-langpacks-5.3.0-3.fc40.x86_64.rpm 21470eb4ec55006c9efeee84c97772462008fceda1ab332e58d2caddfdaa0d1e gdbm-1.23-6.fc40.x86_64.rpm @@ -160,8 +159,8 @@ cd073c42cb4dfcd224e9b4619883f2c7923ab0b083d7c90b01e3052c89f6b814 libgcc-14.2.1- 10c4c12c6539ffea68974cd9b57013d471ac35fe3bef4833c0a22f6b29fbf489 libgcrypt-1.10.3-3.fc40.x86_64.rpm 03d5f4d139dec2e7c94714b1b9f59d37236dbda9f09271bdda99c71251f15f0e libgomp-14.2.1-3.fc40.x86_64.rpm 8d0a9840e06e72ccf756fa5a79c49f572dc827b0c75ea5a1f923235150d27ae2 libgpg-error-1.49-1.fc40.x86_64.rpm -677a67726c759c94faa94475185e46d028f171c9215390ac601ccd914188afb2 libidn2-2.3.7-1.fc40.i686.rpm -2fd2038b4a94eeede34e46ed0e035e619f77d0e412c70cf4e9bb836957e8f31b libidn2-2.3.7-1.fc40.x86_64.rpm +4fdafe5a28dc18a892713cc2071a46cbcb6561c9c62e10f20f04b0e562187228 libidn2-2.3.8-1.fc40.i686.rpm +63a08c0cf18474582a3e62367b5b4275d079e883e40f4cf32cab7afc316ec2dc libidn2-2.3.8-1.fc40.x86_64.rpm 98b0d9d25bd93c7061ce50480e214944a02d7de725e1d31f4461604380ffb74a libkcapi-1.5.0-4.fc40.x86_64.rpm 84977f5f157172dc7642a3f6602692bb6323b4b106c69f7081882e6c6a81a346 libkcapi-hasher-1.5.0-4.fc40.x86_64.rpm 906bb224af7b2e1ea64c258c6978a610b899b0af5be572ce1c09e36ec58b8a79 libkcapi-hmaccalc-1.5.0-4.fc40.x86_64.rpm @@ -245,6 +244,8 @@ a18edf32e89aefd453998d5d0ec3aa1ea193dac43f80b99db195abd7e8cf1a04 ncurses-libs-6 784e0fbc9ccb7087c10f4c41edbed13904f94244ff658f308614abe48cdf0d42 npth-1.7-1.fc40.x86_64.rpm f814bc09b50daaab468715088ec056373dbc209a5075306e4ce76f5c55eb2b42 nvme-cli-2.8-1.fc40.x86_64.rpm ecc7bc53e45b304272ed047ef681aec637eddae7a7ff0bc851665f3ac164f8ac openldap-2.6.8-2.fc40.x86_64.rpm +49e3e1c7d82ab28b1ab79bb2655a95cadeae2295f5543db8a07d74e090bcb90d openssh-9.6p1-2.fc40.x86_64.rpm +369b4d6e159a53afe9d2803d927f0523ceeae0822353aa8f0d81d0e3211b0788 openssh-server-9.6p1-2.fc40.x86_64.rpm bffa85f8feadf0bf5f7a8cea9ff9f5e49266959df6ae4d61cf929054c09ec2f8 openssl-libs-3.2.4-1.fc40.i686.rpm a1b67803e7afb5e16d977e49b8e63c50537bbaa6b261ab10348d55a54b1562dd openssl-libs-3.2.4-1.fc40.x86_64.rpm 9f0336deb6f1b1524ec48d837622e7e2291995369b0356d7ad1e1d427f3b659a os-prober-1.81-6.fc40.x86_64.rpm @@ -275,10 +276,10 @@ c03ba1c46e0e2dda36e654941f307aaa0d6574ee5143d6fec6e9af2bdf3252a2 popt-1.19-6.fc af85755cda79959a19161ebc26a45e507003298bd97b472b9ab0d512afa5e46a protobuf-c-1.5.0-3.fc40.x86_64.rpm 45ff2e9814aa059f323b23710c73309d41d36306667a3004f5fbb86b0cab4484 psmisc-23.6-6.fc40.x86_64.rpm c000cbb0a7df2c0c61559ab3f3732eacd163b171673298f4ec043cb6d223f364 publicsuffix-list-dafsa-20250116-1.fc40.noarch.rpm -7c703b431508f44c5184b5c1df052ed0f49b7439d68aa3597a9a57a5b26bd648 python-pip-wheel-23.3.2-2.fc40.noarch.rpm -15a80b975cc29fdbf3b71a0c8fa3f76a3fe722529036435b0cf7272f01a560c3 python-unversioned-command-3.12.9-1.fc40.noarch.rpm 870b11ae674851e6f9a02e650681c2e4a9fb1c91311beb944813ac6a2d4e15c9 python3-3.12.9-1.fc40.x86_64.rpm 2406c85716129d4183fcd2be8de2923770e8d6a12de270ac94cc427404a34a26 python3-libs-3.12.9-1.fc40.x86_64.rpm +7c703b431508f44c5184b5c1df052ed0f49b7439d68aa3597a9a57a5b26bd648 python-pip-wheel-23.3.2-2.fc40.noarch.rpm +15a80b975cc29fdbf3b71a0c8fa3f76a3fe722529036435b0cf7272f01a560c3 python-unversioned-command-3.12.9-1.fc40.noarch.rpm b593f10e736995a0a898d37a1e595ad04bf162e7f0e7c9994e3032a9d9bc8799 qemu-user-static-8.2.9-1.fc40.x86_64.rpm 72b6185e59a7b359df273e9fe27dc014c0856341abcd1c907c7810a77cc6980e qemu-user-static-aarch64-8.2.9-1.fc40.x86_64.rpm 7eace5bc3e601266452b8356207604012542a8cd019b576e6d2ab9306c6a8e4c qemu-user-static-alpha-8.2.9-1.fc40.x86_64.rpm @@ -339,17 +340,18 @@ e1d443f7dcaec55eedc34bb66dd798ba9901dba69a169cff46f6c45671a3b3fa unbound-anchor 945aa536bc30050abc1870cef167cb944cf78d6628923476db43201a0054574b util-linux-2.40.2-1.fc40.x86_64.rpm 7ec1b5df780c5a30f8e901179480125a6ea87f1f7bad3b69da7f4b351b88c3dd util-linux-core-2.40-0.9.rc1.fc40.x86_64.rpm b1aa4e816c01c08c18924865640f214f717cdfc66837e53a24b8edfb80a86f9d util-linux-core-2.40.2-1.fc40.x86_64.rpm -397636b0d14b32dd63a07aa7618d4844db60c02e63b46b1d352875d0d7a0b4b3 vim-common-9.1.1202-1.fc40.x86_64.rpm -86be9c9504795e7eaab2e275eb297aaedf90ea626af859995c511dce3c06624e vim-data-9.1.1202-1.fc40.noarch.rpm -d5a64a210ce25f4c22f987ca95f4dbd580ba5dd665544ef1960675668abee724 vim-enhanced-9.1.1202-1.fc40.x86_64.rpm -79312c8907531326438d3f85f8cfca2e2b2f88ed521bc57828a3db3fc283b59c vim-filesystem-9.1.1202-1.fc40.noarch.rpm +7c738289068791356ac633f968512021d125c7d2a858bf5493e14b4ce00c3f52 vim-common-9.1.1227-1.fc40.x86_64.rpm +80766fd967a7c24a543871996a0a857c38d3e7ac205fb3f6403ae9cb5529c424 vim-data-9.1.1227-1.fc40.noarch.rpm +d0f66fbd4e87a9245dd907a19ff90eb88bc60d312f3adfcd189eaf32884480c5 vim-enhanced-9.1.1227-1.fc40.x86_64.rpm +501d0bc28c36c713448570aa4a8a35789bc11c490f93ba4269767043251cd326 vim-filesystem-9.1.1227-1.fc40.noarch.rpm +37abef83e8927b4b48f69fcbdcc249d349c6029cc669401676d01f0ea326999e WALinuxAgent-udev-2.10.0.8-2.fc40.noarch.rpm 69fd53fe41a8811e904b5429b1934a413d88978ec54d5c9e64370be32cbfc2ef wget2-2.2.0-2.fc40.x86_64.rpm a00cc0a87c60ffbf5495a9796ac7074e6a47e0bebbb8c137d902014cd7ff5a30 wget2-libs-2.2.0-2.fc40.x86_64.rpm 09822d8d386dc81619639415a211b34592b0c5d43f7be288691cc4d933a0542c wget2-wget-2.2.0-2.fc40.x86_64.rpm cf0306ceed1c6b3be39060d85f16b1953b464d3a625488b170d3b7aadf600645 which-2.21-41.fc40.x86_64.rpm 4ede95a2fa3bc0ae617c8bf3a375b800163d58733b4829b15d9f038505d79fee whois-nls-5.5.20-3.fc40.noarch.rpm e2195010e857f56b19246f8b821f9391922880b7691b3728a413f540edc890a6 xkeyboard-config-2.41-1.fc40.noarch.rpm -cba0417e89e6a56304bf41dd315a518e0fadf0e8f4572b2cf35d5ca621bee847 xxd-9.1.1202-1.fc40.x86_64.rpm +a9f84423ade79c3577ac2fa302e5e290f01a7432f86d48ba168256cf31fc2807 xxd-9.1.1227-1.fc40.x86_64.rpm ee599a1c4d7ee635e54ec137af4dded83f433b9c8a5976f75ecdcd000b5246e3 xz-5.4.6-3.fc40.x86_64.rpm b92ef78d8ab424c22130e457d0ef691d8197bff61c3b8852205d1b02baba3819 xz-libs-5.4.6-3.fc40.i686.rpm b6ee44b3d7e494b0364f26b7d0b169a8092180af787423cd5e8a47dc0f738a66 xz-libs-5.4.6-3.fc40.x86_64.rpm diff --git a/image/mirror/packages.txt b/image/mirror/packages.txt index fd79a427a..9d6240a2e 100644 --- a/image/mirror/packages.txt +++ b/image/mirror/packages.txt @@ -19,6 +19,7 @@ mokutil nano nano-default-editor nvme-cli +openssh-server passt-selinux passwd podman diff --git a/image/sysroot-tree/etc/ssh/sshd_config b/image/sysroot-tree/etc/ssh/sshd_config new file mode 100644 index 000000000..dec4fd51d --- /dev/null +++ b/image/sysroot-tree/etc/ssh/sshd_config @@ -0,0 +1,4 @@ +HostKey /run/ssh/ssh_host_ecdsa_key +TrustedUserCAKeys /run/ssh/ssh_ca.pub +PasswordAuthentication no +ChallengeResponseAuthentication no diff --git a/rfc/016-node-access.md b/rfc/016-node-access.md index 0c6875c48..abc495400 100644 --- a/rfc/016-node-access.md +++ b/rfc/016-node-access.md @@ -1,7 +1,3 @@ ---- -status: approved, not implemented ---- - # RFC 016: Node Access ## Background diff --git a/terraform/infrastructure/aws/main.tf b/terraform/infrastructure/aws/main.tf index 37d63896b..42b4061ea 100644 --- a/terraform/infrastructure/aws/main.tf +++ b/terraform/infrastructure/aws/main.tf @@ -29,6 +29,7 @@ locals { { name = "recovery", port = "9999", health_check = "TCP" }, { name = "join", port = "30090", health_check = "TCP" }, var.debug ? [{ name = "debugd", port = "4000", health_check = "TCP" }] : [], + var.emergency_ssh ? [{ name = "ssh", port = "22", health_check = "TCP" }] : [], ]) target_group_arns = { control-plane : [ diff --git a/terraform/infrastructure/aws/outputs.tf b/terraform/infrastructure/aws/outputs.tf index 62f220619..b362ff094 100644 --- a/terraform/infrastructure/aws/outputs.tf +++ b/terraform/infrastructure/aws/outputs.tf @@ -45,3 +45,8 @@ output "ip_cidr_node" { value = local.cidr_vpc_subnet_nodes description = "CIDR block of the node network." } + +output "loadbalancer_address" { + value = aws_lb.front_end.dns_name + description = "Public loadbalancer address." +} diff --git a/terraform/infrastructure/aws/variables.tf b/terraform/infrastructure/aws/variables.tf index 67d0ec4d3..d55dedabb 100644 --- a/terraform/infrastructure/aws/variables.tf +++ b/terraform/infrastructure/aws/variables.tf @@ -85,3 +85,9 @@ variable "additional_tags" { default = {} description = "Additional tags that should be applied to created resources." } + +variable "emergency_ssh" { + type = bool + default = false + description = "Wether to expose the SSH port through the public load balancer." +} diff --git a/terraform/infrastructure/azure/main.tf b/terraform/infrastructure/azure/main.tf index 40ff289b3..59286af63 100644 --- a/terraform/infrastructure/azure/main.tf +++ b/terraform/infrastructure/azure/main.tf @@ -40,6 +40,7 @@ locals { { name = "recovery", port = "9999", health_check_protocol = "Tcp", path = null, priority = 104 }, { name = "join", port = "30090", health_check_protocol = "Tcp", path = null, priority = 105 }, var.debug ? [{ name = "debugd", port = "4000", health_check_protocol = "Tcp", path = null, priority = 106 }] : [], + var.emergency_ssh ? [{ name = "ssh", port = "22", health_check_protocol = "Tcp", path = null, priority = 107 }] : [], ]) // wildcard_lb_dns_name is the DNS name of the load balancer with a wildcard for the name. // example: given "name-1234567890.location.cloudapp.azure.com" it will return "*.location.cloudapp.azure.com" diff --git a/terraform/infrastructure/azure/outputs.tf b/terraform/infrastructure/azure/outputs.tf index 945c793b8..b3e5d844b 100644 --- a/terraform/infrastructure/azure/outputs.tf +++ b/terraform/infrastructure/azure/outputs.tf @@ -47,6 +47,11 @@ output "ip_cidr_node" { description = "CIDR block of the node network." } +output "loadbalancer_address" { + value = azurerm_public_ip.loadbalancer_ip[0].fqdn + description = "Public loadbalancer address." +} + # Azure-specific outputs output "attestation_url" { diff --git a/terraform/infrastructure/azure/variables.tf b/terraform/infrastructure/azure/variables.tf index a3ab1fd0b..64a02a35d 100644 --- a/terraform/infrastructure/azure/variables.tf +++ b/terraform/infrastructure/azure/variables.tf @@ -101,3 +101,9 @@ variable "additional_tags" { default = {} description = "Additional tags that should be applied to created resources." } + +variable "emergency_ssh" { + type = bool + default = false + description = "Wether to expose the SSH port through the public load balancer." +} diff --git a/terraform/infrastructure/gcp/main.tf b/terraform/infrastructure/gcp/main.tf index cd66002d9..f3af09a5a 100644 --- a/terraform/infrastructure/gcp/main.tf +++ b/terraform/infrastructure/gcp/main.tf @@ -40,6 +40,7 @@ locals { { name = "recovery", port = "9999", health_check = "TCP" }, { name = "join", port = "30090", health_check = "TCP" }, var.debug ? [{ name = "debugd", port = "4000", health_check = "TCP" }] : [], + var.emergency_ssh ? [{ name = "ssh", port = "22", health_check = "TCP" }] : [], ]) node_groups_by_role = { for name, node_group in var.node_groups : node_group.role => name... diff --git a/terraform/infrastructure/gcp/outputs.tf b/terraform/infrastructure/gcp/outputs.tf index cbdf9164a..8525bdb13 100644 --- a/terraform/infrastructure/gcp/outputs.tf +++ b/terraform/infrastructure/gcp/outputs.tf @@ -45,6 +45,11 @@ output "ip_cidr_node" { description = "CIDR block of the node network." } +output "loadbalancer_address" { + value = var.internal_load_balancer ? google_compute_address.loadbalancer_ip_internal[0].address : google_compute_global_address.loadbalancer_ip[0].address + description = "Public loadbalancer address." +} + # GCP-specific outputs output "project" { diff --git a/terraform/infrastructure/gcp/variables.tf b/terraform/infrastructure/gcp/variables.tf index 601394a55..b62b975db 100644 --- a/terraform/infrastructure/gcp/variables.tf +++ b/terraform/infrastructure/gcp/variables.tf @@ -75,3 +75,9 @@ variable "additional_labels" { default = {} description = "Additional labels that should be given to created recources." } + +variable "emergency_ssh" { + type = bool + default = false + description = "Wether to expose the SSH port through the public load balancer." +} diff --git a/terraform/infrastructure/openstack/main.tf b/terraform/infrastructure/openstack/main.tf index 9a56bfdda..442866d4c 100644 --- a/terraform/infrastructure/openstack/main.tf +++ b/terraform/infrastructure/openstack/main.tf @@ -43,6 +43,7 @@ locals { { name = "recovery", port = "9999", health_check = "TCP" }, { name = "join", port = "30090", health_check = "TCP" }, var.debug ? [{ name = "debugd", port = "4000", health_check = "TCP" }] : [], + var.emergency_ssh ? [{ name = "ssh", port = "22", health_check = "TCP" }] : [], ]) cidr_vpc_subnet_nodes = "192.168.178.0/24" cidr_vpc_subnet_lbs = "192.168.177.0/24" diff --git a/terraform/infrastructure/openstack/outputs.tf b/terraform/infrastructure/openstack/outputs.tf index be45ec065..810b11977 100644 --- a/terraform/infrastructure/openstack/outputs.tf +++ b/terraform/infrastructure/openstack/outputs.tf @@ -36,6 +36,11 @@ output "ip_cidr_node" { description = "CIDR block of the node network." } +output "loadbalancer_address" { + value = openstack_networking_floatingip_v2.public_ip.address + description = "Public loadbalancer address." +} + # OpenStack-specific outputs output "network_id" { diff --git a/terraform/infrastructure/openstack/variables.tf b/terraform/infrastructure/openstack/variables.tf index 12242f08b..3afa8c97a 100644 --- a/terraform/infrastructure/openstack/variables.tf +++ b/terraform/infrastructure/openstack/variables.tf @@ -71,3 +71,9 @@ variable "stackit_project_id" { type = string description = "STACKIT project ID." } + +variable "emergency_ssh" { + type = bool + default = false + description = "Wether to expose the SSH port through the public load balancer." +}