feat: implement RFC 16 to allow emergency node access (#3557)

This commit is contained in:
miampf 2025-03-25 11:28:48 +00:00 committed by GitHub
parent c7369fa2a7
commit 3cc930fa97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 256 additions and 69 deletions

View File

@ -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 <<EOF
Host $lb
ProxyJump none
Host *
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null
IdentityFile ./access-key
PreferredAuthentications publickey
CertificateFile=constellation_cert.pub
User root
ProxyJump $lb
EOF
for i in {1..26}; do
if [[ "$i" -eq 26 ]]; then
echo "Port 22 never became reachable"
exit 1
fi
echo "Waiting until port 22 is reachable: $i/25"
if nc -z -w 25 "$lb" 22; then
break
fi
done
# generate and try keypair
ssh-keygen -t ecdsa -q -N "" -f ./access-key
constellation ssh --debug --key ./access-key.pub
internalIPs="$(kubectl get nodes -o=jsonpath='{.items[*].status.addresses}' | jq -r '.[] | select(.type == "InternalIP") | .address')"
for ip in $internalIPs; do
for i in {1..26}; do
if [[ "$i" -eq 26 ]]; then
echo "Failed to connect to $ip over $lb"
exit 1
fi
echo "Trying connection to $ip over $lb: $i/25"
if ssh -F ssh_config -o BatchMode=yes $ip true; then
echo "Connected to $ip successfully"
break
fi
done
done

View File

@ -56,7 +56,7 @@ inputs:
description: "Azure credentials authorized to create an IAM configuration."
required: true
test:
description: "The test to run. Can currently be one of [sonobuoy full, sonobuoy quick, sonobuoy conformance, autoscaling, lb, perf-bench, verify, recover, malicious join, nop, upgrade]."
description: "The test to run. Can currently be one of [sonobuoy full, sonobuoy quick, sonobuoy conformance, autoscaling, lb, perf-bench, verify, recover, malicious join, nop, upgrade, emergency ssh]."
required: true
sonobuoyTestSuiteCmd:
description: "The sonobuoy test suite to run."
@ -115,7 +115,7 @@ runs:
using: "composite"
steps:
- name: Check input
if: (!contains(fromJson('["sonobuoy full", "sonobuoy quick", "sonobuoy conformance", "autoscaling", "perf-bench", "verify", "lb", "recover", "malicious join", "s3proxy", "nop", "upgrade"]'), inputs.test))
if: (!contains(fromJson('["sonobuoy full", "sonobuoy quick", "sonobuoy conformance", "autoscaling", "perf-bench", "verify", "lb", "recover", "malicious join", "s3proxy", "nop", "upgrade", "emergency ssh"]'), inputs.test))
shell: bash
run: |
echo "::error::Invalid input for test field: ${{ inputs.test }}"
@ -149,6 +149,8 @@ runs:
- name: Setup bazel
uses: ./.github/actions/setup_bazel_nix
with:
nixTools: terraform
- name: Log in to the Container registry
uses: ./.github/actions/container_registry_login
@ -444,3 +446,9 @@ runs:
s3AccessKey: ${{ inputs.s3AccessKey }}
s3SecretKey: ${{ inputs.s3SecretKey }}
githubToken: ${{ inputs.githubToken }}
- name: Run emergency ssh test
if: inputs.test == 'emergency ssh'
uses: ./.github/actions/e2e_emergency_ssh
with:
kubeconfig: ${{ steps.constellation-create.outputs.kubeconfig }}

View File

@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
refStream: ["ref/main/stream/nightly/?","ref/main/stream/debug/?", "ref/release/stream/stable/?"]
refStream: ["ref/main/stream/nightly/?", "ref/main/stream/debug/?", "ref/release/stream/stable/?"]
name: Find latest image
runs-on: ubuntu-24.04
permissions:
@ -51,6 +51,33 @@ jobs:
# Tests on main-debug refStream
#
# Emergency SSH test on latest k8s version
- test: "emergency ssh"
refStream: "ref/main/stream/debug/?"
attestationVariant: "gcp-sev-es"
kubernetes-version: "v1.30"
clusterCreation: "cli"
- test: "emergency ssh"
refStream: "ref/main/stream/debug/?"
attestationVariant: "gcp-sev-snp"
kubernetes-version: "v1.30"
clusterCreation: "cli"
- test: "emergency ssh"
refStream: "ref/main/stream/debug/?"
attestationVariant: "azure-sev-snp"
kubernetes-version: "v1.30"
clusterCreation: "cli"
- test: "emergency ssh"
refStream: "ref/main/stream/debug/?"
attestationVariant: "azure-tdx"
kubernetes-version: "v1.30"
clusterCreation: "cli"
- test: "emergency ssh"
refStream: "ref/main/stream/debug/?"
attestationVariant: "aws-sev-snp"
kubernetes-version: "v1.30"
clusterCreation: "cli"
# Sonobuoy full test on latest k8s version
- test: "sonobuoy full"
refStream: "ref/main/stream/debug/?"
@ -138,7 +165,6 @@ jobs:
kubernetes-version: "v1.29"
clusterCreation: "cli"
# verify test on latest k8s version
- test: "verify"
refStream: "ref/main/stream/debug/?"

View File

@ -40,6 +40,7 @@ on:
- "recover"
- "malicious join"
- "s3proxy"
- "emergency ssh"
- "nop"
required: true
kubernetesVersion:

View File

@ -10,7 +10,6 @@ import (
"crypto/ed25519"
"crypto/rand"
"fmt"
"os"
"time"
"github.com/edgelesssys/constellation/v2/internal/constants"
@ -28,12 +27,12 @@ import (
func NewSSHCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "ssh",
Short: "Prepare your cluster for emergency ssh access",
Long: "Prepare your cluster for emergency ssh access and sign a given key pair for authorization.",
Short: "Generate a certificate for emergency SSH access",
Long: "Generate a certificate for emergency SSH access to your SSH-enabled constellation cluster.",
Args: cobra.ExactArgs(0),
RunE: runSSH,
}
cmd.Flags().String("key", "", "the path to an existing ssh public key")
cmd.Flags().String("key", "", "the path to an existing SSH public key")
must(cmd.MarkFlagRequired("key"))
return cmd
}
@ -54,18 +53,10 @@ func runSSH(cmd *cobra.Command, _ []string) error {
}
func writeCertificateForKey(cmd *cobra.Command, keyPath string, fh file.Handler, debugLogger debugLog) error {
_, err := fh.Stat(constants.TerraformWorkingDir)
if os.IsNotExist(err) {
return fmt.Errorf("directory %q does not exist", constants.TerraformWorkingDir)
}
if err != nil {
return err
}
// NOTE(miampf): Since other KMS aren't fully implemented yet, this commands assumes that the cKMS is used and derives the key accordingly.
var mastersecret uri.MasterSecret
if err = fh.ReadJSON(constants.MasterSecretFilename, &mastersecret); err != nil {
return fmt.Errorf("reading master secret: %s", err)
if err := fh.ReadJSON(constants.MasterSecretFilename, &mastersecret); err != nil {
return fmt.Errorf("reading master secret (does %q exist?): %w", constants.MasterSecretFilename, err)
}
mastersecretURI := uri.MasterSecret{Key: mastersecret.Key, Salt: mastersecret.Salt}
@ -80,7 +71,7 @@ func writeCertificateForKey(cmd *cobra.Command, keyPath string, fh file.Handler,
ca, err := crypto.GenerateEmergencySSHCAKey(sshCAKeySeed)
if err != nil {
return fmt.Errorf("generating ssh emergency CA key: %s", err)
return fmt.Errorf("generating SSH emergency CA key: %s", err)
}
debugLogger.Debug("SSH CA KEY generated", "public-key", string(ssh.MarshalAuthorizedKey(ca.PublicKey())))
@ -103,8 +94,8 @@ func writeCertificateForKey(cmd *cobra.Command, keyPath string, fh file.Handler,
ValidPrincipals: []string{"root"},
Permissions: ssh.Permissions{
Extensions: map[string]string{
"permit-port-forwarding": "yes",
"permit-pty": "yes",
"permit-port-forwarding": "",
"permit-pty": "",
},
},
}
@ -113,10 +104,10 @@ func writeCertificateForKey(cmd *cobra.Command, keyPath string, fh file.Handler,
}
debugLogger.Debug("Signed certificate", "certificate", string(ssh.MarshalAuthorizedKey(&certificate)))
if err := fh.Write(fmt.Sprintf("%s/ca_cert.pub", constants.TerraformWorkingDir), ssh.MarshalAuthorizedKey(&certificate), file.OptOverwrite); err != nil {
if err := fh.Write("constellation_cert.pub", ssh.MarshalAuthorizedKey(&certificate), file.OptOverwrite); err != nil {
return fmt.Errorf("writing certificate: %s", err)
}
cmd.Printf("You can now connect to a node using 'ssh -F %s/ssh_config -i <your private key> <node ip>'.\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
}

View File

@ -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)

View File

@ -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

View File

@ -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 <your private key> root@<ip of constellation node>
```
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 <LB domain name>
ProxyJump none
Host *
IdentityFile <your private key>
PreferredAuthentications publickey
CertificateFile=constellation_cert.pub
User root
ProxyJump <LB domain name>
```
With this configuration you can connect to a Constellation node using `ssh -F <this config> <private node IP>`.
You can obtain the private node IP and the domain name of the load balancer using your CSP's web UI.

View File

@ -41,6 +41,7 @@ Packages=containerd
# Network
Packages=iproute
dbus
openssh-server
systemd-networkd
systemd-resolved

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -19,6 +19,7 @@ mokutil
nano
nano-default-editor
nvme-cli
openssh-server
passt-selinux
passwd
podman

View File

@ -0,0 +1,4 @@
HostKey /run/ssh/ssh_host_ecdsa_key
TrustedUserCAKeys /run/ssh/ssh_ca.pub
PasswordAuthentication no
ChallengeResponseAuthentication no

View File

@ -1,7 +1,3 @@
---
status: approved, not implemented
---
# RFC 016: Node Access
## Background

View File

@ -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 : [

View File

@ -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."
}

View File

@ -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."
}

View File

@ -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"

View File

@ -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" {

View File

@ -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."
}

View File

@ -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...

View File

@ -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" {

View File

@ -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."
}

View File

@ -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"

View File

@ -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" {

View File

@ -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."
}