Skip to content

Commit c60d355

Browse files
committed
add pullsecrets from pod for scanAP
Signed-off-by: Matthias Bertschy <[email protected]>
1 parent 99e26a6 commit c60d355

26 files changed

+303
-303
lines changed

admission/rules/v1/helpers.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"context"
55
"fmt"
66

7-
v1 "k8s.io/api/core/v1"
7+
corev1 "k8s.io/api/core/v1"
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1010
"k8s.io/apimachinery/pkg/runtime"
@@ -22,7 +22,7 @@ func GetControllerDetails(event admission.Attributes, clientset kubernetes.Inter
2222

2323
pod, err := GetPodDetails(clientset, podName, namespace)
2424
if err != nil {
25-
return "", "", "", "", fmt.Errorf("failed to get pod details: %v", err)
25+
return "", "", "", "", fmt.Errorf("failed to get pod details: %w", err)
2626
}
2727

2828
workloadKind, workloadName, workloadNamespace := ExtractPodOwner(pod, clientset)
@@ -32,16 +32,16 @@ func GetControllerDetails(event admission.Attributes, clientset kubernetes.Inter
3232
}
3333

3434
// GetPodDetails returns the pod details from the Kubernetes API server.
35-
func GetPodDetails(clientset kubernetes.Interface, podName, namespace string) (*v1.Pod, error) {
35+
func GetPodDetails(clientset kubernetes.Interface, podName, namespace string) (*corev1.Pod, error) {
3636
pod, err := clientset.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
3737
if err != nil {
38-
return nil, fmt.Errorf("failed to get pod: %v", err)
38+
return nil, fmt.Errorf("failed to get pod: %w", err)
3939
}
4040
return pod, nil
4141
}
4242

4343
// ExtractPodOwner returns the kind, name, and namespace of the controller that owns the pod.
44-
func ExtractPodOwner(pod *v1.Pod, clientset kubernetes.Interface) (string, string, string) {
44+
func ExtractPodOwner(pod *corev1.Pod, clientset kubernetes.Interface) (string, string, string) {
4545
for _, ownerRef := range pod.OwnerReferences {
4646
switch ownerRef.Kind {
4747
case "ReplicaSet":
@@ -91,9 +91,9 @@ func GetContainerNameFromExecToPodEvent(event admission.Attributes) (string, err
9191
return "", fmt.Errorf("object is not of type *unstructured.Unstructured")
9292
}
9393

94-
podExecOptions := &v1.PodExecOptions{}
94+
podExecOptions := &corev1.PodExecOptions{}
9595
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredObj.Object, podExecOptions); err != nil {
96-
return "", fmt.Errorf("failed to decode PodExecOptions: %v", err)
96+
return "", fmt.Errorf("failed to decode PodExecOptions: %w", err)
9797
}
9898

9999
return podExecOptions.Container, nil

admission/webhook/server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ func parseRequest(r *http.Request) (*admissionv1.AdmissionReview, error) {
393393
var admissionReview admissionv1.AdmissionReview
394394

395395
if err := json.Unmarshal(body, &admissionReview); err != nil {
396-
return nil, fmt.Errorf("could not parse admission review request: %v", err)
396+
return nil, fmt.Errorf("could not parse admission review request: %w", err)
397397
}
398398

399399
if admissionReview.Request == nil {

admission/webhook/server_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/kubescape/node-agent/pkg/watcher"
1515
"github.com/stretchr/testify/assert"
1616
admissionv1 "k8s.io/api/admission/v1"
17-
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1818
"k8s.io/apimachinery/pkg/runtime"
1919
"k8s.io/apimachinery/pkg/runtime/serializer"
2020
"k8s.io/apiserver/pkg/admission"
@@ -59,7 +59,7 @@ func TestHandleWebhookValidate(t *testing.T) {
5959
review := admissionv1.AdmissionReview{
6060
Request: &admissionv1.AdmissionRequest{
6161
UID: "12345",
62-
Kind: v1.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
62+
Kind: metav1.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
6363
Object: runtime.RawExtension{
6464
Raw: []byte(`{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"test"}}`),
6565
},

main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func main() {
109109
k8sConfig.ContentType = "application/vnd.kubernetes.protobuf"
110110
ksStorageClient, err := kssc.NewForConfig(k8sConfig)
111111
if err != nil {
112-
logger.L().Ctx(ctx).Fatal(fmt.Sprintf("Unable to initialize the storage client: %v", err))
112+
logger.L().Ctx(ctx).Fatal("unable to initialize the storage client", helpers.Error(err))
113113
}
114114

115115
kubernetesCache := objectcache.NewKubernetesCache(k8sApi)

mainhandler/handlerequests.go

+22-28
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,33 @@ import (
77
"regexp"
88
"time"
99

10+
"github.com/armosec/armoapi-go/apis"
11+
"github.com/armosec/armoapi-go/identifiers"
12+
"github.com/armosec/utils-go/boolutils"
13+
"github.com/armosec/utils-go/httputils"
14+
pkgwlid "github.com/armosec/utils-k8s-go/wlid"
1015
mapset "github.com/deckarep/golang-set/v2"
11-
exporters "github.com/kubescape/operator/admission/exporter"
12-
1316
"github.com/kubescape/backend/pkg/versioncheck"
14-
"github.com/kubescape/k8s-interface/workloadinterface"
15-
core1 "k8s.io/api/core/v1"
16-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17-
"k8s.io/apimachinery/pkg/labels"
18-
"k8s.io/apimachinery/pkg/runtime"
19-
"k8s.io/client-go/tools/pager"
20-
2117
"github.com/kubescape/go-logger"
2218
"github.com/kubescape/go-logger/helpers"
19+
instanceidhandlerv1 "github.com/kubescape/k8s-interface/instanceidhandler/v1"
20+
"github.com/kubescape/k8s-interface/k8sinterface"
21+
"github.com/kubescape/k8s-interface/workloadinterface"
22+
v1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
23+
utilsmetav1 "github.com/kubescape/opa-utils/httpserver/meta/v1"
24+
exporters "github.com/kubescape/operator/admission/exporter"
2325
"github.com/kubescape/operator/config"
2426
cs "github.com/kubescape/operator/continuousscanning"
2527
"github.com/kubescape/operator/utils"
2628
"github.com/kubescape/operator/watcher"
29+
kssc "github.com/kubescape/storage/pkg/generated/clientset/versioned"
2730
"github.com/panjf2000/ants/v2"
2831
"go.opentelemetry.io/otel"
29-
30-
"github.com/armosec/armoapi-go/identifiers"
31-
"github.com/armosec/utils-go/boolutils"
32-
"github.com/armosec/utils-go/httputils"
33-
34-
"github.com/armosec/armoapi-go/apis"
35-
36-
v1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
37-
utilsmetav1 "github.com/kubescape/opa-utils/httpserver/meta/v1"
38-
39-
pkgwlid "github.com/armosec/utils-k8s-go/wlid"
40-
instanceidhandlerv1 "github.com/kubescape/k8s-interface/instanceidhandler/v1"
41-
"github.com/kubescape/k8s-interface/k8sinterface"
42-
kssc "github.com/kubescape/storage/pkg/generated/clientset/versioned"
32+
corev1 "k8s.io/api/core/v1"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
"k8s.io/apimachinery/pkg/labels"
35+
"k8s.io/apimachinery/pkg/runtime"
36+
"k8s.io/client-go/tools/pager"
4337
)
4438

4539
type MainHandler struct {
@@ -117,7 +111,7 @@ func NewActionHandler(config config.IConfig, k8sAPI *k8sinterface.KubernetesApi,
117111
func (mainHandler *MainHandler) SetupContinuousScanning(ctx context.Context) error {
118112
ksStorageClient, err := kssc.NewForConfig(k8sinterface.GetK8sConfig())
119113
if err != nil {
120-
logger.L().Ctx(ctx).Fatal(fmt.Sprintf("Unable to initialize the storage client: %v", err))
114+
logger.L().Ctx(ctx).Fatal("unable to initialize the storage client", helpers.Error(err))
121115
}
122116

123117
triggeringHandler := cs.NewTriggeringHandler(mainHandler.eventWorkerPool, mainHandler.config)
@@ -301,7 +295,7 @@ func (mainHandler *MainHandler) HandleScopedRequest(ctx context.Context, session
301295
if err := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
302296
return mainHandler.k8sAPI.KubernetesClient.CoreV1().Pods(ns).List(ctx, opts)
303297
}).EachListItem(ctx, listOptions, func(obj runtime.Object) error {
304-
pod := obj.(*core1.Pod)
298+
pod := obj.(*corev1.Pod)
305299
podId := pkgwlid.GetWLID(mainHandler.config.ClusterName(), pod.GetNamespace(), "pod", pod.GetName())
306300
cmd := sessionObj.Command.DeepCopy()
307301

@@ -385,8 +379,8 @@ func (mainHandler *MainHandler) HandleImageScanningScopedRequest(ctx context.Con
385379
if err := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
386380
return mainHandler.k8sAPI.KubernetesClient.CoreV1().Pods(ns).List(ctx, opts)
387381
}).EachListItem(ctx, listOptions, func(obj runtime.Object) error {
388-
pod := obj.(*core1.Pod)
389-
if pod.Status.Phase != core1.PodRunning {
382+
pod := obj.(*corev1.Pod)
383+
if pod.Status.Phase != corev1.PodRunning {
390384
// skip non-running pods, for some reason the list includes non-running pods
391385
return nil
392386
}
@@ -428,7 +422,7 @@ func (mainHandler *MainHandler) HandleImageScanningScopedRequest(ctx context.Con
428422

429423
noContainerSlug, _ := instanceID.GetSlug(true)
430424
if appProfile := utils.GetApplicationProfileForRelevancyScan(ctx, mainHandler.ksStorageClient, noContainerSlug, ns); appProfile != nil {
431-
cmd := utils.GetApplicationProfileScanCommand(appProfile)
425+
cmd := utils.GetApplicationProfileScanCommand(appProfile, pod)
432426

433427
// send specific command to the channel
434428
newSessionObj := utils.NewSessionObj(ctx, mainHandler.config, cmd, sessionObj.JobID, "")

mainhandler/vulnscan.go

+41-30
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,28 @@ import (
1010
"strings"
1111
"time"
1212

13+
"github.com/armosec/armoapi-go/apis"
14+
apitypes "github.com/armosec/armoapi-go/armotypes"
15+
"github.com/armosec/armoapi-go/identifiers"
1316
"github.com/armosec/registryx/interfaces"
1417
"github.com/armosec/registryx/registryclients"
15-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16-
"k8s.io/utils/strings/slices"
17-
18+
"github.com/armosec/utils-go/httputils"
19+
"github.com/armosec/utils-k8s-go/armometadata"
1820
"github.com/distribution/reference"
1921
dockerregistry "github.com/docker/docker/api/types/registry"
22+
"github.com/google/uuid"
2023
"github.com/kubescape/go-logger"
2124
"github.com/kubescape/go-logger/helpers"
25+
"github.com/kubescape/k8s-interface/cloudsupport"
2226
"github.com/kubescape/k8s-interface/k8sinterface"
2327
"github.com/kubescape/operator/config"
2428
"github.com/kubescape/operator/utils"
2529
"go.opentelemetry.io/otel"
2630
"go.opentelemetry.io/otel/attribute"
2731
"go.opentelemetry.io/otel/trace"
28-
2932
corev1 "k8s.io/api/core/v1"
30-
31-
"github.com/google/uuid"
32-
33-
"github.com/armosec/armoapi-go/apis"
34-
apitypes "github.com/armosec/armoapi-go/armotypes"
35-
"github.com/armosec/armoapi-go/identifiers"
36-
"github.com/armosec/utils-k8s-go/armometadata"
37-
38-
"github.com/armosec/utils-go/httputils"
39-
"github.com/kubescape/k8s-interface/cloudsupport"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
"k8s.io/utils/strings/slices"
4035
)
4136

4237
func getAPScanURL(config config.IConfig) *url.URL {
@@ -100,7 +95,7 @@ func (actionHandler *ActionHandler) scanRegistriesV2AndUpdateStatus(ctx context.
10095
scanTime := time.Now()
10196
imageRegistry, err := actionHandler.loadRegistryFromSessionObj()
10297
if err != nil {
103-
return fmt.Errorf("failed to load registry from sessionObj with err %v", err)
98+
return fmt.Errorf("failed to load registry from sessionObj: %w", err)
10499
}
105100

106101
err = actionHandler.scanRegistriesV2(ctx, imageRegistry)
@@ -119,27 +114,27 @@ func (actionHandler *ActionHandler) scanRegistriesV2AndUpdateStatus(ctx context.
119114

120115
func (actionHandler *ActionHandler) scanRegistriesV2(ctx context.Context, imageRegistry apitypes.ContainerImageRegistry) error {
121116
if err := actionHandler.loadRegistrySecret(ctx, imageRegistry); err != nil {
122-
return fmt.Errorf("failed to load secret with err %v", err)
117+
return fmt.Errorf("failed to load secret: %w", err)
123118
}
124119

125120
client, err := registryclients.GetRegistryClient(imageRegistry)
126121
if err != nil {
127-
return fmt.Errorf("failed to get registry client with err %v", err)
122+
return fmt.Errorf("failed to get registry client: %w", err)
128123
}
129124

130125
images, err := client.GetImagesToScan(ctx)
131126
if err != nil {
132-
return fmt.Errorf("failed to get registry images to scan with err %v", err)
127+
return fmt.Errorf("failed to get registry images to scan: %w", err)
133128
} else if len(images) == 0 {
134129
return errors.New(noImagesToScanError)
135130
}
136131

137132
registryScanCMDList, err := actionHandler.getRegistryImageScanCommands(client, imageRegistry, images)
138133
if err != nil {
139-
return fmt.Errorf("failed to get registry images scan commands with err %v", err)
134+
return fmt.Errorf("failed to get registry images scan commands: %w", err)
140135
}
141136
if err = sendAllImagesToRegistryScan(ctx, actionHandler.config, registryScanCMDList); err != nil {
142-
return fmt.Errorf("failed to send scan commands with err %v", err)
137+
return fmt.Errorf("failed to send scan commands: %w", err)
143138
}
144139

145140
return nil
@@ -149,17 +144,17 @@ func (actionHandler *ActionHandler) loadRegistrySecret(ctx context.Context, imag
149144
secretName := actionHandler.sessionObj.Command.Args[apitypes.RegistrySecretNameArgKey].(string)
150145
secret, err := actionHandler.k8sAPI.KubernetesClient.CoreV1().Secrets(actionHandler.config.Namespace()).Get(ctx, secretName, metav1.GetOptions{})
151146
if err != nil {
152-
return fmt.Errorf("loadRegistrySecret failed to get secret with err %v", err)
147+
return fmt.Errorf("loadRegistrySecret failed to get secret: %w", err)
153148
}
154149

155150
var secretMap map[string]interface{}
156151
err = json.Unmarshal(secret.Data[apitypes.RegistryAuthFieldInSecret], &secretMap)
157152
if err != nil {
158-
return fmt.Errorf("loadRegistrySecret failed to unmarshal registry secret with err %v", err)
153+
return fmt.Errorf("loadRegistrySecret failed to unmarshal registry secret: %w", err)
159154
}
160155
err = imageRegistry.FillSecret(secretMap)
161156
if err != nil {
162-
return fmt.Errorf("loadRegistrySecret failed to fill registry secret with err %v", err)
157+
return fmt.Errorf("loadRegistrySecret failed to fill registry secret: %w", err)
163158
}
164159
return nil
165160
}
@@ -168,11 +163,11 @@ func (actionHandler *ActionHandler) loadRegistryFromSessionObj() (apitypes.Conta
168163
regInfo := actionHandler.sessionObj.Command.Args[apitypes.RegistryInfoArgKey].(map[string]interface{})
169164
regInfoBytes, err := json.Marshal(regInfo)
170165
if err != nil {
171-
return nil, fmt.Errorf("scanRegistriesV2 failed to marshal command arg with err %v", err)
166+
return nil, fmt.Errorf("scanRegistriesV2 failed to marshal command arg: %w", err)
172167
}
173168
imageRegistry, err := apitypes.UnmarshalRegistry(regInfoBytes)
174169
if err != nil {
175-
return nil, fmt.Errorf("scanRegistriesV2 failed to unmarshal command with err %v", err)
170+
return nil, fmt.Errorf("scanRegistriesV2 failed to unmarshal command: %w", err)
176171
}
177172
return imageRegistry, nil
178173
}
@@ -206,7 +201,7 @@ func (actionHandler *ActionHandler) getRegistryImageScanCommands(client interfac
206201
}
207202
auth, err := client.GetDockerAuth()
208203
if err != nil {
209-
return nil, fmt.Errorf("failed to get docker auth with err %v", err)
204+
return nil, fmt.Errorf("failed to get docker auth: %w", err)
210205
}
211206
registryScanCommand.Credentialslist = append(registryScanCommand.Credentialslist, *auth)
212207
registryScanCMDList = append(registryScanCMDList, &apis.RegistryScanCommand{
@@ -240,7 +235,7 @@ func (actionHandler *ActionHandler) scanImage(ctx context.Context) error {
240235
cmd := actionHandler.getImageScanCommand(containerData, imageScanConfig)
241236

242237
if err := sendCommandToScanner(ctx, actionHandler.config, cmd, actionHandler.sessionObj.Command.CommandName); err != nil {
243-
return fmt.Errorf("failed to send command to scanner with err %v", err)
238+
return fmt.Errorf("failed to send command to scanner: %w", err)
244239
}
245240
return nil
246241
}
@@ -253,6 +248,21 @@ func (actionHandler *ActionHandler) scanApplicationProfile(ctx context.Context)
253248
return errors.New("kubevuln is not enabled")
254249
}
255250

251+
// get the pod from the session object
252+
pod, _ := actionHandler.sessionObj.Command.Args[utils.ArgsPod].(*corev1.Pod)
253+
254+
var authConfigs []dockerregistry.AuthConfig
255+
if pod != nil {
256+
// build a list of secrets from the registry secrets
257+
secrets, err := cloudsupport.GetImageRegistryCredentials(actionHandler.k8sAPI, "", pod)
258+
if err != nil {
259+
return fmt.Errorf("failed to get registry credentials: %w", err)
260+
}
261+
for i := range secrets {
262+
authConfigs = append(authConfigs, secrets[i]...)
263+
}
264+
}
265+
256266
span.AddEvent("scanning", trace.WithAttributes(attribute.String("wlid", actionHandler.wlid)))
257267
cmd := &apis.WebsocketScanCommand{
258268
Wlid: actionHandler.wlid,
@@ -261,13 +271,14 @@ func (actionHandler *ActionHandler) scanApplicationProfile(ctx context.Context)
261271
"name": actionHandler.sessionObj.Command.Args[utils.ArgsName],
262272
"namespace": actionHandler.sessionObj.Command.Args[utils.ArgsNamespace],
263273
},
274+
Credentialslist: authConfigs,
264275
},
265276
}
266277

267278
prepareSessionChain(actionHandler.sessionObj, cmd, actionHandler)
268279

269280
if err := sendCommandToScanner(ctx, actionHandler.config, cmd, apis.TypeScanApplicationProfile); err != nil {
270-
return fmt.Errorf("failed to send command to scanner with err %v", err)
281+
return fmt.Errorf("failed to send command to scanner: %w", err)
271282
}
272283
return nil
273284
}
@@ -344,7 +355,7 @@ func getImageScanConfig(k8sAPI *k8sinterface.KubernetesApi, namespace string, po
344355

345356
if pod != nil {
346357
// TODO: this should not happen every scan
347-
// build a list of secrets from the the registry secrets
358+
// build a list of secrets from the registry secrets
348359
secrets, err := cloudsupport.GetImageRegistryCredentials(k8sAPI, imageTag, pod)
349360
if err != nil {
350361
return nil, err
@@ -398,7 +409,7 @@ func sendWorkloadWithCredentials(ctx context.Context, scanUrl *url.URL, command
398409
}
399410

400411
if err != nil {
401-
return fmt.Errorf("failed to marshal websocketScanCommand with err %v", err)
412+
return fmt.Errorf("failed to marshal websocketScanCommand: %w", err)
402413
}
403414
if command.GetWlid() == "" {
404415
logger.L().Debug(fmt.Sprintf("sending scan command to kubevuln: %s", string(jsonScannerC)))

0 commit comments

Comments
 (0)