Skip to content

Commit 8fda182

Browse files
committed
feat: Fail if placeholder resolves to binary data, that would break yaml
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
1 parent b046a7d commit 8fda182

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

pkg/kube/template_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package kube
22

33
import (
4+
"github.com/stretchr/testify/assert"
45
"os"
56
"reflect"
67
"regexp"
@@ -87,6 +88,63 @@ func TestToYAML_Missing_PlaceholdersSpecificPath(t *testing.T) {
8788
}
8889
}
8990

91+
func TestToYAML_BinaryValueInjectedToStringData(t *testing.T) {
92+
mv := helpers.MockVault{}
93+
94+
d := Template{
95+
Resource{
96+
Kind: "Secret",
97+
Annotations: map[string]string{
98+
types.AVPPathAnnotation: "path/to/secret",
99+
},
100+
TemplateData: map[string]interface{}{
101+
"apiVersion": "v1",
102+
"kind": "Secret",
103+
"metadata": map[string]interface{}{
104+
"namespace": "default",
105+
"name": "some-resource",
106+
"annotations": map[string]string{
107+
types.AVPPathAnnotation: "path/to/secret",
108+
},
109+
},
110+
"data": map[string]interface{}{
111+
"d-yscs": "<yaml-safe-control-chars>",
112+
"d-ubd": "<unsafe-binary-data>",
113+
"d-realistic": "<realistic>",
114+
},
115+
"stringData": map[string]interface{}{
116+
"sd-yscc": "<yaml-safe-control-chars>",
117+
"sd-ubd": "<unsafe-binary-data>",
118+
"sd-realistic": "<realistic>",
119+
},
120+
},
121+
Backend: &mv,
122+
Data: map[string]interface{}{
123+
// Tab and linebreak chars are safe
124+
"yaml-safe-control-chars": "\x09first\x0D\x0A\x09second\n",
125+
"unsafe-binary-data": "as\u0001df\nas\x0bdf",
126+
"realistic": "�\u0001\f\u0003�c�ţ8h�\u0001\a�R�\nڒp��Y4���E�m���+��W�%\u000FH��$�(���]�\u000E&\u000E�zi�@�O�X(\f��ߞ\u0003\a\u000EN(�a#��\u000F��5LF1�}��ݗ��\u000Fk\u0010�i5\u000FcJOϐ\u001F�.\u0000sp)�(5��\u0004a\u0015���\u0004�'�9�\u0002��\ak��M4\u0004~\u007F��:�Y�:�\u001A=]c�\u0004;����\u0013�ʼ��ױ;۹�C\u0001��+o+=��r�\u0011�*d�\u0018����Z�赁\u0004��Ża�\n�.հ\u0014H����\u0017�y�\u0006R�xv�X�i)\u0000��-^�\u0006L�ٲfQsfz�\u001D�ͩ8T6^E��5zk�غ%��B\u0001A�Ը�^\u0005��~�\u0084\u0004ă����\nq��;�e�f�Ic��\f\u000F4H]�+ܭU��×�D��\u0017�x�c��\u0017\u0017�{",
127+
},
128+
},
129+
}
130+
131+
expectedErr := []string{
132+
"Replace: could not replace all placeholders in Template:",
133+
"placeholder resolved to binary content in sd-ubd: <unsafe-binary-data>",
134+
"placeholder resolved to binary content in sd-realistic: <realistic>",
135+
"placeholder resolved to binary content in d-ubd: <unsafe-binary-data>",
136+
"placeholder resolved to binary content in d-realistic: <realistic>",
137+
}
138+
139+
err := d.Replace()
140+
if err == nil {
141+
yaml, _ := d.ToYAML()
142+
t.Fatalf("expected error %s but got success, producing: %s", expectedErr, yaml)
143+
}
144+
145+
assert.ElementsMatch(t, strings.Split(err.Error(), "\n"), expectedErr)
146+
}
147+
90148
func TestToYAML_RemoveMissing(t *testing.T) {
91149
mv := helpers.MockVault{}
92150

pkg/kube/util.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import (
55
"encoding/base64"
66
"encoding/json"
77
"fmt"
8+
"github.com/argoproj-labs/argocd-vault-plugin/pkg/types"
9+
"github.com/argoproj-labs/argocd-vault-plugin/pkg/utils"
10+
k8yaml "k8s.io/apimachinery/pkg/util/yaml"
811
"reflect"
912
"regexp"
1013
"strconv"
1114
"strings"
12-
13-
"github.com/argoproj-labs/argocd-vault-plugin/pkg/types"
14-
"github.com/argoproj-labs/argocd-vault-plugin/pkg/utils"
15-
k8yaml "k8s.io/apimachinery/pkg/util/yaml"
15+
"unicode"
1616
)
1717

1818
type missingKeyError struct {
@@ -199,7 +199,21 @@ func genericReplacement(key, value string, resource Resource) (_ interface{}, er
199199
return nonStringReplacement, err
200200
}
201201

202-
return string(res), err
202+
sres := string(res)
203+
if containsBinary(sres) {
204+
e := fmt.Errorf("placeholder resolved to binary content in %s: %s", key, value)
205+
err = append(err, e)
206+
}
207+
return sres, err
208+
}
209+
210+
func containsBinary(rep string) bool {
211+
for _, r := range rep {
212+
if unicode.IsControl(r) && r != '\t' && r != '\n' && r != '\r' {
213+
return true
214+
}
215+
}
216+
return false
203217
}
204218

205219
func configReplacement(key, value string, resource Resource) (interface{}, []error) {

0 commit comments

Comments
 (0)