|
5 | 5 | "encoding/json"
|
6 | 6 | "errors"
|
7 | 7 | "fmt"
|
| 8 | + "github.com/armosec/registryx/interfaces" |
| 9 | + "github.com/armosec/registryx/registryclients" |
| 10 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
8 | 11 | "net/url"
|
9 | 12 | "strings"
|
10 | 13 | "time"
|
@@ -156,6 +159,102 @@ func (actionHandler *ActionHandler) scanRegistries(ctx context.Context, sessionO
|
156 | 159 | return actionHandler.scanRegistry(ctx, registryScan, sessionObj)
|
157 | 160 | }
|
158 | 161 |
|
| 162 | +func (actionHandler *ActionHandler) scanRegistriesV2(ctx context.Context, sessionObj *utils.SessionObj) error { |
| 163 | + ctx, span := otel.Tracer("").Start(ctx, "actionHandler.scanRegistries") |
| 164 | + defer span.End() |
| 165 | + |
| 166 | + if !actionHandler.config.Components().Kubevuln.Enabled { |
| 167 | + return errors.New("kubevuln is not enabled") |
| 168 | + } |
| 169 | + |
| 170 | + // send change status of registry to scanning |
| 171 | + imageRegistry, err := actionHandler.loadRegistryFromSessionObj(sessionObj) |
| 172 | + if err != nil { |
| 173 | + return fmt.Errorf("scanRegistriesV2 failed to load registry from sessionObj with err %v", err) |
| 174 | + } |
| 175 | + |
| 176 | + if err = actionHandler.loadRegistrySecret(ctx, sessionObj, imageRegistry); err != nil { |
| 177 | + return fmt.Errorf("scanRegistriesV2 failed to load secret with err %v", err) |
| 178 | + } |
| 179 | + |
| 180 | + client, err := registryclients.GetRegistryClient(imageRegistry) |
| 181 | + if err != nil { |
| 182 | + return fmt.Errorf("scanRegistriesV2 failed to get registry client with err %v", err) |
| 183 | + } |
| 184 | + |
| 185 | + images, err := client.GetImagesToScan(ctx) |
| 186 | + if err != nil { |
| 187 | + return fmt.Errorf("scanRegistriesV2 failed to get registry images to scan with err %v", err) |
| 188 | + } |
| 189 | + |
| 190 | + registryScanCMDList := actionHandler.getRegistryImageScanCommands(sessionObj, client, imageRegistry, images) |
| 191 | + sessionObj.Reporter.SendDetails(fmt.Sprintf("sending %d images from registry %v to vuln scan", len(registryScanCMDList), imageRegistry), actionHandler.sendReport) |
| 192 | + |
| 193 | + return sendAllImagesToRegistryScan(ctx, actionHandler.config, registryScanCMDList) |
| 194 | +} |
| 195 | + |
| 196 | +func (actionHandler *ActionHandler) loadRegistrySecret(ctx context.Context, sessionObj *utils.SessionObj, imageRegistry apitypes.ContainerImageRegistry) error { |
| 197 | + secretName := sessionObj.Command.Args[apitypes.RegistrySecretNameArgKey].(string) |
| 198 | + secret, err := actionHandler.k8sAPI.KubernetesClient.CoreV1().Secrets(apitypes.KubescapeNamespace).Get(ctx, secretName, metav1.GetOptions{}) |
| 199 | + if err != nil { |
| 200 | + return fmt.Errorf("loadRegistrySecret failed to get secret with err %v", err) |
| 201 | + } |
| 202 | + |
| 203 | + var secretMap map[string]string |
| 204 | + err = json.Unmarshal(secret.Data[apitypes.RegistryAuthFieldInSecret], &secretMap) |
| 205 | + if err != nil { |
| 206 | + return fmt.Errorf("loadRegistrySecret failed to unmarshal registry secret with err %v", err) |
| 207 | + } |
| 208 | + err = imageRegistry.FillSecret(secretMap) |
| 209 | + if err != nil { |
| 210 | + return fmt.Errorf("loadRegistrySecret failed to fill registry secret with err %v", err) |
| 211 | + } |
| 212 | + return nil |
| 213 | +} |
| 214 | + |
| 215 | +func (actionHandler *ActionHandler) loadRegistryFromSessionObj(sessionObj *utils.SessionObj) (apitypes.ContainerImageRegistry, error) { |
| 216 | + regInfo := sessionObj.Command.Args[apitypes.RegistryInfoArgKey].(map[string]interface{}) |
| 217 | + regInfoBytes, err := json.Marshal(regInfo) |
| 218 | + if err != nil { |
| 219 | + return nil, fmt.Errorf("scanRegistriesV2 failed to marshal command arg with err %v", err) |
| 220 | + } |
| 221 | + imageRegistry, err := apitypes.UnmarshalRegistry(regInfoBytes) |
| 222 | + if err != nil { |
| 223 | + return nil, fmt.Errorf("scanRegistriesV2 failed to unmarshal command with err %v", err) |
| 224 | + } |
| 225 | + return imageRegistry, nil |
| 226 | +} |
| 227 | + |
| 228 | +func (actionHandler *ActionHandler) getRegistryImageScanCommands(sessionObj *utils.SessionObj, client interfaces.RegistryClient, imageRegistry apitypes.ContainerImageRegistry, images map[string]string) []*apis.RegistryScanCommand { |
| 229 | + registryScanCMDList := make([]*apis.RegistryScanCommand, 0, len(images)) |
| 230 | + for image, tag := range images { |
| 231 | + repository := image |
| 232 | + parts := strings.Split(image, "/") |
| 233 | + if len(parts) > 1 { |
| 234 | + repository = parts[1] |
| 235 | + } |
| 236 | + registryScanCommand := &apis.ImageScanParams{ |
| 237 | + ParentJobID: sessionObj.Reporter.GetJobID(), |
| 238 | + JobID: uuid.NewString(), |
| 239 | + ImageTag: image + ":" + tag, |
| 240 | + Session: apis.SessionChain{ActionTitle: "vulnerability-scan", JobIDs: make([]string, 0), Timestamp: sessionObj.Reporter.GetTimestamp()}, |
| 241 | + Args: map[string]interface{}{ |
| 242 | + identifiers.AttributeRegistryName: imageRegistry.GetDisplayName(), |
| 243 | + identifiers.AttributeRepository: repository, |
| 244 | + identifiers.AttributeTag: tag, |
| 245 | + identifiers.AttributeUseHTTP: false, |
| 246 | + identifiers.AttributeSkipTLSVerify: false, |
| 247 | + identifiers.AttributeSensor: imageRegistry.GetBase().ClusterName, |
| 248 | + }, |
| 249 | + } |
| 250 | + registryScanCommand.Credentialslist = append(registryScanCommand.Credentialslist, *client.GetDockerAuth()) |
| 251 | + registryScanCMDList = append(registryScanCMDList, &apis.RegistryScanCommand{ |
| 252 | + ImageScanParams: *registryScanCommand, |
| 253 | + }) |
| 254 | + } |
| 255 | + return registryScanCMDList |
| 256 | +} |
| 257 | + |
159 | 258 | func (actionHandler *ActionHandler) loadRegistryScan(ctx context.Context, sessionObj *utils.SessionObj) (*registryScan, error) {
|
160 | 259 | registryScan := NewRegistryScan(actionHandler.config, actionHandler.k8sAPI)
|
161 | 260 | if regName, authMethodType := actionHandler.parseRegistryName(sessionObj); regName != "" {
|
|
0 commit comments