security: use Vault injection for remote worker credentials
This commit is contained in:
parent
40618a90e8
commit
b42cf9564f
@ -12,7 +12,13 @@ import (
|
||||
"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) {
|
||||
return a.cachedDevices(host)
|
||||
@ -447,9 +453,10 @@ func (a *App) remoteBuildPodSpec(name, host, image, node, artifactRef, buildTag
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": name,
|
||||
"namespace": a.settings.Namespace,
|
||||
"labels": map[string]string{"app": "metis-remote", "metis-run": "build"},
|
||||
"name": name,
|
||||
"namespace": a.settings.Namespace,
|
||||
"labels": map[string]string{"app": "metis-remote", "metis-run": "build"},
|
||||
"annotations": vaultRuntimeAnnotations(true),
|
||||
},
|
||||
"spec": map[string]any{
|
||||
"restartPolicy": "Never",
|
||||
@ -462,22 +469,22 @@ func (a *App) remoteBuildPodSpec(name, host, image, node, artifactRef, buildTag
|
||||
"name": "remote-build",
|
||||
"image": image,
|
||||
"imagePullPolicy": "Always",
|
||||
"command": []string{
|
||||
"metis", "remote-build",
|
||||
"--inventory", a.settings.InventoryPath,
|
||||
"--node", node,
|
||||
"--cache", "/workspace/cache",
|
||||
"--work-dir", "/workspace/build",
|
||||
"--artifact-ref", artifactRef,
|
||||
"--build-tag", buildTag,
|
||||
"--harbor-registry", a.settings.HarborRegistry,
|
||||
"command": []string{"/bin/sh", "-c"},
|
||||
"args": []string{
|
||||
remoteWorkerEntrypoint(
|
||||
true,
|
||||
"remote-build",
|
||||
"--inventory", a.settings.InventoryPath,
|
||||
"--node", node,
|
||||
"--cache", "/workspace/cache",
|
||||
"--work-dir", "/workspace/build",
|
||||
"--artifact-ref", artifactRef,
|
||||
"--build-tag", buildTag,
|
||||
"--harbor-registry", a.settings.HarborRegistry,
|
||||
),
|
||||
},
|
||||
"envFrom": []map[string]any{
|
||||
{"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{
|
||||
{"name": "workspace", "mountPath": "/workspace"},
|
||||
@ -497,9 +504,10 @@ func (a *App) remoteFlashPodSpec(name, host, image, node, device, artifactRef st
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": name,
|
||||
"namespace": a.settings.Namespace,
|
||||
"labels": map[string]string{"app": "metis-remote", "metis-run": "flash"},
|
||||
"name": name,
|
||||
"namespace": a.settings.Namespace,
|
||||
"labels": map[string]string{"app": "metis-remote", "metis-run": "flash"},
|
||||
"annotations": vaultRuntimeAnnotations(false),
|
||||
},
|
||||
"spec": map[string]any{
|
||||
"restartPolicy": "Never",
|
||||
@ -512,19 +520,22 @@ func (a *App) remoteFlashPodSpec(name, host, image, node, device, artifactRef st
|
||||
"name": "remote-flash",
|
||||
"image": image,
|
||||
"imagePullPolicy": "Always",
|
||||
"command": []string{
|
||||
"metis", "remote-flash",
|
||||
"--node", node,
|
||||
"--device", device,
|
||||
"--artifact-ref", artifactRef,
|
||||
"--work-dir", "/workspace/flash",
|
||||
"--harbor-registry", a.settings.HarborRegistry,
|
||||
"--host-tmp-dir", mountedHostTmpDir(a.settings.HostTmpDir),
|
||||
"command": []string{"/bin/sh", "-c"},
|
||||
"args": []string{
|
||||
remoteWorkerEntrypoint(
|
||||
false,
|
||||
"remote-flash",
|
||||
"--node", node,
|
||||
"--device", device,
|
||||
"--artifact-ref", artifactRef,
|
||||
"--work-dir", "/workspace/flash",
|
||||
"--harbor-registry", a.settings.HarborRegistry,
|
||||
"--host-tmp-dir", mountedHostTmpDir(a.settings.HostTmpDir),
|
||||
),
|
||||
},
|
||||
"securityContext": map[string]any{"privileged": true, "runAsUser": 0},
|
||||
"envFrom": []map[string]any{
|
||||
{"configMapRef": map[string]any{"name": "metis"}},
|
||||
{"secretRef": map[string]any{"name": "metis-harbor"}},
|
||||
},
|
||||
"volumeMounts": []map[string]any{
|
||||
{"name": "workspace", "mountPath": "/workspace"},
|
||||
@ -572,3 +583,56 @@ func mountedHostTmpDir(path string) string {
|
||||
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, "'", `'"'"'`) + "'"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user