@@ -2,13 +2,14 @@ package cloudsupport
2
2
3
3
import (
4
4
"context"
5
+ "encoding/base64"
6
+ "encoding/json"
5
7
"fmt"
8
+ "strings"
6
9
7
- logger "github.com/kubescape/go-logger"
8
- "github.com/kubescape/go-logger/helpers"
9
-
10
- "github.com/armosec/utils-k8s-go/secrethandling"
11
10
"github.com/docker/docker/api/types/registry"
11
+ "github.com/kubescape/go-logger"
12
+ "github.com/kubescape/go-logger/helpers"
12
13
"github.com/kubescape/k8s-interface/k8sinterface"
13
14
corev1 "k8s.io/api/core/v1"
14
15
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -18,15 +19,15 @@ func listPodImagePullSecrets(podSpec *corev1.PodSpec) ([]string, error) {
18
19
if podSpec == nil {
19
20
return []string {}, fmt .Errorf ("in listPodImagePullSecrets podSpec is nil" )
20
21
}
21
- secrets := []string {}
22
+ var secrets []string
22
23
for _ , i := range podSpec .ImagePullSecrets {
23
24
secrets = append (secrets , i .Name )
24
25
}
25
26
return secrets , nil
26
27
}
27
28
28
29
func listServiceAccountImagePullSecrets (k8sAPI * k8sinterface.KubernetesApi , namespace , serviceAccountName string ) ([]string , error ) {
29
- secrets := []string {}
30
+ var secrets []string
30
31
if serviceAccountName == "" {
31
32
return secrets , nil
32
33
}
@@ -41,49 +42,44 @@ func listServiceAccountImagePullSecrets(k8sAPI *k8sinterface.KubernetesApi, name
41
42
return secrets , nil
42
43
}
43
44
44
- func getImagePullSecret (k8sAPI * k8sinterface.KubernetesApi , secrets []string , namespace string ) map [string ]registry.AuthConfig {
45
+ func getImagePullSecret (k8sAPI * k8sinterface.KubernetesApi , secrets []string , namespace string ) map [string ][] registry.AuthConfig {
45
46
46
- secretsAuthConfig := make (map [string ]registry.AuthConfig )
47
+ secretsAuthConfig := make (map [string ][] registry.AuthConfig )
47
48
48
49
for i := range secrets {
49
50
res , err := k8sAPI .KubernetesClient .CoreV1 ().Secrets (namespace ).Get (context .Background (), secrets [i ], metav1.GetOptions {})
50
51
if err != nil {
51
52
logger .L ().Error ("unable to get secret" , helpers .String ("secret name" , secrets [i ]), helpers .Error (err ))
52
53
continue
53
54
}
54
- sec , err := secrethandling . ParseSecret (res , secrets [ i ] )
55
+ sec , err := ParseSecret (res )
55
56
if err != nil {
56
57
logger .L ().Error ("failed to pars secret" , helpers .String ("secret name" , secrets [i ]), helpers .Error (err ))
57
58
continue
58
59
}
59
- secretsAuthConfig [secrets [i ]] = * sec
60
+ secretsAuthConfig [secrets [i ]] = sec
60
61
}
61
62
62
63
return secretsAuthConfig
63
64
}
64
65
65
- // DEPRECATED
66
66
// GetImageRegistryCredentials returns various credentials for images in the pod
67
67
// imageTag empty means returns all of the credentials for all images in pod spec containers
68
68
// pod.ObjectMeta.Namespace must be well setted
69
- func GetImageRegistryCredentials ( imageTag string , pod * corev1. Pod ) ( map [ string ]registry. AuthConfig , error ) {
70
- k8sAPI := k8sinterface .NewKubernetesApi ()
69
+ // DEPRECATED
70
+ func GetImageRegistryCredentials ( k8sAPI * k8sinterface.KubernetesApi , imageTag string , pod * corev1. Pod ) ( map [ string ][]registry. AuthConfig , error ) {
71
71
listSecret , _ := listPodImagePullSecrets (& pod .Spec )
72
72
listServiceSecret , _ := listServiceAccountImagePullSecrets (k8sAPI , pod .GetNamespace (), pod .Spec .ServiceAccountName )
73
73
listSecret = append (listSecret , listServiceSecret ... )
74
74
secrets := getImagePullSecret (k8sAPI , listSecret , pod .ObjectMeta .Namespace )
75
75
76
- if len (secrets ) == 0 {
77
- secrets = make (map [string ]registry.AuthConfig )
78
- }
79
-
80
76
if imageTag != "" {
81
77
cloudVendorSecrets , err := GetCloudVendorRegistryCredentials (imageTag )
82
78
if err != nil {
83
79
logger .L ().Debug ("failed to GetCloudVendorRegistryCredentials" , helpers .String ("imageTag" , imageTag ), helpers .Error (err ))
84
80
} else if len (cloudVendorSecrets ) > 0 {
85
81
for secName := range cloudVendorSecrets {
86
- secrets [secName ] = cloudVendorSecrets [secName ]
82
+ secrets [secName ] = []registry. AuthConfig { cloudVendorSecrets [secName ]}
87
83
}
88
84
}
89
85
} else {
@@ -95,7 +91,7 @@ func GetImageRegistryCredentials(imageTag string, pod *corev1.Pod) (map[string]r
95
91
logger .L ().Debug ("failed to GetCloudVendorRegistryCredentials" , helpers .String ("imageTag" , imageTag ), helpers .Error (err ))
96
92
} else if len (cloudVendorSecrets ) > 0 {
97
93
for secName := range cloudVendorSecrets {
98
- secrets [secName ] = cloudVendorSecrets [secName ]
94
+ secrets [secName ] = []registry. AuthConfig { cloudVendorSecrets [secName ]}
99
95
}
100
96
}
101
97
}
@@ -104,30 +100,25 @@ func GetImageRegistryCredentials(imageTag string, pod *corev1.Pod) (map[string]r
104
100
return secrets , nil
105
101
}
106
102
107
- // GetImageRegistryCredentials returns various credentials for images in the pod
103
+ // GetWorkloadImageRegistryCredentials returns various credentials for images in the pod
108
104
// imageTag empty means returns all of the credentials for all images in pod spec containers
109
105
// pod.ObjectMeta.Namespace must be well setted
110
- func GetWorkloadImageRegistryCredentials (imageTag string , workload k8sinterface.IWorkload ) (map [string ]registry.AuthConfig , error ) {
106
+ func GetWorkloadImageRegistryCredentials (k8sAPI * k8sinterface. KubernetesApi , imageTag string , workload k8sinterface.IWorkload ) (map [string ][ ]registry.AuthConfig , error ) {
111
107
podSpec , err := workload .GetPodSpec ()
112
108
if err != nil {
113
109
return nil , err
114
110
}
115
- k8sAPI := k8sinterface .NewKubernetesApi ()
116
111
listSecret , _ := listPodImagePullSecrets (podSpec )
117
112
listServiceSecret , _ := listServiceAccountImagePullSecrets (k8sAPI , workload .GetNamespace (), podSpec .ServiceAccountName )
118
113
listSecret = append (listSecret , listServiceSecret ... )
119
114
secrets := getImagePullSecret (k8sAPI , listSecret , workload .GetNamespace ())
120
115
121
- if len (secrets ) == 0 {
122
- secrets = make (map [string ]registry.AuthConfig )
123
- }
124
-
125
116
if imageTag != "" {
126
117
if cloudVendorSecrets , err := GetCloudVendorRegistryCredentials (imageTag ); err != nil {
127
118
return secrets , fmt .Errorf ("failed to GetCloudVendorRegistryCredentials, image: %s, message: %v" , imageTag , err )
128
119
} else if len (cloudVendorSecrets ) > 0 {
129
120
for secName := range cloudVendorSecrets {
130
- secrets [secName ] = cloudVendorSecrets [secName ]
121
+ secrets [secName ] = []registry. AuthConfig { cloudVendorSecrets [secName ]}
131
122
}
132
123
}
133
124
} else {
@@ -137,7 +128,7 @@ func GetWorkloadImageRegistryCredentials(imageTag string, workload k8sinterface.
137
128
return secrets , fmt .Errorf ("failed to GetCloudVendorRegistryCredentials, image: %s, message: %v" , imageTag , err )
138
129
} else if len (cloudVendorSecrets ) > 0 {
139
130
for secName := range cloudVendorSecrets {
140
- secrets [secName ] = cloudVendorSecrets [secName ]
131
+ secrets [secName ] = []registry. AuthConfig { cloudVendorSecrets [secName ]}
141
132
}
142
133
}
143
134
}
@@ -165,3 +156,119 @@ func GetWorkloadsImages(workload k8sinterface.IWorkload) map[string]string {
165
156
}
166
157
return images
167
158
}
159
+
160
+ type DockerConfigJsonstructure map [string ]map [string ]registry.AuthConfig
161
+
162
+ func updateSecret (authConfig * registry.AuthConfig , serverAddress string ) {
163
+ if authConfig .ServerAddress == "" {
164
+ authConfig .ServerAddress = serverAddress
165
+ }
166
+ if authConfig .Username == "" || authConfig .Password == "" {
167
+ auth := authConfig .Auth
168
+ decodedAuth , err := base64 .StdEncoding .DecodeString (auth )
169
+ if err != nil {
170
+ return
171
+ }
172
+
173
+ splittedAuth := strings .Split (string (decodedAuth ), ":" )
174
+ if len (splittedAuth ) == 2 {
175
+ authConfig .Username = splittedAuth [0 ]
176
+ authConfig .Password = splittedAuth [1 ]
177
+ }
178
+ }
179
+ if authConfig .Auth == "" {
180
+ auth := fmt .Sprintf ("%s:%s" , authConfig .Username , authConfig .Password )
181
+ authConfig .Auth = base64 .StdEncoding .EncodeToString ([]byte (auth ))
182
+ }
183
+ }
184
+
185
+ func parseEncodedSecret (sec map [string ][]byte ) (string , string ) {
186
+ buser := sec [corev1 .BasicAuthUsernameKey ]
187
+ bpsw := sec [corev1 .BasicAuthPasswordKey ]
188
+ duser , _ := base64 .StdEncoding .DecodeString (string (buser ))
189
+ dpsw , _ := base64 .StdEncoding .DecodeString (string (bpsw ))
190
+ return string (duser ), string (dpsw )
191
+
192
+ }
193
+
194
+ func parseDecodedSecret (sec map [string ]string ) (string , string ) {
195
+ user := sec [corev1 .BasicAuthUsernameKey ]
196
+ psw := sec [corev1 .BasicAuthPasswordKey ]
197
+ return user , psw
198
+
199
+ }
200
+
201
+ func GetSecretContent (secret * corev1.Secret ) (interface {}, error ) {
202
+
203
+ // Secret types- https://github.com/kubernetes/kubernetes/blob/7693a1d5fe2a35b6e2e205f03ae9b3eddcdabc6b/pkg/apis/core/types.go#L4394-L4478
204
+ switch secret .Type {
205
+ case corev1 .SecretTypeDockerConfigJson :
206
+ sec := make (DockerConfigJsonstructure )
207
+ if err := json .Unmarshal (secret .Data [corev1 .DockerConfigJsonKey ], & sec ); err != nil {
208
+ return nil , err
209
+ }
210
+ return sec , nil
211
+ default :
212
+ user , psw := "" , ""
213
+ if len (secret .Data ) != 0 {
214
+ user , psw = parseEncodedSecret (secret .Data )
215
+ } else if len (secret .StringData ) != 0 {
216
+ userD , pswD := parseDecodedSecret (secret .StringData )
217
+ if userD != "" {
218
+ user = userD
219
+ }
220
+ if pswD != "" {
221
+ psw = pswD
222
+ }
223
+ } else {
224
+ return nil , fmt .Errorf ("data not found in secret" )
225
+ }
226
+ if user == "" || psw == "" {
227
+ return nil , fmt .Errorf ("username or password not found" )
228
+ }
229
+
230
+ return & registry.AuthConfig {Username : user , Password : psw }, nil
231
+ }
232
+ }
233
+
234
+ func ParseSecret (res * corev1.Secret ) ([]registry.AuthConfig , error ) {
235
+
236
+ // Read secret
237
+ secret , err := GetSecretContent (res )
238
+ if err != nil {
239
+ return nil , err
240
+ }
241
+
242
+ if secret == nil {
243
+ return nil , fmt .Errorf ("secret not found" )
244
+ }
245
+ sec , err := ReadSecret (secret )
246
+ if err != nil {
247
+ return sec , err
248
+ }
249
+ return sec , nil
250
+
251
+ }
252
+
253
+ func ReadSecret (secret interface {}) ([]registry.AuthConfig , error ) {
254
+ // Store secret based on it's structure
255
+ var authConfig []registry.AuthConfig
256
+ if sec , ok := secret .(* registry.AuthConfig ); ok {
257
+ return []registry.AuthConfig {* sec }, nil
258
+ }
259
+ if sec , ok := secret .(map [string ]string ); ok {
260
+ return []registry.AuthConfig {{Username : sec ["username" ]}}, nil
261
+ }
262
+ if sec , ok := secret .(DockerConfigJsonstructure ); ok {
263
+ if _ , k := sec ["auths" ]; ! k {
264
+ return authConfig , fmt .Errorf ("cant find auths" )
265
+ }
266
+ for serverAddress , auth := range sec ["auths" ] {
267
+ updateSecret (& auth , serverAddress )
268
+ authConfig = append (authConfig , auth )
269
+ }
270
+ return authConfig , nil
271
+ }
272
+
273
+ return authConfig , fmt .Errorf ("cant find secret" )
274
+ }
0 commit comments