Skip to content

Certs improv#54

Open
esposem wants to merge 1 commit into
confidential-devhub:mainfrom
esposem:certs-improv
Open

Certs improv#54
esposem wants to merge 1 commit into
confidential-devhub:mainfrom
esposem:certs-improv

Conversation

@esposem

@esposem esposem commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

As per issue #51
Plus fix namespace error in generated trustee secret

@esposem

esposem commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@bpradipt this is where I keep getting stuck

[cmd/apply.go](https://github.com/confidential-devhub/cococtl/pull/52/files/c710607ee2124fdcb94c8f5f36580f1140d08cd6#diff-a08f2011636c2b27ac4df1809b3bf95ee8aa9a6de2050807d33ddfb65fb69f6f)
	} else {
		// Skip-apply mode: save certs to file instead of uploading
-		certFilePath, err := saveSidecarCertsToYAML(manifestPath, serverCert, appName, namespace)
+		certFilePath, err := saveSidecarCertsToYAML(manifestPath, serverCert, appName, trusteeNamespace)

This should be namespace only, which is the workload namespace.

Now, you know the use case (OCP) and I am pretty sure trustee doesn't support reading secrets from other namespaces, so I don't understand why this should not be trusteeNamespace...

Suppose an example app.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hello-http-server
  namespace: default
  labels:
    app: hello-server
spec:
  # 1. Init Container: Reads the specific secret key from env before main startup
  initContainers:
  - name: read-secret-init
    image: registry.access.redhat.com/ubi9/ubi:latest
    command:
    - "sh"
    - "-c"
    - "echo '--- INIT: Reading explicit secret key ---'; echo \"The secret is: $MY_SECRET\"; echo '--- INIT: Finished ---'"
    env:
    - name: MY_SECRET
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: secret-value

  # 2. Main Container: Also has access to the explicitly referenced key
  containers:
  - name: http-echo
    image: registry.access.redhat.com/ubi9/ubi:latest
    command:
    - "python3"
    - "-c"
    - |
      import socket

      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      s.bind(('0.0.0.0', 8080))
      s.listen(5)
      while True:
          conn, addr = s.accept()
          request = conn.recv(1024)
          response = b"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 7\r\n\r\nhello!\n"
          conn.sendall(response)
          conn.close()
    ports:
    - containerPort: 8080
      name: http

if I run

cococtl init --enable-sidecar --runtime-class kata-remote --trustee-namespace trustee-operator-system --trustee-url $ROUTE

cococtl apply -f app.yaml --skip-apply --enable-initdata --sidecar --sidecar-port-forward 8080

I get

app-coco.yaml # ns: default, fine. Uses 
     * name: TLS_CERT_URI  
        value: kbs:///default/sidecar-tls-hello-http-server/server-cert 
     * name: MY_SECRET
              valueFrom:
                secretKeyRef:
                    key: secret-value
                    name: my-app-secret-sealed 
app-sealed-secrets.yaml # ns: default, makes sense (accessed by app-coco.yaml)
app-sidecar-certs.yaml  # <--- this is where I have issues. why is the ns default, and not trustee-operator-system? The TLS_CERT_URI points to kbs:///default/sidecar-tls-hello-http-server/server-cert 
app-sidecar-service.yaml  # ns: default, makes sense (used by app-coco.yaml)
app-trustee-secrets.yaml # not needed in my use case 
app.yaml # unchanged

Supposing a pod called hello-http-server is created:

we would have

kind: Secret
metadata:
    name: sidecar-tls-hello-http-server
    namespace: default
type: kubernetes.io/tls
data:
    tls.crt: ...
    tls.key: ...

But in the pod-coco.yaml we have

        - env:
            - name: TLS_CERT_URI
              value: kbs:///default/sidecar-tls-hello-http-server/server-cert
            - name: TLS_KEY_URI
              value: kbs:///default/sidecar-tls-hello-http-server/server-key
            - name: CLIENT_CA_URI
              value: kbs:///default/sidecar-tls/client-ca

this doesn't make sense as applying the secret and adding it into kbs will create /default/sidecar-tls-hello-http/server/tls.crt not /default/.../server-cert.

Fix it with this commit.
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
@bpradipt

bpradipt commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

I'm assuming you are using the trustee-operator kbsSecretResources model where you kubectl apply a K8s Secret, and the operator reads it from its own namespace and republishes it into KBS at kbs:///default/<secret-name>/<key>.

In this model the secret must live in the trustee namespace.

Now, in cococtl the model is direct KBS repository write: handleSidecarServerCert uploads the cert bytes directly into the KBS repo:

 // cmd/apply.go:
 serverCertPath := namespace + "/sidecar-tls-" + appName + "/server-cert"
 resources := map[string][]byte{ serverCertPath: serverCert.CertPEM, ... }
 trustee.UploadResources(ctx, kbsClient, resources)

The path prefix is the workload namespace, and it's a logical KBS repo path. It has nothing to do with which K8s namespace Trustee runs in. Trustee's "can't read secrets from other namespaces" constraint never comes into play, because no K8s Secret is being read at all.

TL;DR: The upload path uses the workload namespace, so the skip-apply file's metadata.namespace must match it (namespace) to stay consistent with the TLS_CERT_URI in app-coco.yaml.

Using trusteeNamespace would make the file disagree with the URI the app is told to fetch from.

In OCP, since the secrets comes from CRD config or vault, we'll have to think of a proper mechanism.

This is in addition to the bug with sidecar secret which is incorrectly emitted as tls.crt/tls.key.

@esposem

esposem commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

makes sense, for now let's focus on this bug fix. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants