dumpSecretKeyRefToFile dumps a certain secret to a file inside a temporary folder using 0600 as permission bits. This function overlaps with the Kubernetes ability to mount a secret in a pod, with the difference that we can change the attached secret without restarting the pod. We also need to have
( ctx context.Context, client ctrl.Client, namespace string, serverName string, selector *corev1.SecretKeySelector, )
| 128 | // with the difference that we can change the attached secret without restarting the pod. |
| 129 | // We also need to have more control over when the secret content is updated. |
| 130 | func dumpSecretKeyRefToFile( |
| 131 | ctx context.Context, client ctrl.Client, |
| 132 | namespace string, serverName string, selector *corev1.SecretKeySelector, |
| 133 | ) (string, error) { |
| 134 | var secret corev1.Secret |
| 135 | |
| 136 | err := client.Get(ctx, ctrl.ObjectKey{Namespace: namespace, Name: selector.Name}, &secret) |
| 137 | if err != nil { |
| 138 | return "", err |
| 139 | } |
| 140 | |
| 141 | value, ok := secret.Data[selector.Key] |
| 142 | if !ok { |
| 143 | return "", fmt.Errorf("missing key %v in secret %v", selector.Key, selector.Name) |
| 144 | } |
| 145 | |
| 146 | filePath := getSecretKeyRefFileName(serverName, selector) |
| 147 | if err := os.MkdirAll(filepath.Dir(filePath), 0o700); err != nil { |
| 148 | return "", err |
| 149 | } |
| 150 | |
| 151 | // Write atomically: this file is reused across reconciliations and read |
| 152 | // concurrently by libpq, so an in-place rewrite could expose a partial file |
| 153 | // or leave stale bytes behind when the secret rotates to shorter content. |
| 154 | if _, err := fileutils.WriteFileAtomic(filePath, value, 0o600); err != nil { |
| 155 | return "", err |
| 156 | } |
| 157 | |
| 158 | return filePath, nil |
| 159 | } |
| 160 | |
| 161 | // getPgPassFilePath gets the path where the pgpass file will be stored. |
| 162 | func getPgPassFilePath(serverName string) string { |
no test coverage detected