func CreateSecret(name string, encryptedData map[string][]byte, unencryptedData map[string]string) error {
var secret *corev1.Secret
if (len(encryptedData) == 0) && (len(unencryptedData) == 0) {
return fmt.Errorf("Secret data cannot be blank")
}
secret = &corev1.Secret{
Type: corev1.SecretTypeOpaque,
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
"heritage": "component-testing",
"app": "super8",
},
},
}
if encryptedData != nil || len(encryptedData) != 0 {
secret.Data = encryptedData
}
if unencryptedData != nil || len(unencryptedData) != 0 {
secret.StringData = unencryptedData
}
secretOut, err := kubeClient.client.CoreV1().Secrets(kubeClient.namespace).Create(secret)
fmt.Println(secretOut.Name)
return err
}
encrypts all the data provided in secret.Data and secret.StringData irrespective of the content
where as the same when created with below method matches creating a secret using kubectl create -f secrets.yaml
func CreateSecretFromJson(b []byte) {
var s corev1.Secret
err := json.Unmarshal(b, &s)
if err != nil {
fmt.Printf("unmarshall error")
}
secret, poderr := kubeClient.client.CoreV1().Secrets(kubeClient.namespace).Create(&s)
if poderr != nil {
fmt.Println(poderr.Error())
} else {
fmt.Printf("Created Secret %q.\n", secret.GetObjectMeta().GetName())
}
}
My data in secret has both base 64 encrypted and unencrypted (which is already an encrypted or binary data)
this is the documented behavior of the stringData field:
// stringData allows specifying non-binary secret data in string form.
// It is provided as a write-only convenience method.
// All keys and values are merged into the data field on write, overwriting any existing values.
// It is never output when reading from the API.
your json.Unmarshal(b, &s) call will load stringData into s, but the API never returns stringData, so the result of kubeClient.client.CoreV1().Secrets(kubeClient.namespace).Create(&s) will only contain data
for example:
$ curl -k https://localhost:6443/api/v1/namespaces/default/secrets \
-X POST -H "Content-Type: application/json" \
--data '{"metadata":{"name":"test"},"data":{"a":"YmFy"},"stringData":{"b":"test"}}'
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "test",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/secrets/test",
"uid": "82ef45ee-4fdd-11e8-87bf-00e092001ba4",
"resourceVersion": "25758",
"creationTimestamp": "2018-05-04T20:55:43Z"
},
"data": {
"a": "YmFy",
"b": "dGVzdA=="
},
"type": "Opaque"
}
also, the values in the data field are not encrypted, they are simply base64-encoded in json form, which decodes to normal strings in the go structs
True. But When I create a pod with reference to Secret created from Json - pod gets created successfully .
When the pod is created with reference to secret created using go-client - pod gets into error status.
With Failed to create secure key unwrapping key -80003
With Go-client I would expect that Data field will not be base64 encoded again - now it does.
StringData should be base64 encoded by api - this is happening
Can you describe your setup more completely, and include API request/response after creating the secret each way (with replacement data so you don't disclose any data you care about protecting)
Using the same sample in your comment.
$ curl -k https://localhost:6443/api/v1/namespaces/default/secrets \
-X POST -H "Content-Type: application/json" \
--data '{"metadata":{"name":"test"},"data":{"a":"YmFy"},"stringData":{"b":"test"}}'
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "test",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/secrets/test",
"uid": "82ef45ee-4fdd-11e8-87bf-00e092001ba4",
"resourceVersion": "25758",
"creationTimestamp": "2018-05-04T20:55:43Z"
},
"data": {
"a": "WW1GeQ==",
"b": "dGVzdA=="
},
"type": "Opaque"
}
P.S: I am not curling. I create secret through the func CreateSecret I mentioned in my initial bug report
I see. You are putting a base64 encoded string into the go object. Don't do that. Just put the string you want in, and when it is JSON encoded it is transformed to base64
In my case the string i assign to Data go object is a private key. if go-client is transforming it to base64 when it is JSON encoded, then it should be able to get the information back to original when mounted as volume to a pod. It is not able to do so.
it's all about what object ends up in the API. If you can create a secret using client-go that is identical when retrieved from the API as one created with kubectl create -f file.json, then they will behave the same when used within a pod
when I create a pod with reference to Secret created from Json - pod gets created successfully
is that using kubectl create -f ... or your CreateSecretFromJson method? can you give an example of the json file you fed in that worked as expected?
for example, you could write this in client-go:
kubeClient.client.CoreV1().Secrets(kubeClient.namespace).Create(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
Data: map[string][]byte{
"a": []byte(`bar`),
},
StringData: map[string]string{
"b": `test`,
},
})
which would produce this API object (kubectl get secret/test -o json):
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "test",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/secrets/test",
"uid": "82ef45ee-4fdd-11e8-87bf-00e092001ba4",
"resourceVersion": "25758",
"creationTimestamp": "2018-05-04T20:55:43Z"
},
"data": {
"a": "YmFy",
"b": "dGVzdA=="
},
"type": "Opaque"
}
which when mounted into a pod, would produce two files:
$ cat a
bar
$ cat b
test
Most helpful comment
for example, you could write this in client-go:
which would produce this API object (
kubectl get secret/test -o json):which when mounted into a pod, would produce two files: