-
Notifications
You must be signed in to change notification settings - Fork 198
/
yaml_encoder.go
145 lines (113 loc) · 3.36 KB
/
yaml_encoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package secret
import (
"fmt"
"gopkg.in/yaml.v2"
)
// YamlEncoder is an Encoder compatible object with additional helpers to work with yaml data: EncryptYamlData and DecryptYamlData
type YamlEncoder struct {
Encoder Encoder
generateFunc func([]byte) ([]byte, error)
extractFunc func([]byte) ([]byte, error)
}
func NewYamlEncoder(encoder Encoder) *YamlEncoder {
yamlEncoder := &YamlEncoder{Encoder: encoder}
if encoder != nil {
yamlEncoder.generateFunc = encoder.Encrypt
yamlEncoder.extractFunc = encoder.Decrypt
} else {
yamlEncoder.generateFunc = doNothing
yamlEncoder.extractFunc = doNothing
}
return yamlEncoder
}
func (s *YamlEncoder) Encrypt(data []byte) ([]byte, error) {
resultData, err := s.generateFunc(data)
if err != nil {
return nil, fmt.Errorf("encryption failed: check encryption key and data: %s", err)
}
return resultData, nil
}
func (s *YamlEncoder) EncryptYamlData(data []byte) ([]byte, error) {
resultData, err := doYamlData(s.generateFunc, data)
if err != nil {
return nil, fmt.Errorf("encryption failed: check encryption key and data: %s", err)
}
return resultData, nil
}
func (s *YamlEncoder) Decrypt(data []byte) ([]byte, error) {
resultData, err := s.extractFunc(data)
if err != nil {
if IsExtractDataError(err) {
return nil, fmt.Errorf("decryption failed: check data `%s`: %s", string(data), err)
}
return nil, fmt.Errorf("decryption failed: check encryption key and data: %s", err)
}
return resultData, nil
}
func (s *YamlEncoder) DecryptYamlData(data []byte) ([]byte, error) {
resultData, err := doYamlData(s.extractFunc, data)
if err != nil {
if IsExtractDataError(err) {
return nil, fmt.Errorf("decryption failed: check data `%s`: %s", string(data), err)
}
return nil, fmt.Errorf("decryption failed: check encryption key and data: %s", err)
}
return resultData, nil
}
func doYamlData(doFunc func([]byte) ([]byte, error), data []byte) ([]byte, error) {
config := make(yaml.MapSlice, 0)
err := yaml.UnmarshalStrict(data, &config)
if err != nil {
return nil, err
}
resultConfig, err := doYamlValueSecret(doFunc, config)
if err != nil {
return nil, err
}
resultData, err := yaml.Marshal(resultConfig)
if err != nil {
return nil, err
}
return resultData, nil
}
func doYamlValueSecret(doFunc func([]byte) ([]byte, error), data interface{}) (interface{}, error) {
switch data.(type) {
case yaml.MapSlice:
result := make(yaml.MapSlice, len(data.(yaml.MapSlice)))
for ind, elm := range data.(yaml.MapSlice) {
result[ind].Key = elm.Key
resultValue, err := doYamlValueSecret(doFunc, elm.Value)
if err != nil {
return nil, err
}
result[ind].Value = resultValue
}
return result, nil
case yaml.MapItem:
var result yaml.MapItem
result.Key = data.(yaml.MapItem).Key
resultValue, err := doYamlValueSecret(doFunc, data.(yaml.MapItem).Value)
if err != nil {
return nil, err
}
result.Value = resultValue
return result, nil
case []interface{}:
var result []interface{}
for _, elm := range data.([]interface{}) {
resultElm, err := doYamlValueSecret(doFunc, elm)
if err != nil {
return nil, err
}
result = append(result, resultElm)
}
return result, nil
default:
result, err := doFunc([]byte(fmt.Sprintf("%v", data)))
if err != nil {
return nil, err
}
return string(result), nil
}
}
func doNothing(data []byte) ([]byte, error) { return data, nil }