1
1
package diff
2
2
3
3
import (
4
+ "bytes"
4
5
"fmt"
5
6
"io"
6
7
"math"
@@ -9,19 +10,27 @@ import (
9
10
10
11
"github.com/aryann/difflib"
11
12
"github.com/mgutz/ansi"
13
+ v1 "k8s.io/api/core/v1"
14
+ "k8s.io/apimachinery/pkg/runtime/serializer/json"
15
+ "k8s.io/apimachinery/pkg/util/yaml"
16
+ "k8s.io/client-go/kubernetes/scheme"
12
17
13
18
"github.com/databus23/helm-diff/manifest"
14
19
)
15
20
16
21
// Manifests diff on manifests
17
- func Manifests (oldIndex , newIndex map [string ]* manifest.MappingResult , suppressedKinds []string , context int , to io.Writer ) bool {
22
+ func Manifests (oldIndex , newIndex map [string ]* manifest.MappingResult , suppressedKinds []string , showSecrets bool , context int , to io.Writer ) bool {
18
23
seenAnyChanges := false
19
24
emptyMapping := & manifest.MappingResult {}
20
25
for key , oldContent := range oldIndex {
21
26
if newContent , ok := newIndex [key ]; ok {
22
27
if oldContent .Content != newContent .Content {
23
28
// modified
24
29
fmt .Fprintf (to , ansi .Color ("%s has changed:" , "yellow" )+ "\n " , key )
30
+ if ! showSecrets {
31
+ redactSecrets (oldContent , newContent )
32
+ }
33
+
25
34
diffs := diffMappingResults (oldContent , newContent )
26
35
if len (diffs ) > 0 {
27
36
seenAnyChanges = true
@@ -31,6 +40,10 @@ func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressed
31
40
} else {
32
41
// removed
33
42
fmt .Fprintf (to , ansi .Color ("%s has been removed:" , "yellow" )+ "\n " , key )
43
+ if ! showSecrets {
44
+ redactSecrets (oldContent , nil )
45
+
46
+ }
34
47
diffs := diffMappingResults (oldContent , emptyMapping )
35
48
if len (diffs ) > 0 {
36
49
seenAnyChanges = true
@@ -43,6 +56,9 @@ func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressed
43
56
if _ , ok := oldIndex [key ]; ! ok {
44
57
// added
45
58
fmt .Fprintf (to , ansi .Color ("%s has been added:" , "yellow" )+ "\n " , key )
59
+ if ! showSecrets {
60
+ redactSecrets (nil , newContent )
61
+ }
46
62
diffs := diffMappingResults (emptyMapping , newContent )
47
63
if len (diffs ) > 0 {
48
64
seenAnyChanges = true
@@ -53,11 +69,79 @@ func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressed
53
69
return seenAnyChanges
54
70
}
55
71
72
+ func redactSecrets (old , new * manifest.MappingResult ) {
73
+ if old != nil && old .Kind != "Secret" && new != nil && new .Kind != "Secret" {
74
+ return
75
+ }
76
+ serializer := json .NewYAMLSerializer (json .DefaultMetaFactory , scheme .Scheme ,
77
+ scheme .Scheme )
78
+ var oldSecret , newSecret v1.Secret
79
+
80
+ if old != nil {
81
+ if err := yaml .NewYAMLToJSONDecoder (bytes .NewBufferString (old .Content )).Decode (& oldSecret ); err != nil {
82
+ old .Content = fmt .Sprintf ("Error parsing old secret: %s" , err )
83
+ }
84
+ }
85
+ if new != nil {
86
+ if err := yaml .NewYAMLToJSONDecoder (bytes .NewBufferString (new .Content )).Decode (& newSecret ); err != nil {
87
+ new .Content = fmt .Sprintf ("Error parsing new secret: %s" , err )
88
+ }
89
+ }
90
+ if old != nil {
91
+ oldSecret .StringData = make (map [string ]string , len (oldSecret .Data ))
92
+ for k , v := range oldSecret .Data {
93
+ if new != nil && bytes .Equal (v , newSecret .Data [k ]) {
94
+ oldSecret .StringData [k ] = fmt .Sprintf ("REDACTED # (%d bytes)" , len (v ))
95
+ } else {
96
+ oldSecret .StringData [k ] = fmt .Sprintf ("-------- # (%d bytes)" , len (v ))
97
+ }
98
+ }
99
+ }
100
+ if new != nil {
101
+ newSecret .StringData = make (map [string ]string , len (newSecret .Data ))
102
+ for k , v := range newSecret .Data {
103
+ if old != nil && bytes .Equal (v , oldSecret .Data [k ]) {
104
+ newSecret .StringData [k ] = fmt .Sprintf ("REDACTED # (%d bytes)" , len (v ))
105
+ } else {
106
+ newSecret .StringData [k ] = fmt .Sprintf ("++++++++ # (%d bytes)" , len (v ))
107
+ }
108
+ }
109
+ }
110
+ // remove Data field now that we are using StringData for serialization
111
+ var buf bytes.Buffer
112
+ if old != nil {
113
+ oldSecret .Data = nil
114
+ if err := serializer .Encode (& oldSecret , & buf ); err != nil {
115
+
116
+ }
117
+ old .Content = getComment (old .Content ) + strings .Replace (strings .Replace (buf .String (), "stringData" , "data" , 1 ), " creationTimestamp: null\n " , "" , 1 )
118
+ buf .Reset () //reuse buffer for new secret
119
+ }
120
+ if new != nil {
121
+ newSecret .Data = nil
122
+ if err := serializer .Encode (& newSecret , & buf ); err != nil {
123
+
124
+ }
125
+ new .Content = getComment (new .Content ) + strings .Replace (strings .Replace (buf .String (), "stringData" , "data" , 1 ), " creationTimestamp: null\n " , "" , 1 )
126
+ }
127
+ }
128
+
129
+ // return the first line of a string if its a comment.
130
+ // This gives as the # Source: lines from the rendering
131
+ func getComment (s string ) string {
132
+ i := strings .Index (s , "\n " )
133
+ if i < 0 || ! strings .HasPrefix (s , "#" ) {
134
+ return ""
135
+ }
136
+ return s [:i + 1 ]
137
+
138
+ }
139
+
56
140
// Releases reindex the content based on the template names and pass it to Manifests
57
- func Releases (oldIndex , newIndex map [string ]* manifest.MappingResult , suppressedKinds []string , context int , to io.Writer ) bool {
141
+ func Releases (oldIndex , newIndex map [string ]* manifest.MappingResult , suppressedKinds []string , showSecrets bool , context int , to io.Writer ) bool {
58
142
oldIndex = reIndexForRelease (oldIndex )
59
143
newIndex = reIndexForRelease (newIndex )
60
- return Manifests (oldIndex , newIndex , suppressedKinds , context , to )
144
+ return Manifests (oldIndex , newIndex , suppressedKinds , showSecrets , context , to )
61
145
}
62
146
63
147
func diffMappingResults (oldContent * manifest.MappingResult , newContent * manifest.MappingResult ) []difflib.DiffRecord {
@@ -71,6 +155,7 @@ func diffStrings(before, after string) []difflib.DiffRecord {
71
155
72
156
func printDiffRecords (suppressedKinds []string , kind string , context int , diffs []difflib.DiffRecord , to io.Writer ) {
73
157
for _ , ckind := range suppressedKinds {
158
+
74
159
if ckind == kind {
75
160
str := fmt .Sprintf ("+ Changes suppressed on sensitive content of type %s\n " , kind )
76
161
fmt .Fprintf (to , ansi .Color (str , "yellow" ))
0 commit comments