security: use Vault injection for remote worker credentials

This commit is contained in:
Brad Stein 2026-04-05 11:30:45 -03:00
parent 40618a90e8
commit b42cf9564f

View File

@ -12,7 +12,13 @@ import (
"metis/pkg/inventory" "metis/pkg/inventory"
) )
const hostTmpDevicePath = "hosttmp:///tmp" const (
hostTmpDevicePath = "hosttmp:///tmp"
vaultRoleMaintenance = "maintenance"
vaultRuntimeSecretPath = "kv/data/atlas/maintenance/metis-runtime"
vaultHarborSecretPath = "kv/data/atlas/harbor/harbor-core"
vaultSSHKeysSecretPath = "kv/data/atlas/maintenance/metis-ssh-keys"
)
func (a *App) ListDevices(host string) ([]Device, error) { func (a *App) ListDevices(host string) ([]Device, error) {
return a.cachedDevices(host) return a.cachedDevices(host)
@ -450,6 +456,7 @@ func (a *App) remoteBuildPodSpec(name, host, image, node, artifactRef, buildTag
"name": name, "name": name,
"namespace": a.settings.Namespace, "namespace": a.settings.Namespace,
"labels": map[string]string{"app": "metis-remote", "metis-run": "build"}, "labels": map[string]string{"app": "metis-remote", "metis-run": "build"},
"annotations": vaultRuntimeAnnotations(true),
}, },
"spec": map[string]any{ "spec": map[string]any{
"restartPolicy": "Never", "restartPolicy": "Never",
@ -462,8 +469,11 @@ func (a *App) remoteBuildPodSpec(name, host, image, node, artifactRef, buildTag
"name": "remote-build", "name": "remote-build",
"image": image, "image": image,
"imagePullPolicy": "Always", "imagePullPolicy": "Always",
"command": []string{ "command": []string{"/bin/sh", "-c"},
"metis", "remote-build", "args": []string{
remoteWorkerEntrypoint(
true,
"remote-build",
"--inventory", a.settings.InventoryPath, "--inventory", a.settings.InventoryPath,
"--node", node, "--node", node,
"--cache", "/workspace/cache", "--cache", "/workspace/cache",
@ -471,13 +481,10 @@ func (a *App) remoteBuildPodSpec(name, host, image, node, artifactRef, buildTag
"--artifact-ref", artifactRef, "--artifact-ref", artifactRef,
"--build-tag", buildTag, "--build-tag", buildTag,
"--harbor-registry", a.settings.HarborRegistry, "--harbor-registry", a.settings.HarborRegistry,
),
}, },
"envFrom": []map[string]any{ "envFrom": []map[string]any{
{"configMapRef": map[string]any{"name": "metis"}}, {"configMapRef": map[string]any{"name": "metis"}},
{"secretRef": map[string]any{"name": "metis-harbor"}},
},
"env": []map[string]any{
{"name": "METIS_K3S_TOKEN", "valueFrom": map[string]any{"secretKeyRef": map[string]any{"name": "metis-runtime", "key": "k3s_token", "optional": true}}},
}, },
"volumeMounts": []map[string]any{ "volumeMounts": []map[string]any{
{"name": "workspace", "mountPath": "/workspace"}, {"name": "workspace", "mountPath": "/workspace"},
@ -500,6 +507,7 @@ func (a *App) remoteFlashPodSpec(name, host, image, node, device, artifactRef st
"name": name, "name": name,
"namespace": a.settings.Namespace, "namespace": a.settings.Namespace,
"labels": map[string]string{"app": "metis-remote", "metis-run": "flash"}, "labels": map[string]string{"app": "metis-remote", "metis-run": "flash"},
"annotations": vaultRuntimeAnnotations(false),
}, },
"spec": map[string]any{ "spec": map[string]any{
"restartPolicy": "Never", "restartPolicy": "Never",
@ -512,19 +520,22 @@ func (a *App) remoteFlashPodSpec(name, host, image, node, device, artifactRef st
"name": "remote-flash", "name": "remote-flash",
"image": image, "image": image,
"imagePullPolicy": "Always", "imagePullPolicy": "Always",
"command": []string{ "command": []string{"/bin/sh", "-c"},
"metis", "remote-flash", "args": []string{
remoteWorkerEntrypoint(
false,
"remote-flash",
"--node", node, "--node", node,
"--device", device, "--device", device,
"--artifact-ref", artifactRef, "--artifact-ref", artifactRef,
"--work-dir", "/workspace/flash", "--work-dir", "/workspace/flash",
"--harbor-registry", a.settings.HarborRegistry, "--harbor-registry", a.settings.HarborRegistry,
"--host-tmp-dir", mountedHostTmpDir(a.settings.HostTmpDir), "--host-tmp-dir", mountedHostTmpDir(a.settings.HostTmpDir),
),
}, },
"securityContext": map[string]any{"privileged": true, "runAsUser": 0}, "securityContext": map[string]any{"privileged": true, "runAsUser": 0},
"envFrom": []map[string]any{ "envFrom": []map[string]any{
{"configMapRef": map[string]any{"name": "metis"}}, {"configMapRef": map[string]any{"name": "metis"}},
{"secretRef": map[string]any{"name": "metis-harbor"}},
}, },
"volumeMounts": []map[string]any{ "volumeMounts": []map[string]any{
{"name": "workspace", "mountPath": "/workspace"}, {"name": "workspace", "mountPath": "/workspace"},
@ -572,3 +583,56 @@ func mountedHostTmpDir(path string) string {
return filepath.Join("/host-tmp", strings.TrimPrefix(path, "/")) return filepath.Join("/host-tmp", strings.TrimPrefix(path, "/"))
} }
} }
func vaultRuntimeAnnotations(includeSSHKeys bool) map[string]string {
annotations := map[string]string{
"vault.hashicorp.com/agent-inject": "true",
"vault.hashicorp.com/agent-pre-populate-only": "true",
"vault.hashicorp.com/role": vaultRoleMaintenance,
"vault.hashicorp.com/agent-inject-secret-metis-runtime-env.sh": vaultRuntimeSecretPath,
"vault.hashicorp.com/agent-inject-template-metis-runtime-env.sh": `{{ with secret "kv/data/atlas/maintenance/metis-runtime" }}
export METIS_K3S_TOKEN="{{ .Data.data.k3s_token }}"
{{ end }}`,
"vault.hashicorp.com/agent-inject-secret-metis-harbor-env.sh": vaultHarborSecretPath,
"vault.hashicorp.com/agent-inject-template-metis-harbor-env.sh": `{{ with secret "kv/data/atlas/harbor/harbor-core" }}
export METIS_HARBOR_PASSWORD="{{ .Data.data.harbor_admin_password }}"
{{ end }}`,
}
if includeSSHKeys {
annotations["vault.hashicorp.com/agent-inject-secret-metis-ssh-env.sh"] = vaultSSHKeysSecretPath
annotations["vault.hashicorp.com/agent-inject-template-metis-ssh-env.sh"] = `{{ with secret "kv/data/atlas/maintenance/metis-ssh-keys" }}
export METIS_SSH_KEY_BASTION="{{ .Data.data.bastion_pub }}"
export METIS_SSH_KEY_BRAD="{{ .Data.data.brad_pub }}"
export METIS_SSH_KEY_HECATE_TETHYS="{{ .Data.data.hecate_tethys_pub }}"
{{ end }}`
}
return annotations
}
func remoteWorkerEntrypoint(includeSSHKeys bool, args ...string) string {
lines := []string{
"set -e",
". /vault/secrets/metis-runtime-env.sh",
". /vault/secrets/metis-harbor-env.sh",
}
if includeSSHKeys {
lines = append(lines, ". /vault/secrets/metis-ssh-env.sh")
}
lines = append(lines, "exec "+shellJoin(append([]string{"metis"}, args...)...))
return strings.Join(lines, "\n")
}
func shellJoin(args ...string) string {
quoted := make([]string, 0, len(args))
for _, arg := range args {
quoted = append(quoted, shellQuote(arg))
}
return strings.Join(quoted, " ")
}
func shellQuote(value string) string {
if value == "" {
return "''"
}
return "'" + strings.ReplaceAll(value, "'", `'"'"'`) + "'"
}