Skip to content

Commit

Permalink
decode input secrets used in template stringData
Browse files Browse the repository at this point in the history
  • Loading branch information
carpenterm committed Jul 31, 2023
1 parent f737917 commit 617ff2e
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
39 changes: 38 additions & 1 deletion pkg/generator/secret_template_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package generator
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"time"

Expand Down Expand Up @@ -283,7 +284,12 @@ func evaluateTemplate(template *sg2v1alpha1.JSONPathTemplate, values map[string]
}

// Template Secret StringData
stringData, err := evaluate(template.StringData, values)
decodedValues, err := decodeSecrets(values)
if err != nil {
return corev1.Secret{}, fmt.Errorf("decoding secrets: %w", err)
}

stringData, err := evaluate(template.StringData, decodedValues)
if err != nil {
return corev1.Secret{}, fmt.Errorf("templating stringData: %w", err)
}
Expand Down Expand Up @@ -349,3 +355,34 @@ func evaluateBytes(mapping map[string]string, values map[string]interface{}) (ma

return evaluatedMapping, nil
}

func decodeSecrets(values map[string]interface{}) (map[string]interface{}, error) {
decodedValues := make(map[string]interface{})
for valueKey, value := range values {
jsonData, err := json.Marshal(value)
if err != nil {
return nil, fmt.Errorf("failed to marshal values into JSON: %w", err)
}

obj := &unstructured.Unstructured{}
if err := json.Unmarshal(jsonData, obj); err != nil {
return nil, fmt.Errorf("failed to unmarshal JSON into Unstructured object: %w", err)
}

if obj.GetKind() == "Secret" {
data, _, _ := unstructured.NestedStringMap(obj.Object, "data")
for dataKey, encodedValue := range data {
decodedValue, err := base64.StdEncoding.DecodeString(string(encodedValue))
if err != nil {
return nil, fmt.Errorf("failed decoding base64 from a Secret: %w", err)
}
unstructured.SetNestedStringMap(obj.Object, map[string]string{dataKey: string(decodedValue)}, "data")
}
decodedValues[valueKey] = obj.Object
} else {
decodedValues[valueKey] = value
}
}

return decodedValues, nil
}
56 changes: 56 additions & 0 deletions pkg/generator/secret_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,62 @@ func Test_SecretTemplate(t *testing.T) {
},
},
},
{
name: "reconciling secret template with input from another secret decoded in stringData",
template: sg2v1alpha1.SecretTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "secretTemplate",
Namespace: "test",
},
Spec: sg2v1alpha1.SecretTemplateSpec{
InputResources: []sg2v1alpha1.InputResource{{
Name: "creds",
Ref: sg2v1alpha1.InputResourceRef{
APIVersion: "v1",
Kind: "Secret",
Name: "existingSecret",
},
}},
JSONPathTemplate: &sg2v1alpha1.JSONPathTemplate{
Data: map[string]string{
"key1": "$( .creds.data.inputKey1 )",
"key2": "$( .creds.data.inputKey2 )",
},
StringData: map[string]string{
"key3": "test-$( .creds.data.inputKey3 )",
},
},
},
},
existingObjects: []client.Object{
secret("existingSecret", map[string]string{
"inputKey1": "value1",
"inputKey2": "value2",
"inputKey3": "value3",
}),
},
expectedSecret: corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "secretTemplate",
Namespace: "test",
ResourceVersion: "1",
OwnerReferences: []metav1.OwnerReference{
secretTemplateOwnerRef("secretTemplate"),
},
},
Data: map[string][]byte{
"key1": []byte("value1"),
"key2": []byte("value2"),
},
StringData: map[string]string{
"key3": "test-value3",
},
},
},
{
name: "reconciling secret template with input from two inputs with dynamic inputname",
template: sg2v1alpha1.SecretTemplate{
Expand Down

0 comments on commit 617ff2e

Please sign in to comment.