From d6dd17fdfe063cbf6509b647c657db9272a62744 Mon Sep 17 00:00:00 2001
From: Ygal Blum <ygal.blum@gmail.com>
Date: Wed, 8 Feb 2023 12:19:10 +0200
Subject: [PATCH] Quadlet: Add support for the Secret key in Container group

Add E2E tests
Add system test
Add to man page

Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
---
 docs/source/markdown/podman-systemd.unit.5.md |  5 ++
 pkg/systemd/quadlet/quadlet.go                |  7 ++
 test/e2e/quadlet/secrets.container            |  9 +++
 test/e2e/quadlet_test.go                      |  1 +
 test/system/252-quadlet.bats                  | 70 +++++++++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 test/e2e/quadlet/secrets.container

diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md
index df75e75585..3f19f88b76 100644
--- a/docs/source/markdown/podman-systemd.unit.5.md
+++ b/docs/source/markdown/podman-systemd.unit.5.md
@@ -301,6 +301,11 @@ Set the label process level for the container processes.
 
 Set the label process type for the container processes.
 
+#### `Secret=`
+
+Use a Podman secret in the container either as a file or an environment variable.
+This is equivalent to the Podman `--secret` option and generally has the form `secret[,opt=opt ...]`
+
 #### `Timezone=` (if unset uses system-configured default)
 
 The timezone to run the container in.
diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go
index 0fb6f47575..167d8676b0 100644
--- a/pkg/systemd/quadlet/quadlet.go
+++ b/pkg/systemd/quadlet/quadlet.go
@@ -74,6 +74,7 @@ const (
 	KeySecurityLabelFileType = "SecurityLabelFileType"
 	KeySecurityLabelLevel    = "SecurityLabelLevel"
 	KeySecurityLabelType     = "SecurityLabelType"
+	KeySecret                = "Secret"
 	KeyTimezone              = "Timezone"
 	KeyType                  = "Type"
 	KeyUser                  = "User"
@@ -117,6 +118,7 @@ var (
 		KeySecurityLabelFileType: true,
 		KeySecurityLabelLevel:    true,
 		KeySecurityLabelType:     true,
+		KeySecret:                true,
 		KeyTimezone:              true,
 		KeyUser:                  true,
 		KeyVolatileTmp:           true,
@@ -518,6 +520,11 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
 		podman.addBool("--env-host", envHost)
 	}
 
+	secrets := container.LookupAllArgs(ContainerGroup, KeySecret)
+	for _, secret := range secrets {
+		podman.add("--secret", secret)
+	}
+
 	podmanArgs := container.LookupAllArgs(ContainerGroup, KeyPodmanArgs)
 	podman.add(podmanArgs...)
 
diff --git a/test/e2e/quadlet/secrets.container b/test/e2e/quadlet/secrets.container
new file mode 100644
index 0000000000..b1e61f996f
--- /dev/null
+++ b/test/e2e/quadlet/secrets.container
@@ -0,0 +1,9 @@
+## assert-podman-args "--secret" "mysecret"
+## assert-podman-args "--secret" "source=mysecret,type=env,target=MYSECRET"
+## assert-podman-args "--secret" "source=mysecret,type=mount,uid=1000,gid=1001,mode=777"
+
+[Container]
+Image=localhost/imagename
+Secret=mysecret
+Secret=source=mysecret,type=env,target=MYSECRET
+Secret=source=mysecret,type=mount,uid=1000,gid=1001,mode=777
diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go
index 5c323ad543..257f746fe6 100644
--- a/test/e2e/quadlet_test.go
+++ b/test/e2e/quadlet_test.go
@@ -481,6 +481,7 @@ var _ = Describe("quadlet system generator", func() {
 		Entry("env-file.container", "env-file.container"),
 		Entry("env-host.container", "env-host.container"),
 		Entry("env-host-false.container", "env-host-false.container"),
+		Entry("secrets.container", "secrets.container"),
 
 		Entry("basic.volume", "basic.volume"),
 		Entry("label.volume", "label.volume"),
diff --git a/test/system/252-quadlet.bats b/test/system/252-quadlet.bats
index a83be32df7..0418f37567 100644
--- a/test/system/252-quadlet.bats
+++ b/test/system/252-quadlet.bats
@@ -114,6 +114,24 @@ function service_cleanup() {
     systemctl daemon-reload
 }
 
+function create_secret() {
+    local secret_name=$(random_string)
+    local secret_file=$PODMAN_TMPDIR/secret_$(random_string)
+    local secret=$(random_string)
+
+    echo $secret > $secret_file
+    run_podman secret create $secret_name $secret_file
+
+    SECRET_NAME=$secret_name
+    SECRET=$secret
+}
+
+function remove_secret() {
+    local secret_name="$1"
+
+    run_podman secret rm $secret_name
+}
+
 @test "quadlet - basic" {
     local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container
     cat > $quadlet_file <<EOF
@@ -477,4 +495,56 @@ EOF
     service_cleanup $QUADLET_SERVICE_NAME failed
 }
 
+@test "quadlet - secret as environment variable" {
+    create_secret
+
+    local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container
+    cat > $quadlet_file <<EOF
+[Container]
+ContainerName=$NAME
+Image=$IMAGE
+Secret=$SECRET_NAME,type=env,target=MYSECRET
+Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; top"
+EOF
+
+    run_quadlet "$quadlet_file"
+    service_setup $QUADLET_SERVICE_NAME
+
+    # Ensure we have output. Output is synced via sd-notify (socat in Exec)
+    run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME"
+    is "$output" '.*STARTED CONTAINER.*'
+
+    run_podman exec $QUADLET_CONTAINER_NAME /bin/sh -c "printenv MYSECRET"
+    is "$output" $SECRET
+
+    service_cleanup $QUADLET_SERVICE_NAME failed
+    remove_secret $SECRET_NAME
+}
+
+@test "quadlet - secret as a file" {
+    create_secret
+
+    local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container
+    cat > $quadlet_file <<EOF
+[Container]
+ContainerName=$NAME
+Image=$IMAGE
+Secret=$SECRET_NAME,type=mount,target=/root/secret
+Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; top"
+EOF
+
+    run_quadlet "$quadlet_file"
+    service_setup $QUADLET_SERVICE_NAME
+
+    # Ensure we have output. Output is synced via sd-notify (socat in Exec)
+    run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME"
+    is "$output" '.*STARTED CONTAINER.*'
+
+    run_podman exec $QUADLET_CONTAINER_NAME /bin/sh -c "cat /root/secret"
+    is "$output" $SECRET
+
+    service_cleanup $QUADLET_SERVICE_NAME failed
+    remove_secret $SECRET_NAME
+}
+
 # vim: filetype=sh