sealed-secrets
sealed-secrets copied to clipboard
When sealing multiple secrets in singe yaml file only first is sealed
Steps to reproduce
10:27:56 in ~/Downloads/kubeseal-test
➜ kubectl create secret generic mysecret --dry-run --from-literal=foo=bar -o yaml >mysecret.yaml
10:28:13 in ~/Downloads/kubeseal-test
➜ cat mysecret.yaml
apiVersion: v1
data:
foo: YmFy
kind: Secret
metadata:
creationTimestamp: null
name: mysecret
10:28:14 in ~/Downloads/kubeseal-test
➜ echo "---" >> mysecret.yaml
10:28:34 in ~/Downloads/kubeseal-test
➜ kubectl create secret generic mysecret2 --dry-run --from-literal=foo2=bar2 -o yaml >>mysecret.yaml
10:28:56 in ~/Downloads/kubeseal-test
➜ cat mysecret.yaml
apiVersion: v1
data:
foo: YmFy
kind: Secret
metadata:
creationTimestamp: null
name: mysecret
---
apiVersion: v1
data:
foo2: YmFyMg==
kind: Secret
metadata:
creationTimestamp: null
name: mysecret2
10:28:59 in ~/Downloads/kubeseal-test
➜ kubeseal --format yaml <mysecret.yaml >mysealedsecret.yaml
10:29:36 in ~/Downloads/kubeseal-test
➜ cat mysealedsecret.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: mysecret
namespace: default
spec:
encryptedData:
foo: AgBcOSwLF/cCWmAR7J3mZvFBJIYq7QIjBUQbymqHAhhUDwqpukiCRnA3Rr9iTOXUDOQLthjoujU9NLIM/5xpSFy2AjFRexA02B4ZoxqDFD2ZNxh1kFzedKEDRYgt855jaCwZZbqCnJc4Q4I9m0fWioj9+Ij3rFouVlu+QATpqyAZ7baiVa3wYp6s9YnDSsGwS0OI2URfB5wxZyEIF/vmw/TuZe6dN/qgPVQOK3wWN1+/j9dMYFPgUbTi9gcYr7SerYFCwi5dergNLagEb/zovMhQXymvvhFTeqk4AOZXXSpVbUNIIpdatLWntIXa1k7xNWIl+O1y0KHmLEmW8Ynv2GHbl0c04suJTAapMmWcVorlN1eRjmPaXogtPDTrbDMzs4SqFM6KAxhairwpjZEX8A7dIfWohGVb01aD4wjdzWd0Jgi5WL6LyCkhvV7YUGDfoJsV8Av1WF1snRJRh2ChoTGbHre2i6eZXAUUDDsLLnVRvEioCFMsKVe+pkXHwZhDhVrCmdswUB4mvNDolpEDZ/pj0ykz9M6WMTErs9VlNB1OHvWBr/B6AIDU/HTomJ4zd9siMhwN+zksLz88pfF8kcKlC/nHd+3xtsPsL8jZbppp8Bw1DwXu19FGOwpwDyGoFxkeB3OH5ECK9yuhHGdecoPoDLDco4An+NOgLI52Qp9fscTuezA4aw9AH7L71XQzqd6BB9A=
you can see only mysecret
and mysecret2
is truncated
Thanks for the report. Yep, the input is assumed to only be a single document, not a full YAML stream atm. We can change that, but obviously that would only work for -o yaml
(not json), which unfortunately breaks the symmetry beween these options :(
Related: I think we should completely rethink kubeseal
to work on individual key values rather than entire Secrets, now that we've changed the SealedSecrets schema. So we might end up obsoleting this particular issue rather than fixing it directly...
@anguslees yes! that would solve another issue we have. We want to allow developers to exchange encrypted credentials so other side get sealed credentials and all they have to do is deploy them to k8s with sealed-secrets setup. Unfortunately currently encrypting side has to know into which namespace it will be deployed as namespace is part of encryption algorithm. So definitely 👍
Also it would be great to have simple go api to allow integrate sealed-secrets into other tools like helm without need to use whole kubeseal binary and bash magic.
Is there any public roadmap?
Thanks!
What if we use the {"apiVersion": "v1", "kind": "List", "items": [...]}
to render to and from json?
FTR, per-item encryption has been implemented in v0.7.0
Unfortunately currently encrypting side has to know into which namespace it will be deployed as namespace is part of encryption algorithm.
This is by design in order to allow you to enforce strict namespace isolation with RBAC rules.
For your use case to work you need to explicitly pass the sealedsecrets.bitnami.com/cluster-wide: "true"
annotation, see v0.6.0 release notes
It looks like just outputting multiple json objects back-to-back also works: https://github.com/kubernetes/kubernetes/issues/8362
So you can have:
{
"apiVersion": "v1",
...
}
{
"apiVersion": "v1",
...
}
I also want it for yaml since it is pretty common to store multiple secrets in one file.
Outputting multiple json objects doesn't seem to work anymore, getting the following error:
error: couldn't get version/kind; json parse error: invalid character '{' after top-level value
With:
$ kubeseal --version
kubeseal version: v0.12.1+dirty
$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", BuildDate:"2020-04-16T11:56:40Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Example:
apiVersion: v1
kind: Secret
metadata:
name: firstsecret
namespace: randomns
type: Opaque
stringData:
SECRET: EXAMPLE
---
apiVersion: v1
kind: Secret
metadata:
name: secondsecret
namespace: randomns
type: Opaque
stringData:
SECRET2: EXAMPLE
kubectl create -f example.yaml --dry-run=client -o json | kubeseal --cert ../workload-secrets.pem -o yaml
A v1/List will work
Different error, but still an error:
error: converting (v1.List) to (v1.Secret): ObjectMeta not present in src
$ <example.yaml kubeseal --cert workload-secrets.pem -o yaml
example.yaml:
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Secret
metadata:
name: firstsecret
namespace: randomns
type: Opaque
stringData:
SECRET: EXAMPLE
- apiVersion: v1
kind: Secret
metadata:
name: secondsecret
namespace: randomns
type: Opaque
stringData:
SECRET2: EXAMPLE
Guessing it might have to do with the usage of stringData
I meant, it "will" work once implemented
It should be easy to implement hence the "good first issue" label. I like small self-contained PRs to review :-)
@voor I meant kubectl
accepts multiple json without a list being needed, not kubeseal
supporting multiple secrets would be very useful, that way kustomize could be used to create the secrets.
kubectl create --dry-run=client -k . | kubeseal ...
once implementing this, let's make sure it works also on --validate
(see #474)
I'm using kustomize
to generate secrets to send in to the kubeseal
command. Does anyone have any bash script workarounds to iterate over each secret in a multiyaml output to send to kubeseal
yet?
I'm very much an amateur at bash scripting so creating a loop that iterates over each secret in a single file (split by ---
??) has been quite difficult for me.
For example, here's my yaml
:
data:
firebase-dev-credentials.json: |
MY_BASE_64_CREDENTIALS
kind: Secret
metadata:
name: nodejs-firebase-credentials-989t6dg7m2
type: Opaque
---
apiVersion: v1
data:
AGENDA_DATABASE_URL: |
MY_BASE_64_URL
kind: Secret
metadata:
name: nodejs-secrets-c229fkh579
type: Opaque
Running kubectl kustomize .
will output the above text to the shell. How can I loop over each yaml using a bash script to pipe to kubeseal
in the mean time? Would love any guidance!
Here is a python script looping on multiple yamls and passing them to kubeseal
#!/bin/python3
import subprocess
import sys
kubeseal = "kubeseal -o yaml".split()
secrets = sys.stdin.read()
for secret in secrets.split("\n---\n"):
process = subprocess.Popen(kubeseal, stdin=subprocess.PIPE)
process.stdin.write(secret.encode())
process.communicate()
if process.returncode == 0:
print("---")
Save it in seal.py
then chmod u+x seal.py
, and you should be able to seal multiple secrets generated with kubectl kustomize . | ./seal.py
Although love python just like everyone else, let me chime in with some underrated good ol' shell scripting with awk
:
awk 'BEGIN {SR=0} /^-+$/{SR++} !/^-+$/{out=SR ".yaml"; print > out}' multi.yaml
for i in [0-9]*.yaml; do
kubeseal -f $i -w sealed-$i
done
(it correctly deals with a multidoc yaml file that begins with ---
by just starting the numbering from 1 instead of 0)
Example:
$ cat multi.yaml
---
apiVersion: v1
data:
foo: YmFy
kind: Secret
metadata:
creationTimestamp: null
name: mysecret
---
apiVersion: v1
data:
foo: YmF6
kind: Secret
metadata:
creationTimestamp: null
name: mysecret2
---
apiVersion: v1
data:
foo: cXV4
kind: Secret
metadata:
creationTimestamp: null
name: mysecret3
$ awk 'BEGIN {SR=1} /^-+$/{SR++} !/^-+$/{out=SR ".yaml"; print > out}' multi.yaml
$ ls
1.yaml 2.yaml 3.yaml
$ for i in [0-9]*.yaml; do kubeseal -f $i -w sealed-$i; done
$ ls
1.yaml 2.yaml 3.yaml
sealed-1.yaml sealed-2.yaml sealed-3.yaml
It would be really great to get this feature in the product. I think many people use multi-document yamls in order to organize their resources. Going off @bchabanne-cochl, I wrote a python script which loops through the multi-document yaml and outputsindividual .json seals with names SEALED-
#!/bin/python3
import sys
import yaml
import subprocess
nargs = len(sys.argv)
filename = sys.argv[1]
with open(filename) as file:
docs = yaml.load_all(file, Loader=yaml.SafeLoader)
for doc in docs:
with open("SEALED-" + doc["metadata"]["name"] + ".json", "w") as outFile:
process = subprocess.Popen(
"kubeseal", stdin=subprocess.PIPE, stdout=outFile)
process.stdin.write(
yaml.dump(doc, default_flow_style=False).encode())
process.communicate()
any update on having multiple sealed secret in single values template like I have to connect to different DB's and I need to create 2 sealed secret one for oracle and other for Postgres. But I can deploy 2 apps using single templates ? is this possible ? if yes can you please provide me some insight?
To aid with splitting the secrets files, GNU Coreutils has a csplit
command for context-sensitive file splitting:
$ csplit -z -s multistream-secrets.yaml -f secret- -b %02d.yaml '/^---$/' '{*}'
$ ls -1 secret-*.yaml
secret-00.yaml
secret-01.yaml
secret-02.yaml