diff --git a/packages/amazon-vpc-cni-plugins/Cargo.toml b/packages/amazon-vpc-cni-plugins/Cargo.toml index 707e31895..35378ca80 100644 --- a/packages/amazon-vpc-cni-plugins/Cargo.toml +++ b/packages/amazon-vpc-cni-plugins/Cargo.toml @@ -13,8 +13,8 @@ path = "../packages.rs" releases-url = "https://github.com/aws/amazon-ecs-agent/commits/master/amazon-vpc-cni-plugins" [[package.metadata.build-package.external-files]] -url = "https://github.com/aws/amazon-vpc-cni-plugins/archive/be5214353252f8315a1341f4df9ffbd8cf69000c/amazon-vpc-cni-plugins.tar.gz" -sha512 = "b1aa61d0000ff732dae67213cea2eac49363c048416716e27f36b2b43f6227db8b15ead27c43c5fd623569a49572cb6b2149c86d69363f75cec4620ddc9ef47b" +url = "https://github.com/aws/amazon-vpc-cni-plugins/archive/a4e9ac076709c882a904afabc4c24c7700600f6b/amazon-vpc-cni-plugins.tar.gz" +sha512 = "b2cc6db9462e9fb27eb2599cbc9eba7e9dae18b76af9137c99e69ee0f07dec72e2358740a3e0b873c7fe8ed004a2d47a48b4159769aaebc7641f0ec6aa00d613" [build-dependencies] glibc = { path = "../glibc" } diff --git a/packages/amazon-vpc-cni-plugins/amazon-vpc-cni-plugins.spec b/packages/amazon-vpc-cni-plugins/amazon-vpc-cni-plugins.spec index 801046deb..28f76d0e9 100644 --- a/packages/amazon-vpc-cni-plugins/amazon-vpc-cni-plugins.spec +++ b/packages/amazon-vpc-cni-plugins/amazon-vpc-cni-plugins.spec @@ -1,7 +1,7 @@ %global vpccni_goproject github.com/aws %global vpccni_gorepo amazon-vpc-cni-plugins %global vpccni_goimport %{vpccni_goproject}/%{vpccni_gorepo} -%global vpccni_gitrev be5214353252f8315a1341f4df9ffbd8cf69000c +%global vpccni_gitrev a4e9ac076709c882a904afabc4c24c7700600f6b %global vpccni_gover 1.3 Name: %{_cross_os}amazon-vpc-cni-plugins diff --git a/packages/ecs-agent/Cargo.toml b/packages/ecs-agent/Cargo.toml index 8fc216cc6..17bb90363 100644 --- a/packages/ecs-agent/Cargo.toml +++ b/packages/ecs-agent/Cargo.toml @@ -13,8 +13,9 @@ path = "../packages.rs" releases-url = "https://github.com/aws/amazon-ecs-agent/releases" [[package.metadata.build-package.external-files]] -url = "https://github.com/aws/amazon-ecs-agent/archive/v1.91.2/amazon-ecs-agent-1.91.2.tar.gz" -sha512 = "c079dc22ee60ff0701d9a66f59add26fcab02baae36c72f98e8397ea6747a1858c4df2cada9ed3e2af3657d65920d2495b0b94c88dfbd573a6485ce2a4d6a816" +# Verify the Git submodule commit of amazon-vpc-cni-plugins matches what is shipped in ../amazon-vpc-cni-plugins +url = "https://github.com/aws/amazon-ecs-agent/archive/v1.101.1/amazon-ecs-agent-1.101.1.tar.gz" +sha512 = "cc65271442a918c66baa4e01a4bd2663f024bfa4fbfc71a277407d0cf75702eb336d398657d24ed358d5138dd504a20290ab7e350f6a4a63037b27f21a8a0695" [build-dependencies] glibc = { path = "../glibc" } diff --git a/packages/ecs-agent/ecs-agent.spec b/packages/ecs-agent/ecs-agent.spec index 66de4854a..7f7993863 100644 --- a/packages/ecs-agent/ecs-agent.spec +++ b/packages/ecs-agent/ecs-agent.spec @@ -2,10 +2,10 @@ %global agent_gorepo amazon-ecs-agent %global agent_goimport %{agent_goproject}/%{agent_gorepo} -%global agent_gover 1.91.2 +%global agent_gover 1.101.1 # git rev-parse --short=8 -%global agent_gitrev b7e96508 +%global agent_gitrev 64b39fa7 # Construct reproducible tar archives # See https://reproducible-builds.org/docs/archives/ diff --git a/sources/host-ctr/cmd/host-ctr/ecr.go b/sources/host-ctr/cmd/host-ctr/ecr.go new file mode 100644 index 000000000..ccefe6ec0 --- /dev/null +++ b/sources/host-ctr/cmd/host-ctr/ecr.go @@ -0,0 +1,256 @@ +package main + +import ( + "context" + "encoding/base64" + "errors" + "fmt" + "regexp" + "strings" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/ecr" + "github.com/aws/aws-sdk-go-v2/service/ecrpublic" + "github.com/containerd/containerd" + "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/log" +) + +// specialRegionEndpoints supports regions not yet included in the AWS GO SDK. +// ap-southeast-7 is currently in the SDK but persisted here for future region builds. +var specialRegionEndpoints = map[string]string{ + "ap-southeast-7": "https://api.ecr.ap-southeast-7.amazonaws.com", +} + +// ecrPrivateHostPattern matches ECR private registry hostnames. +// Capture groups: [1] = account (unused), [2] = "-fips" or empty, [3] = region +// +// ECR hostname pattern also used in the ecr-credential-provider: +// https://github.com/kubernetes/cloud-provider-aws/blob/d1c7c02d2da22e87175802ec94c73bd8871691bc/cmd/ecr-credential-provider/main.go#L46 +// +// Example hostnames: +// - 777777777777.dkr.ecr.us-west-2.amazonaws.com +// - 777777777777.dkr.ecr-fips.us-west-2.amazonaws.com +// - 777777777777.dkr.ecr.cn-north-1.amazonaws.com.cn +var ecrPrivateHostPattern = regexp.MustCompile( + `^(\d{12})` + // [1] account ID (12 digits) + `\.dkr[\.\-]ecr` + // .dkr.ecr or .dkr-ecr + `(\-fips)?` + // [2] optional -fips + `\.([a-zA-Z0-9][a-zA-Z0-9-_]*)` + // [3] region + `\.(?:` + // domain suffix (non-capturing) + `amazonaws\.(?:com(?:\.cn)?|eu)|` + // amazonaws.com, .com.cn, .eu + `on\.(?:aws|amazonwebservices\.com\.cn)|` + // on.aws, on.amazonwebservices.com.cn + `sc2s\.sgov\.gov|` + // Isolated regions + `c2s\.ic\.gov|` + + `cloud\.adc-e\.uk|` + + `csp\.hci\.ic\.gov` + + `)$`) + +const ecrPublicHost = "public.ecr.aws" +const ecrPublicRegion = "us-east-1" + +// Regions with FIPS endpoints (see "FIPS" entries at the link below) +// https://docs.aws.amazon.com/general/latest/gr/ecr.html +var fipsSupportedEcrRegionSet = map[string]bool{ + "us-east-1": true, + "us-east-2": true, + "us-west-1": true, + "us-west-2": true, + "us-gov-east-1": true, + "us-gov-west-1": true, +} + +// parsedECR contains the parsed components of an ECR private registry hostname. +type parsedECR struct { + Region string + Fips bool +} + +// extractHostFromRef extracts the registry hostname from an image reference. +func extractHostFromRef(ref string) (string, error) { + parsed, err := reference.Parse(ref) + if err != nil { + return "", fmt.Errorf("failed to parse reference: %w", err) + } + return parsed.Hostname(), nil +} + +// parseECRHost parses an ECR private registry hostname and extracts +// the region and whether it's a FIPS endpoint. +func parseECRHost(host string) (*parsedECR, error) { + matches := ecrPrivateHostPattern.FindStringSubmatch(host) + if matches == nil { + return nil, fmt.Errorf("not a valid ECR host: %s", host) + } + + isFips := matches[2] == "-fips" + region := matches[3] + + if isFips { + if _, ok := fipsSupportedEcrRegionSet[region]; !ok { + return nil, fmt.Errorf("invalid FIPS region: %s", region) + } + } + + return &parsedECR{Region: region, Fips: isFips}, nil +} + +// isECRPrivateRef returns true if ref points to an ECR private registry. +func isECRPrivateRef(ref string) bool { + host, err := extractHostFromRef(ref) + if err != nil { + return false + } + return ecrPrivateHostPattern.MatchString(host) +} + +// decodeECRToken decodes a base64 ECR token and returns username and password. +func decodeECRToken(token *string) (string, string, error) { + if token == nil { + return "", "", errors.New("missing authorization token") + } + + authToken, err := base64.StdEncoding.DecodeString(*token) + if err != nil { + return "", "", fmt.Errorf("failed to decode authorization token: %w", err) + } + + if len(authToken) == 0 { + return "", "", errors.New("authorization token is empty after base64 decoding") + } + + tokens := strings.SplitN(string(authToken), ":", 2) + if len(tokens) != 2 { + return "", "", errors.New("invalid authorization token format") + } + + return tokens[0], tokens[1], nil +} + +// getECRPrivateCredentials fetches authorization credentials for private ECR registries. +func getECRPrivateCredentials(ctx context.Context, region string, useFIPS bool) (string, string, error) { + cfgOpts := []func(*config.LoadOptions) error{config.WithRegion(region)} + + if useFIPS { + cfgOpts = append(cfgOpts, config.WithUseFIPSEndpoint(aws.FIPSEndpointStateEnabled)) + } + + cfg, err := config.LoadDefaultConfig(ctx, cfgOpts...) + if err != nil { + return "", "", fmt.Errorf("failed to load AWS config for region %s: %w", region, err) + } + + log.G(ctx).WithField("region", region).WithField("fips", useFIPS).Info("setting up ECR client") + + var client *ecr.Client + if endpoint, ok := specialRegionEndpoints[region]; ok { + log.G(ctx).WithField("region", region).WithField("endpoint", endpoint).Info("using special region endpoint") + client = ecr.NewFromConfig(cfg, func(o *ecr.Options) { + o.BaseEndpoint = aws.String(endpoint) + }) + } else { + client = ecr.NewFromConfig(cfg) + } + + output, err := client.GetAuthorizationToken(ctx, &ecr.GetAuthorizationTokenInput{}) + if err != nil { + return "", "", fmt.Errorf("failed to get ECR authorization token: %w", err) + } + + if output == nil || len(output.AuthorizationData) == 0 { + return "", "", fmt.Errorf("no authorization data returned") + } + + return decodeECRToken(output.AuthorizationData[0].AuthorizationToken) +} + +// getECRPublicCredentials fetches authorization credentials for ECR Public registries using us-east-1. +func getECRPublicCredentials(ctx context.Context) (string, string, error) { + cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(ecrPublicRegion)) + if err != nil { + return "", "", fmt.Errorf("failed to load AWS config for ECR Public (%s): %w", ecrPublicRegion, err) + } + + client := ecrpublic.NewFromConfig(cfg) + output, err := client.GetAuthorizationToken(ctx, &ecrpublic.GetAuthorizationTokenInput{}) + if err != nil { + return "", "", fmt.Errorf("failed to get ECR Public authorization token: %w", err) + } + + if output == nil || output.AuthorizationData == nil { + return "", "", errors.New("missing authorization data") + } + + return decodeECRToken(output.AuthorizationData.AuthorizationToken) +} + +// withECRPrivateResolver creates a resolver for private ECR registries. +// Returns an error if credentials cannot be obtained - private ECR requires +// authentication. +func withECRPrivateResolver(ctx context.Context, ref string) containerd.RemoteOpt { + return func(_ *containerd.Client, c *containerd.RemoteContext) error { + ecrHost, err := extractHostFromRef(ref) + if err != nil { + return fmt.Errorf("failed to extract host from reference: %w", err) + } + + parsed, err := parseECRHost(ecrHost) + if err != nil { + return fmt.Errorf("failed to parse ECR host: %w", err) + } + + username, password, err := getECRPrivateCredentials(ctx, parsed.Region, parsed.Fips) + if err != nil { + return fmt.Errorf("failed to get private ECR credentials for region %s: %w", parsed.Region, err) + } + + authOpt := docker.WithAuthCreds(func(host string) (string, string, error) { + if host != ecrHost { + return "", "", fmt.Errorf("ecr-private: unexpected host %s, expected %s", host, ecrHost) + } + return username, password, nil + }) + authorizer := docker.NewDockerAuthorizer(authOpt) + c.Resolver = docker.NewResolver(docker.ResolverOptions{ + Hosts: registryHosts(nil, &authorizer), + }) + + log.G(ctx).WithField("ref", ref).WithField("region", parsed.Region).Info("pulling private ECR image") + return nil + } +} + +// withECRPublicResolver creates a resolver for ECR Public registries. +// Falls back to unauthenticated pull if credentials cannot be obtained since +// ECR Public supports anonymous access. +func withECRPublicResolver(ctx context.Context, ref string, registryConfig *RegistryConfig, defaultResolver containerd.RemoteOpt) containerd.RemoteOpt { + if registryConfig != nil { + if _, found := registryConfig.Credentials[ecrPublicHost]; found { + return defaultResolver + } + } + + username, password, err := getECRPublicCredentials(ctx) + if err != nil { + log.G(ctx).WithError(err).Warn("ecr-public: failed to get credentials, falling back to unauthenticated pull") + return defaultResolver + } + + authOpt := docker.WithAuthCreds(func(host string) (string, string, error) { + if host != ecrPublicHost { + return "", "", fmt.Errorf("ecr-public: unexpected host %s, expected %s", host, ecrPublicHost) + } + return username, password, nil + }) + authorizer := docker.NewDockerAuthorizer(authOpt) + + return func(_ *containerd.Client, c *containerd.RemoteContext) error { + c.Resolver = docker.NewResolver(docker.ResolverOptions{ + Hosts: registryHosts(registryConfig, &authorizer), + }) + log.G(ctx).WithField("ref", ref).Info("pulling from ECR Public") + return nil + } +} diff --git a/sources/host-ctr/cmd/host-ctr/main.go b/sources/host-ctr/cmd/host-ctr/main.go index 7070cd673..65ac0fe63 100644 --- a/sources/host-ctr/cmd/host-ctr/main.go +++ b/sources/host-ctr/cmd/host-ctr/main.go @@ -2,22 +2,16 @@ package main import ( "context" - "encoding/base64" "encoding/json" "fmt" "io" "math/rand" "os" "os/signal" - "regexp" "strings" "syscall" "time" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/service/ecrpublic" - "github.com/awslabs/amazon-ecr-containerd-resolver/ecr" "github.com/containerd/containerd" "github.com/containerd/containerd/api/types/runc/options" "github.com/containerd/containerd/cio" @@ -34,44 +28,6 @@ import ( "github.com/urfave/cli/v2" ) -// Expecting to match ECR image names of the form: -// -// Example 1: 777777777777.dkr.ecr.us-west-2.amazonaws.com/my_image:latest -// Example 2: 777777777777.dkr.ecr.cn-north-1.amazonaws.com.cn/my_image:latest -// Example 3: 777777777777.dkr.ecr.eu-isoe-west-1.cloud.adc-e.uk/my_image:latest -// Example 4: 777777777777.dkr.ecr-fips.us-west-2.amazonaws.com/my_image:latest - -// ECR hostname pattern also used in the ecr-credential-provider: -// https://github.com/kubernetes/cloud-provider-aws/blob/212135d0d7b448cd34e2e11e5e81f59e3e6c2d7a/cmd/ecr-credential-provider/main.go#L45 -var ecrRegex = regexp.MustCompile(`^(\d{12})\.dkr[\.\-]ecr(-fips)?\.([a-zA-Z0-9][a-zA-Z0-9-_]*)\.(amazonaws(\.com(?:\.cn)?|\.eu)|on\.(?:aws|amazonwebservices\.com\.cn)|sc2s\.sgov\.gov|c2s\.ic\.gov|cloud\.adc-e\.uk|csp\.hci\.ic\.gov).*$`) - -// A set of currently supported ECR regions which are not yet present in the golang SDK -var ecrRefPrefixMapping = map[string]string{ - "ap-southeast-7": "ecr.aws/arn:aws:ecr:ap-southeast-7:", - "mx-central-1": "ecr.aws/arn:aws:ecr:mx-central-1:", - "ap-east-2": "ecr.aws/arn:aws:ecr:ap-east-2:", - "ap-southeast-6": "ecr.aws/arn:aws:ecr:ap-southeast-6:", - "us-northeast-1": "ecr.aws/arn:aws:ecr:us-northeast-1:", - "eu-isoe-west-1": "ecr.aws/arn:aws-iso-e:ecr:eu-isoe-west-1:", - "eusc-de-east-1": "ecr.aws/arn:aws-eusc:ecr:eusc-de-east-1:", - "us-iso-east-1": "ecr.aws/arn:aws-iso:ecr:us-iso-east-1:", - "us-iso-west-1": "ecr.aws/arn:aws-iso:ecr:us-iso-west-1:", - "us-isob-east-1": "ecr.aws/arn:aws-iso-b:ecr:us-isob-east-1:", - "us-isob-west-1": "ecr.aws/arn:aws-iso-b:ecr:us-isob-west-1:", - "us-isof-south-1": "ecr.aws/arn:aws-iso-f:ecr:us-isof-south-1:", - "us-isof-east-1": "ecr.aws/arn:aws-iso-f:ecr:us-isof-east-1:", -} - -// A set of the currently supported FIPS regions for ECR: https://docs.aws.amazon.com/general/latest/gr/ecr.html -var fipsSupportedEcrRegionSet = map[string]bool{ - "us-east-1": true, - "us-east-2": true, - "us-west-1": true, - "us-west-2": true, - "us-gov-east-1": true, - "us-gov-west-1": true, -} - const ( // The maximum size of an image label. imageLabelMaxSize = 4096 @@ -339,22 +295,13 @@ func runCtr(containerdSocket string, namespace string, containerID string, sourc } defer client.Close() - // Check if the image source is an ECR image. If it is, then we need to handle it with the ECR resolver. - isECRImage := ecrRegex.MatchString(source) var img containerd.Image emptyLabels := make(map[string]string) - if isECRImage { - img, err = fetchECRImage(ctx, source, client, registryConfigPath, useCachedImage, emptyLabels) - if err != nil { - return err - } - } else { - img, err = fetchImage(ctx, source, client, registryConfigPath, useCachedImage, emptyLabels) - if err != nil { - log.G(ctx).WithField("ref", source).Error(err) - return err - } + img, err = fetchImage(ctx, source, client, registryConfigPath, useCachedImage, emptyLabels) + if err != nil { + log.G(ctx).WithField("ref", source).Error(err) + return err } prefix := cType.Prefix() @@ -580,19 +527,10 @@ func pullImageOnly(containerdSocket string, namespace string, source string, reg } defer client.Close() - // Check if the image source is an ECR image. If it is, then we need to handle it with the ECR resolver. - isECRImage := ecrRegex.MatchString(source) - if isECRImage { - _, err = fetchECRImage(ctx, source, client, registryConfigPath, useCachedImage, labels) - if err != nil { - return err - } - } else { - _, err = fetchImage(ctx, source, client, registryConfigPath, useCachedImage, labels) - if err != nil { - log.G(ctx).WithField("ref", source).Error(err) - return err - } + _, err = fetchImage(ctx, source, client, registryConfigPath, useCachedImage, labels) + if err != nil { + log.G(ctx).WithField("ref", source).Error(err) + return err } return nil @@ -650,162 +588,6 @@ func cleanUp(containerdSocket string, namespace string, containerID string) erro return nil } -type parsedECR struct { - Region string - Account string - RepoPath string - Fips bool -} - -// parseImageURIAsECR mimics the parsing in ecr.ParseImageURI but only returns metadata pertaining -// to the parsed URI. -func parseImageURIAsECR(input string) (*parsedECR, error) { - matches := ecrRegex.FindStringSubmatch(input) - - if len(matches) < 3 { - return nil, fmt.Errorf("invalid image URI: %s", input) - } - account := matches[1] - - // Need to include the full repository path and the imageID (e.g. /eks/image-name:tag) - tokens := strings.SplitN(input, "/", 2) - if len(tokens) != 2 { - return nil, fmt.Errorf("invalid image URI: %s", input) - } - fullRepoPath := tokens[len(tokens)-1] - // Run simple checks on the provided repository. - switch { - case - // Must not be empty - fullRepoPath == "", - // Must not have a partial/unsupplied label - strings.HasSuffix(fullRepoPath, ":"), - // Must not have a partial/unsupplied digest specifier - strings.HasSuffix(fullRepoPath, "@"): - return nil, errors.New("incomplete reference provided") - } - - isFips := matches[2] == "-fips" - region := matches[3] - - return &parsedECR{ - Region: region, - Account: account, - RepoPath: fullRepoPath, - Fips: isFips, - }, nil -} - -// Metadata for specially-treated ECR URIs -type specialRegions struct { - // region => domain mappings - EcrRefPrefixMappings map[string]string - // The set of regions supporting FIPS - FipsSupportedEcrRegions map[string]bool -} - -// parseImageURISpecialRegions mimics the parsing in ecr.ParseImageURI but -// constructs the canonical ECR references while skipping certain checks. -// We only do this for special regions that are not yet supported by the aws-go-sdk and for ECR FIPS endpoints. -// Referenced source: https://github.com/awslabs/amazon-ecr-containerd-resolver/blob/a5058cf091f4fc573813a032db37a9820952f1f9/ecr/ref.go#L70-L71 -func parseImageURISpecialRegions(input string, specialRegions specialRegions) (ecr.ECRSpec, error) { - parsedECR, err := parseImageURIAsECR(input) - if err != nil { - return ecr.ECRSpec{}, err - } - - // Return early if the FIPS endpoint is being used. amazon-ecr-containerd-resolver doesn't yet support FIPS urls: - // https://github.com/awslabs/amazon-ecr-containerd-resolver/blob/7b72333e780f5a5168936eae79fb89448e2f2a8f/ecr/ref.go#L43 - // The ecr-prefix helper for admin and control host containers will have already accounted for setting this endpoint - // if the region has FIPS support. - if parsedECR.Fips { - _, isFips := specialRegions.FipsSupportedEcrRegions[parsedECR.Region] - if !isFips { - return ecr.ECRSpec{}, fmt.Errorf("%s: %s", "invalid FIPS region", parsedECR.Region) - } - ecrRefPrefix := fmt.Sprintf("ecr.aws/arn:aws:ecr-fips:%s:", parsedECR.Region) - return ecr.ParseRef(fmt.Sprintf("%s%s:repository/%s", ecrRefPrefix, parsedECR.Account, parsedECR.RepoPath)) - } - - // Get the ECR image reference prefix from the AWS region - ecrRefPrefix, ok := specialRegions.EcrRefPrefixMappings[parsedECR.Region] - if !ok { - return ecr.ECRSpec{}, fmt.Errorf("%s: %s", "invalid region in internal mapping", parsedECR.Region) - } - - return ecr.ParseRef(fmt.Sprintf("%s%s:repository/%s", ecrRefPrefix, parsedECR.Account, parsedECR.RepoPath)) -} - -// fetchECRRef attempts to resolve the ECR reference from an input source string. -// We check special regions handling first, then fall back to standard parsing if not found. -func fetchECRRef(ctx context.Context, input string, specialRegions specialRegions) (ecr.ECRSpec, error) { - var spec ecr.ECRSpec - // First check if this is a special region that needs custom handling - spec, err := parseImageURISpecialRegions(input, specialRegions) - if err == nil { - return spec, nil - } - log.G(ctx).WithError(err).WithField("source", input).Info("not a special ECR reference, trying standard parsing") - - // Fall back to standard aws-sdk-go-v2 parsing for other cases - spec, err = ecr.ParseImageURI(input) - if err == nil { - return spec, nil - } - - log.G(ctx).WithError(err).WithField("source", input).Error("failed to parse ECR reference") - return ecr.ECRSpec{}, errors.Wrap(err, "could not parse ECR reference") -} - -// fetchECRImage does some additional conversions before resolving the image reference and fetches the image. -func fetchECRImage(ctx context.Context, source string, client *containerd.Client, registryConfigPath string, fetchCachedImageIfExist bool, labels map[string]string) (containerd.Image, error) { - specialRegions := specialRegions{ - EcrRefPrefixMappings: ecrRefPrefixMapping, - FipsSupportedEcrRegions: fipsSupportedEcrRegionSet, - } - ecrRef, err := fetchECRRef(ctx, source, specialRegions) - if err != nil { - return nil, err - } - ref := ecrRef.Canonical() - - log.G(ctx). - WithField("ref", ref). - WithField("source", source). - Debug("parsed ECR reference from URI") - - img, err := fetchImage(ctx, ref, client, registryConfigPath, fetchCachedImageIfExist, labels) - if err != nil { - log.G(ctx).WithField("ref", ref).Error(err) - return nil, err - } - - // When the image is from ECR, the image reference will be converted from - // its ref format. This is of the form of `"ecr.aws/" + ECR repository ARN + - // label/digest`. - // - // See the resolver for details on this format - - // https://github.com/awslabs/amazon-ecr-containerd-resolver. - // - // If the image was pulled from ECR, add `source` ref pointing to the same - // image so other clients can locate it using both `source` and the parsed - // ECR ref. - log.G(ctx). - WithField("ref", ref). - WithField("source", source). - Debug("adding source tag on pulled image") - if err := tagImage(ctx, ref, source, client); err != nil { - log.G(ctx). - WithError(err). - WithField("source", source). - WithField("ref", ref). - Error("failed to add source tag on pulled image") - return nil, err - } - - return img, nil -} - // newContainerdClient creates a new containerd client connected to the specified containerd socket. func newContainerdClient(ctx context.Context, containerdSocket string, namespace string) (*containerd.Client, error) { client, err := containerd.New(containerdSocket, containerd.WithDefaultNamespace(namespace)) @@ -1199,124 +981,23 @@ func pullImage(ctx context.Context, source string, client *containerd.Client, re return img, nil } -// tagImage adds a tag to the image in containerd's metadata storage. -// -// Image tag logic derived from: -// -// https://github.com/containerd/containerd/blob/d80513ee8a6995bc7889c93e7858ddbbc51f063d/cmd/ctr/commands/images/tag.go#L67-L86 -func tagImage(ctx context.Context, imageName string, newImageName string, client *containerd.Client) error { - log.G(ctx).WithField("img", newImageName).Info("tagging image") - // Retrieve image information - imageService := client.ImageService() - image, err := imageService.Get(ctx, imageName) - if err != nil { - return err - } - // Tag with new image name - image.Name = newImageName - // Attempt to create the image first - if _, err = imageService.Create(ctx, image); err != nil { - // The image already exists then delete the original and attempt to create the new one - if errdefs.IsAlreadyExists(err) { - if err = imageService.Delete(ctx, newImageName); err != nil { - return err - } - if _, err = imageService.Create(ctx, image); err != nil { - return err - } - } else { - return err - } - } - return nil -} - // withDynamicResolver provides an initialized resolver for use with ref. func withDynamicResolver(ctx context.Context, ref string, registryConfig *RegistryConfig) containerd.RemoteOpt { - defaultResolver := func(_ *containerd.Client, _ *containerd.RemoteContext) error { return nil } - if registryConfig != nil { - defaultResolver = func(_ *containerd.Client, c *containerd.RemoteContext) error { - resolver := docker.NewResolver(docker.ResolverOptions{ + defaultResolver := func(_ *containerd.Client, c *containerd.RemoteContext) error { + if registryConfig != nil { + c.Resolver = docker.NewResolver(docker.ResolverOptions{ Hosts: registryHosts(registryConfig, nil), }) - c.Resolver = resolver - return nil } + return nil } switch { - // For private ECR registries, we need to use the Amazon ECR resolver. - // Currently we're unable to support image registry configuration with the ECR resolver. - // FIXME Track upstream `amazon-ecr-containerd-resolver` support for image registry configuration. - case strings.HasPrefix(ref, "ecr.aws/"): - return func(_ *containerd.Client, c *containerd.RemoteContext) error { - // Create the Amazon ECR resolver - resolver, err := ecr.NewResolver() - if err != nil { - return errors.Wrap(err, "Failed to create ECR resolver") - } - log.G(ctx).WithField("ref", ref).Info("pulling with Amazon ECR Resolver") - c.Resolver = resolver - return nil - } - // For Amazon ECR Public registries, we should try and fetch credentials before resolving the image reference + case isECRPrivateRef(ref): + return withECRPrivateResolver(ctx, ref) case strings.HasPrefix(ref, "public.ecr.aws/"): - // if we have registryConfig, and the user specified credentials for - // 'public.ecr.aws', then use defaultResolver. - if registryConfig != nil { - if _, found := registryConfig.Credentials["public.ecr.aws"]; found { - return defaultResolver - } - } - - // Try to get credentials for authenticated pulls from ECR Public - // The ECR Public API is only available in us-east-1 today - cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) - if err != nil { - log.G(ctx).Warn("ecr-public: failed to load AWS config, falling back to default resolver (unauthenticated pull)") - return defaultResolver - } - client := ecrpublic.NewFromConfig(cfg) - output, err := client.GetAuthorizationToken(ctx, &ecrpublic.GetAuthorizationTokenInput{}) - if err != nil { - log.G(ctx).Warn("ecr-public: failed to get authorization token, falling back to default resolver (unauthenticated pull)") - return defaultResolver - } - if output == nil || output.AuthorizationData == nil { - log.G(ctx).Warn("ecr-public: missing AuthorizationData in ECR Public GetAuthorizationToken response, falling back to default resolver (unauthenticated pull)") - return defaultResolver - } - authToken, err := base64.StdEncoding.DecodeString(aws.ToString(output.AuthorizationData.AuthorizationToken)) - if err != nil { - log.G(ctx).Warn("ecr-public: unable to decode authorization token, falling back to default resolver (unauthenticated pull)") - return defaultResolver - } - tokens := strings.SplitN(string(authToken), ":", 2) - if len(tokens) != 2 { - log.G(ctx).Warn("ecr-public: invalid credentials decoded from authorization token, falling back to default resolver (unauthenticated pull)") - return defaultResolver - } - // Use the fetched authorization credentials to resolve the image - authOpt := docker.WithAuthCreds(func(host string) (string, string, error) { - // Double-check to make sure the we're doing this for an ECR Public registry - if host != "public.ecr.aws" { - return "", "", errors.New("ecr-public: expected image to start with public.ecr.aws") - } - return tokens[0], tokens[1], nil - }) - authorizer := docker.NewDockerAuthorizer(authOpt) - resolverOpt := docker.ResolverOptions{ - Hosts: registryHosts(registryConfig, &authorizer), - } - - return func(_ *containerd.Client, c *containerd.RemoteContext) error { - resolver := docker.NewResolver(resolverOpt) - log.G(ctx).WithField("ref", ref).Info("pulling from ECR Public") - c.Resolver = resolver - return nil - } + return withECRPublicResolver(ctx, ref, registryConfig, defaultResolver) default: - // For all other registries return defaultResolver } } diff --git a/sources/host-ctr/cmd/host-ctr/main_test.go b/sources/host-ctr/cmd/host-ctr/main_test.go index 1c61483e7..3538cc736 100644 --- a/sources/host-ctr/cmd/host-ctr/main_test.go +++ b/sources/host-ctr/cmd/host-ctr/main_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/aws/aws-sdk-go-v2/config" "github.com/containerd/containerd/remotes/docker" "github.com/stretchr/testify/assert" ) @@ -11,10 +12,10 @@ import ( // Test RegistryHosts with valid endpoints URLs func TestRegistryHosts(t *testing.T) { tests := []struct { - name string - host string - config RegistryConfig - expected []docker.RegistryHost + name string + host string + config RegistryConfig + want []docker.RegistryHost }{ { "HTTP scheme", @@ -144,7 +145,7 @@ func TestRegistryHosts(t *testing.T) { f := registryHosts(&tc.config, nil) result, err := f(tc.host) assert.NoError(t, err) - assert.Equal(t, tc.expected, result) + assert.Equal(t, tc.want, result) }) } } @@ -162,330 +163,92 @@ func TestBadRegistryHosts(t *testing.T) { assert.Error(t, err) } -func TestParseImageURIAsECR(t *testing.T) { +func TestParseECRHost(t *testing.T) { tests := []struct { - name string - ecrImgURI string - expectedErr bool - expectedResult *parsedECR + name string + host string + wantErr bool + wantResult *parsedECR }{ - { - "Parse typical region for normal use-cases", - "777777777777.dkr.ecr.us-west-2.amazonaws.com/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "us-west-2", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse China regions", - "777777777777.dkr.ecr.cn-north-1.amazonaws.com.cn/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "cn-north-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse special region", - "777777777777.dkr.ecr.eu-isoe-west-1.cloud.adc-e.uk/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "eu-isoe-west-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse special region", - "777777777777.dkr.ecr.eusc-de-east-1.amazonaws.eu/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "eusc-de-east-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse special region", - "777777777777.dkr.ecr.us-iso-east-1.c2s.ic.gov/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "us-iso-east-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse special region", - "777777777777.dkr.ecr.us-isob-east-1.sc2s.sgov.gov/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "us-isob-east-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse special region", - "777777777777.dkr.ecr.us-isob-west-1.sc2s.sgov.gov/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "us-isob-west-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse special region", - "777777777777.dkr.ecr.us-isof-east-1.csp.hci.ic.gov/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "us-isof-east-1", - RepoPath: "my_image:latest", - Fips: false, - }, - }, - { - "Parse FIPS region for normal use-cases", - "777777777777.dkr.ecr-fips.us-west-2.amazonaws.com/my_image:latest", - false, - &parsedECR{ - Account: "777777777777", - Region: "us-west-2", - RepoPath: "my_image:latest", - Fips: true, - }, - }, - { - "Fail for no region", - "111111111111.dkr.ecr..amazonaws.com/bottlerocket/container:1.2.3", - true, - nil, - }, - { - "Empty string fails", - "", - true, - nil, - }, + {"us-west-2", "777777777777.dkr.ecr.us-west-2.amazonaws.com", false, &parsedECR{Region: "us-west-2", Fips: false}}, + {"cn-north-1", "777777777777.dkr.ecr.cn-north-1.amazonaws.com.cn", false, &parsedECR{Region: "cn-north-1", Fips: false}}, + {"eu-isoe-west-1", "777777777777.dkr.ecr.eu-isoe-west-1.cloud.adc-e.uk", false, &parsedECR{Region: "eu-isoe-west-1", Fips: false}}, + {"eusc-de-east-1", "777777777777.dkr.ecr.eusc-de-east-1.amazonaws.eu", false, &parsedECR{Region: "eusc-de-east-1", Fips: false}}, + {"us-iso-east-1", "777777777777.dkr.ecr.us-iso-east-1.c2s.ic.gov", false, &parsedECR{Region: "us-iso-east-1", Fips: false}}, + {"us-isob-east-1", "777777777777.dkr.ecr.us-isob-east-1.sc2s.sgov.gov", false, &parsedECR{Region: "us-isob-east-1", Fips: false}}, + {"us-isof-east-1", "777777777777.dkr.ecr.us-isof-east-1.csp.hci.ic.gov", false, &parsedECR{Region: "us-isof-east-1", Fips: false}}, + {"fips us-west-2", "777777777777.dkr.ecr-fips.us-west-2.amazonaws.com", false, &parsedECR{Region: "us-west-2", Fips: true}}, + {"invalid FIPS region", "111111111111.dkr.ecr-fips.eu-west-1.amazonaws.com", true, nil}, + {"empty string", "", true, nil}, + {"non-ECR domain", "111111111111.dkr.ecr.us-west-2.amazonaws.com.example.org", true, nil}, + {"unrecognized domain suffix", "111111111111.dkr.ecr.us-west-2.notamazon.com", true, nil}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - result, err := parseImageURIAsECR(tc.ecrImgURI) - if tc.expectedErr { - // handle error cases - if err == nil { - t.Fail() - } - } else { - // handle happy paths - assert.Equal(t, tc.expectedResult, result) + result, err := parseECRHost(tc.host) + if tc.wantErr { + assert.Error(t, err) + return } + assert.NoError(t, err) + assert.Equal(t, tc.wantResult, result) }) } } -func TestFetchECRRef(t *testing.T) { - specialRegions := specialRegions{ - FipsSupportedEcrRegions: map[string]bool{ - "us-east-1": true, - "us-east-2": true, - "us-west-1": true, - "us-west-2": true, - "us-gov-east-1": true, - "us-gov-west-1": true, - }, - EcrRefPrefixMappings: map[string]string{ - "ap-southeast-7": "ecr.aws/arn:aws:ecr:ap-southeast-7:", - "mx-central-1": "ecr.aws/arn:aws:ecr:mx-central-1:", - "ap-east-2": "ecr.aws/arn:aws:ecr:ap-east-2:", - "ap-southeast-6": "ecr.aws/arn:aws:ecr:ap-southeast-6:", - "us-northeast-1": "ecr.aws/arn:aws:ecr:us-northeast-1:", - "eu-isoe-west-1": "ecr.aws/arn:aws-iso-e:ecr:eu-isoe-west-1:", - "eusc-de-east-1": "ecr.aws/arn:aws-eusc:ecr:eusc-de-east-1:", - "us-iso-east-1": "ecr.aws/arn:aws-iso:ecr:us-iso-east-1:", - "us-iso-west-1": "ecr.aws/arn:aws-iso:ecr:us-iso-west-1:", - "us-isob-east-1": "ecr.aws/arn:aws-iso-b:ecr:us-isob-east-1:", - "us-isob-west-1": "ecr.aws/arn:aws-iso-b:ecr:us-isob-west-1:", - "us-isof-south-1": "ecr.aws/arn:aws-iso-f:ecr:us-isof-south-1:", - "us-isof-east-1": "ecr.aws/arn:aws-iso-f:ecr:us-isof-east-1:", - }, - } +func TestECRRegionHandling(t *testing.T) { tests := []struct { - name string - ecrImgURI string - expectedErr bool - expectedRef string + name string + host string + wantFips bool + wantErr bool }{ - { - "Parse typical region for normal use-cases", - "111111111111.dkr.ecr.us-west-2.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws:ecr:us-west-2:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region", - "111111111111.dkr.ecr.eu-isoe-west-1.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-iso-e:ecr:eu-isoe-west-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region", - "111111111111.dkr.ecr.us-iso-east-1.c2s.ic.gov/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-iso:ecr:us-iso-east-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region", - "111111111111.dkr.ecr.us-isob-east-1.sc2s.sgov.gov/bottlerocket-control:v0.7.17", - false, - "ecr.aws/arn:aws-iso-b:ecr:us-isob-east-1:111111111111:repository/bottlerocket-control:v0.7.17", - }, - { - "Parse special region", - "111111111111.dkr.ecr.us-iso-west-1.c2s.ic.gov/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-iso:ecr:us-iso-west-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region", - "111111111111.dkr.ecr.us-isof-south-1.csp.hci.ic.gov/bottlerocket-control:v0.7.17", - false, - "ecr.aws/arn:aws-iso-f:ecr:us-isof-south-1:111111111111:repository/bottlerocket-control:v0.7.17", - }, - { - "Parse special region", - "111111111111.dkr.ecr.us-isof-east-1.csp.hci.ic.gov/bottlerocket-control:v0.7.17", - false, - "ecr.aws/arn:aws-iso-f:ecr:us-isof-east-1:111111111111:repository/bottlerocket-control:v0.7.17", - }, - { - "Parse special region", - "111111111111.dkr.ecr.eu-isoe-west-1.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-iso-e:ecr:eu-isoe-west-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region ap-east-2", - "111111111111.dkr.ecr.ap-east-2.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws:ecr:ap-east-2:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region ap-southeast-6", - "111111111111.dkr.ecr.ap-southeast-6.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws:ecr:ap-southeast-6:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region us-northeast-1", - "111111111111.dkr.ecr.us-northeast-1.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws:ecr:us-northeast-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region eusc-de-east-1", - "111111111111.dkr.ecr.eusc-de-east-1.amazonaws.eu/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-eusc:ecr:eusc-de-east-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse special region us-isob-west-1", - "111111111111.dkr.ecr.us-isob-west-1.sc2s.sgov.gov/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-iso-b:ecr:us-isob-west-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse China regions", - "111111111111.dkr.ecr.cn-north-1.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-cn:ecr:cn-north-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse gov regions", - "111111111111.dkr.ecr.us-gov-west-1.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws-us-gov:ecr:us-gov-west-1:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Parse FIPS region for normal use-cases", - "111111111111.dkr.ecr-fips.us-west-2.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws:ecr-fips:us-west-2:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Fail for region that does not have FIPS support", - "111111111111.dkr.ecr-fips.ca-central-1.amazonaws.com/bottlerocket/container:1.2.3", - true, - "", - }, - { - "Invalid region defaults to aws partition (as of aws-sdk-go-v2)", - "111111111111.dkr.ecr.outer-space.amazonaws.com/bottlerocket/container:1.2.3", - false, - "ecr.aws/arn:aws:ecr:outer-space:111111111111:repository/bottlerocket/container:1.2.3", - }, - { - "Empty string fails", - "", - true, - "", - }, - { - "Missing account ID fails", - "dkr.ecr.us-west-2.amazonaws.com/bottlerocket/container:1.2.3", - true, - "", - }, - { - "Missing repository fails", - "111111111111.dkr.ecr.us-west-2.amazonaws.com/", - true, - "", - }, - { - "Malformed URI fails", - "not-an-ecr-uri", - true, - "", - }, + {"us-west-2", "111111111111.dkr.ecr.us-west-2.amazonaws.com", false, false}, + {"cn-north-1", "111111111111.dkr.ecr.cn-north-1.amazonaws.com.cn", false, false}, + {"eu-isoe-west-1", "111111111111.dkr.ecr.eu-isoe-west-1.cloud.adc-e.uk", false, false}, + {"eusc-de-east-1", "111111111111.dkr.ecr.eusc-de-east-1.amazonaws.eu", false, false}, + {"us-iso-east-1", "111111111111.dkr.ecr.us-iso-east-1.c2s.ic.gov", false, false}, + {"us-iso-west-1", "111111111111.dkr.ecr.us-iso-west-1.c2s.ic.gov", false, false}, + {"us-isob-east-1", "111111111111.dkr.ecr.us-isob-east-1.sc2s.sgov.gov", false, false}, + {"us-isob-west-1", "111111111111.dkr.ecr.us-isob-west-1.sc2s.sgov.gov", false, false}, + {"us-isof-east-1", "111111111111.dkr.ecr.us-isof-east-1.csp.hci.ic.gov", false, false}, + {"us-isof-south-1", "111111111111.dkr.ecr.us-isof-south-1.csp.hci.ic.gov", false, false}, + {"ap-southeast-7", "111111111111.dkr.ecr.ap-southeast-7.amazonaws.com", false, false}, + {"mx-central-1", "111111111111.dkr.ecr.mx-central-1.amazonaws.com", false, false}, + {"ap-east-2", "111111111111.dkr.ecr.ap-east-2.amazonaws.com", false, false}, + {"ap-southeast-6", "111111111111.dkr.ecr.ap-southeast-6.amazonaws.com", false, false}, + {"us-northeast-1", "111111111111.dkr.ecr.us-northeast-1.amazonaws.com", false, false}, + {"fips us-west-2", "111111111111.dkr.ecr-fips.us-west-2.amazonaws.com", true, false}, + {"fips us-gov-west-1", "111111111111.dkr.ecr-fips.us-gov-west-1.amazonaws.com", true, false}, + {"missing account ID", "dkr.ecr.us-west-2.amazonaws.com", false, true}, + {"malformed host", "not-an-ecr-host", false, true}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - result, err := fetchECRRef(context.TODO(), tc.ecrImgURI, specialRegions) - if tc.expectedErr { - // handle error cases - if err == nil { - t.Fail() - } - } else { - // handle happy paths - assert.Equal(t, tc.expectedRef, result.Canonical()) + parsed, err := parseECRHost(tc.host) + if tc.wantErr { + assert.Error(t, err) + return } + assert.NoError(t, err) + assert.NotEmpty(t, parsed.Region) + assert.Equal(t, tc.wantFips, parsed.Fips) + + cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion(parsed.Region)) + assert.NoError(t, err, "AWS SDK should support region %s", parsed.Region) + assert.Equal(t, parsed.Region, cfg.Region) }) } } func TestConvertLabel(t *testing.T) { tests := []struct { - name string - labels []string - expectedErr bool - expectedLabelMap map[string]string + name string + labels []string + wantErr bool + wantLabelMap map[string]string }{ { "Valid single label", @@ -541,15 +304,141 @@ func TestConvertLabel(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result, err := convertLabels(tc.labels) - if tc.expectedErr { + if tc.wantErr { // handle error cases if err == nil { t.Fail() } } else { // handle happy paths - assert.Equal(t, tc.expectedLabelMap, result) + assert.Equal(t, tc.wantLabelMap, result) + } + }) + } +} + +func TestDecodeECRToken(t *testing.T) { + tests := []struct { + name string + token *string + wantUser string + wantPass string + wantErr bool + }{ + { + name: "Valid token", + token: stringPtr("QVdTOnBhc3N3b3Jk"), // base64("AWS:password") + wantUser: "AWS", + wantPass: "password", + wantErr: false, + }, + { + name: "Nil token", + token: nil, + wantErr: true, + }, + { + name: "Invalid base64", + token: stringPtr("not-valid-base64!@#"), + wantErr: true, + }, + { + name: "Missing colon separator", + token: stringPtr("QVdTcGFzc3dvcmQ="), // base64("AWSpassword") + wantErr: true, + }, + { + name: "Empty token", + token: stringPtr(""), + wantErr: true, + }, + { + name: "Password with colons", + token: stringPtr("QVdTOnBhc3M6d29yZDp3aXRoOmNvbG9ucw=="), // base64("AWS:pass:word:with:colons") + wantUser: "AWS", + wantPass: "pass:word:with:colons", + wantErr: false, + }, + { + name: "Password with special chars", + token: stringPtr("QVdTOnBAc3MhdzByZCMkJQ=="), // base64("AWS:p@ss!w0rd#$%") + wantUser: "AWS", + wantPass: "p@ss!w0rd#$%", + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + user, pass, err := decodeECRToken(tt.token) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.wantUser, user) + assert.Equal(t, tt.wantPass, pass) } }) } } + +func TestExtractHostFromRef(t *testing.T) { + tests := []struct { + name string + ref string + wantHost string + wantError bool + }{ + { + name: "ECR private registry", + ref: "123456789012.dkr.ecr.us-west-2.amazonaws.com/my-repo:latest", + wantHost: "123456789012.dkr.ecr.us-west-2.amazonaws.com", + wantError: false, + }, + { + name: "ECR public registry", + ref: "public.ecr.aws/my-repo:latest", + wantHost: "public.ecr.aws", + wantError: false, + }, + { + name: "Docker Hub", + ref: "docker.io/library/nginx:latest", + wantHost: "docker.io", + wantError: false, + }, + { + name: "Quay.io registry", + ref: "quay.io/prometheus/node-exporter:v1.5.0", + wantHost: "quay.io", + wantError: false, + }, + { + name: "Invalid reference", + ref: "not a valid reference", + wantError: true, + }, + { + name: "Empty reference", + ref: "", + wantError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + host, err := extractHostFromRef(tt.ref) + if tt.wantError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.wantHost, host) + } + }) + } +} + +// Helper function for tests +func stringPtr(s string) *string { + return &s +} diff --git a/sources/host-ctr/go.mod b/sources/host-ctr/go.mod index d71c4299b..b0a80ce5a 100644 --- a/sources/host-ctr/go.mod +++ b/sources/host-ctr/go.mod @@ -7,8 +7,8 @@ toolchain go1.24.6 require ( github.com/aws/aws-sdk-go-v2 v1.40.0 github.com/aws/aws-sdk-go-v2/config v1.32.1 + github.com/aws/aws-sdk-go-v2/service/ecr v1.54.0 github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.5 - github.com/awslabs/amazon-ecr-containerd-resolver v0.0.0-20250903194853-2883582d177b github.com/containerd/containerd v1.7.29 github.com/containerd/containerd/api v1.10.0 github.com/containerd/errdefs v1.0.0 @@ -52,7 +52,6 @@ require ( github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.54.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.0.1 // indirect @@ -76,7 +75,7 @@ require ( github.com/containerd/typeurl v1.0.2 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/containernetworking/cni v1.3.0 // indirect - github.com/containernetworking/plugins v1.8.0 // indirect + github.com/containernetworking/plugins v1.9.0 // indirect github.com/containers/ocicrypt v1.2.1 // indirect github.com/coreos/go-systemd/v22 v22.6.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect @@ -100,7 +99,6 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect - github.com/htcat/htcat v1.0.2 // indirect github.com/intel/goresctrl v0.10.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.1 // indirect diff --git a/sources/host-ctr/go.sum b/sources/host-ctr/go.sum index 972186cb7..0311fda81 100644 --- a/sources/host-ctr/go.sum +++ b/sources/host-ctr/go.sum @@ -16,64 +16,38 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk= -github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE= github.com/aws/aws-sdk-go-v2 v1.40.0 h1:/WMUA0kjhZExjOQN2z3oLALDREea1A7TobfuiBrKlwc= github.com/aws/aws-sdk-go-v2 v1.40.0/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE= -github.com/aws/aws-sdk-go-v2/config v1.31.17 h1:QFl8lL6RgakNK86vusim14P2k8BFSxjvUkcWLDjgz9Y= -github.com/aws/aws-sdk-go-v2/config v1.31.17/go.mod h1:V8P7ILjp/Uef/aX8TjGk6OHZN6IKPM5YW6S78QnRD5c= github.com/aws/aws-sdk-go-v2/config v1.32.1 h1:iODUDLgk3q8/flEC7ymhmxjfoAnBDwEEYEVyKZ9mzjU= github.com/aws/aws-sdk-go-v2/config v1.32.1/go.mod h1:xoAgo17AGrPpJBSLg81W+ikM0cpOZG8ad04T2r+d5P0= -github.com/aws/aws-sdk-go-v2/credentials v1.18.21 h1:56HGpsgnmD+2/KpG0ikvvR8+3v3COCwaF4r+oWwOeNA= -github.com/aws/aws-sdk-go-v2/credentials v1.18.21/go.mod h1:3YELwedmQbw7cXNaII2Wywd+YY58AmLPwX4LzARgmmA= github.com/aws/aws-sdk-go-v2/credentials v1.19.1 h1:JeW+EwmtTE0yXFK8SmklrFh/cGTTXsQJumgMZNlbxfM= github.com/aws/aws-sdk-go-v2/credentials v1.19.1/go.mod h1:BOoXiStwTF+fT2XufhO0Efssbi1CNIO/ZXpZu87N0pw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 h1:T1brd5dR3/fzNFAQch/iBKeX07/ffu/cLu+q+RuzEWk= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13/go.mod h1:Peg/GBAQ6JDt+RoBf4meB1wylmAipb7Kg2ZFakZTlwk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14 h1:WZVR5DbDgxzA0BJeudId89Kmgy6DIU4ORpxwsVHz0qA= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14/go.mod h1:Dadl9QO0kHgbrH1GRqGiZdYtW5w+IXXaBNCHTIaheM4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 h1:a+8/MLcWlIxo1lF9xaGt3J/u3yOZx+CdSveSNwjhD40= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13/go.mod h1:oGnKwIYZ4XttyU2JWxFrwvhF6YKiK/9/wmE3v3Iu9K8= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14 h1:PZHqQACxYb8mYgms4RZbhZG0a7dPW06xOjmaH0EJC/I= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14/go.mod h1:VymhrMJUWs69D8u0/lZ7jSB6WgaG/NqHi3gX0aYf6U0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 h1:HBSI2kDkMdWz4ZM7FjwE7e/pWDEZ+nR95x8Ztet1ooY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13/go.mod h1:YE94ZoDArI7awZqJzBAZ3PDD2zSfuP7w6P2knOzIn8M= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14 h1:bOS19y6zlJwagBfHxs0ESzr1XCOU2KXJCWcq3E2vfjY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14/go.mod h1:1ipeGBMAxZ0xcTm6y6paC2C/J6f6OO7LBODV9afuAyM= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= -github.com/aws/aws-sdk-go-v2/service/ecr v1.51.2 h1:aq2N/9UkbEyljIQ7OFcudEgUsJzO8MYucmfsM/k/dmc= -github.com/aws/aws-sdk-go-v2/service/ecr v1.51.2/go.mod h1:1NVD1KuMjH2GqnPwMotPndQaT/MreKkWpjkF12d6oKU= github.com/aws/aws-sdk-go-v2/service/ecr v1.54.0 h1:ZIHAPzOl29665Ny0bcOZaiQh3ooQmKZdnpjUr9Bs6D8= github.com/aws/aws-sdk-go-v2/service/ecr v1.54.0/go.mod h1:gTUZahuPMDg0ySQRPFNIbxUzpqu9CSSzU2LVURbWi54= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.2 h1:9fe6w8bydUwNAhFVmjo+SRqAJjbBMOyILL/6hTTVkyA= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.2/go.mod h1:x7gU4CAyAz4BsM9hlRkhHiYw2GIr1QCmN45uwQw9l/E= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.5 h1:1f7Ah71P6+IgmIFxmzOZP3j26jscVsvlqkIENjYCntY= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.5/go.mod h1:z7nn/sUdic8fCdTPhg+w6/9aCvb7BNCLlfifxKn0T2Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 h1:kDqdFvMY4AtKoACfzIGD8A0+hbT41KTKF//gq7jITfM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13/go.mod h1:lmKuogqSU3HzQCwZ9ZtcqOc5XGMqtDK7OIc2+DxiUEg= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14 h1:FIouAnCE46kyYqyhs0XEBDFFSREtdnr8HQuLPQPLCrY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14/go.mod h1:UTwDc5COa5+guonQU8qBikJo1ZJ4ln2r1MkF7Dqag1E= github.com/aws/aws-sdk-go-v2/service/signin v1.0.1 h1:BDgIUYGEo5TkayOWv/oBLPphWwNm/A91AebUjAu5L5g= github.com/aws/aws-sdk-go-v2/service/signin v1.0.1/go.mod h1:iS6EPmNeqCsGo+xQmXv0jIMjyYtQfnwg36zl2FwEouk= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.1 h1:0JPwLz1J+5lEOfy/g0SURC9cxhbQ1lIMHMa+AHZSzz0= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.1/go.mod h1:fKvyjJcz63iL/ftA6RaM8sRCtN4r4zl4tjL3qw5ec7k= github.com/aws/aws-sdk-go-v2/service/sso v1.30.4 h1:U//SlnkE1wOQiIImxzdY5PXat4Wq+8rlfVEw4Y7J8as= github.com/aws/aws-sdk-go-v2/service/sso v1.30.4/go.mod h1:av+ArJpoYf3pgyrj6tcehSFW+y9/QvAY8kMooR9bZCw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5 h1:OWs0/j2UYR5LOGi88sD5/lhN6TDLG6SfA7CqsQO9zF0= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5/go.mod h1:klO+ejMvYsB4QATfEOIXk8WAEwN4N0aBfJpvC+5SZBo= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.9 h1:LU8S9W/mPDAU9q0FjCLi0TrCheLMGwzbRpvUMwYspcA= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.9/go.mod h1:/j67Z5XBVDx8nZVp9EuFM9/BS5dvBznbqILGuu73hug= -github.com/aws/aws-sdk-go-v2/service/sts v1.39.1 h1:mLlUgHn02ue8whiR4BmxxGJLR2gwU6s6ZzJ5wDamBUs= -github.com/aws/aws-sdk-go-v2/service/sts v1.39.1/go.mod h1:E19xDjpzPZC7LS2knI9E6BaRFDK43Eul7vd6rSq2HWk= github.com/aws/aws-sdk-go-v2/service/sts v1.41.1 h1:GdGmKtG+/Krag7VfyOXV17xjTCz0i9NT+JnqLTOI5nA= github.com/aws/aws-sdk-go-v2/service/sts v1.41.1/go.mod h1:6TxbXoDSgBQ225Qd8Q+MbxUxUh6TtNKwbRt/EPS9xso= github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM= github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= -github.com/awslabs/amazon-ecr-containerd-resolver v0.0.0-20250903194853-2883582d177b h1:2R4uPbXloeRzHyElp9Rl5zBhw75IXVFKUpT6lbEdgIc= -github.com/awslabs/amazon-ecr-containerd-resolver v0.0.0-20250903194853-2883582d177b/go.mod h1:Fr8ioid2nLnm0FMPM5J0v0NNWKyYFtKQ4yorKsGwJhE= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -87,7 +61,6 @@ github.com/cilium/ebpf v0.20.0 h1:atwWj9d3NffHyPZzVlx3hmw1on5CLe9eljR8VuHTwhM= github.com/cilium/ebpf v0.20.0/go.mod h1:pzLjFymM+uZPLk/IXZUL63xdx5VXEo+enTzxkZXdycw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups/v3 v3.1.0 h1:azxYVj+91ZgSnIBp2eI3k9y2iYQSR/ZQIgh9vKO+HSY= github.com/containerd/cgroups/v3 v3.1.0/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE= @@ -120,16 +93,14 @@ github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++ github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo= github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4= -github.com/containernetworking/plugins v1.8.0 h1:WjGbV/0UQyo8A4qBsAh6GaDAtu1hevxVxsEuqtBqUFk= -github.com/containernetworking/plugins v1.8.0/go.mod h1:JG3BxoJifxxHBhG3hFyxyhid7JgRVBu/wtooGEvWf1c= +github.com/containernetworking/plugins v1.9.0 h1:Mg3SXBdRGkdXyFC4lcwr6u2ZB2SDeL6LC3U+QrEANuQ= +github.com/containernetworking/plugins v1.9.0/go.mod h1:JG3BxoJifxxHBhG3hFyxyhid7JgRVBu/wtooGEvWf1c= github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM= github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ= github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is= -github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -177,8 +148,6 @@ github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.2.0 h1:3WexO+U+yg9T70v9FdHr9kCxYlazaAXUhx2VMkbfax8= github.com/godbus/dbus/v5 v5.2.0/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -224,8 +193,6 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/htcat/htcat v1.0.2 h1:zro95dGwkKDeZOgq9ei+9szd5qurGxBGfHY8hRehA7k= -github.com/htcat/htcat v1.0.2/go.mod h1:i8ViQbjSi2+lJzM6Lx20FIxHENCz6mzJglK3HH06W3s= github.com/intel/goresctrl v0.10.0 h1:Q94PBhLtQM/aVxVTKzB1j/ooMuV+9XleTN1fq2OGsSo= github.com/intel/goresctrl v0.10.0/go.mod h1:1S8GDqL46GuKb525bxNhIEEkhf4rhVcbSf9DuKhp7mw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -305,15 +272,11 @@ github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.9.1-0.20250523060157-0ea5ed0382a2 h1:2xZEHOdeQBV6PW8ZtimN863bIOl7OCW/X10K0cnxKeA= github.com/opencontainers/runtime-tools v0.9.1-0.20250523060157-0ea5ed0382a2/go.mod h1:MXdPzqAA8pHC58USHqNCSjyLnRQ6D+NjbpP+02Z1U/0= -github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= -github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE= github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 h1:QTvNkZ5ylY0PGgA+Lih+GdboMLY/G9SEGLMEGVjTVA4= -github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/petermattis/goid v0.0.0-20251121121749-a11dd1a45f9a h1:VweslR2akb/ARhXfqSfRbj1vpWwYXf3eeAUyw/ndms0= github.com/petermattis/goid v0.0.0-20251121121749-a11dd1a45f9a/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -334,8 +297,6 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8= -github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko= github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc= github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -345,8 +306,6 @@ github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4 github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sasha-s/go-deadlock v0.3.6 h1:TR7sfOnZ7x00tWPfD397Peodt57KzMDo+9Ae9rMiUmw= @@ -376,8 +335,6 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tchap/go-patricia/v2 v2.3.3 h1:xfNEsODumaEcCcY3gI0hYPZ/PcpVv5ju6RMAhgwZDDc= github.com/tchap/go-patricia/v2 v2.3.3/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= -github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= -github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= github.com/tetratelabs/wazero v1.10.1 h1:2DugeJf6VVk58KTPszlNfeeN8AhhpwcZqkJj2wwFuH8= github.com/tetratelabs/wazero v1.10.1/go.mod h1:DRm5twOQ5Gr1AoEdSi0CLjDQF1J9ZAuyqFIjl1KKfQU= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= @@ -432,8 +389,6 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -447,8 +402,6 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -469,13 +422,9 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= -golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -490,8 +439,6 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -514,8 +461,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= @@ -527,8 +472,6 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -540,8 +483,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= @@ -571,12 +512,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20251103181224-f26f9409b101 h1:MgBTzgUJFAmp2PlyqKJecSpZpjFxkYL3nDUIeH/6Q30= -google.golang.org/genproto v0.0.0-20251103181224-f26f9409b101/go.mod h1:bbWg36d7wp3knc0hIlmJAnW5R/CQ2rzpEVb72eH4ex4= google.golang.org/genproto v0.0.0-20251111163417-95abcf5c77ba h1:Ze6qXW0j37YCqZdCD2LkzVSxgEWez0cO4NUyd44DiDY= google.golang.org/genproto v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:4FLPzLA8eGAktPOTemJGDgDYRpLYwrNu4u2JtWINhnI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -584,8 +521,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= -google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -613,24 +548,14 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= -k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= -k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= -k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA= -k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0= k8s.io/apiserver v0.34.2 h1:2/yu8suwkmES7IzwlehAovo8dDE07cFRC7KMDb1+MAE= k8s.io/apiserver v0.34.2/go.mod h1:gqJQy2yDOB50R3JUReHSFr+cwJnL8G1dzTA0YLEqAPI= -k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= -k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= -k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= -k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ= k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM= k8s.io/cri-api v0.27.14 h1:cliTAhn5VpM5UDh2xsjsHVm4dG1y5k8Z0ZM5uqVwL4Q= @@ -645,8 +570,6 @@ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5E sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/structured-merge-diff/v6 v6.3.1 h1:JrhdFMqOd/+3ByqlP2I45kTOZmTRLBUm5pvRjeheg7E= sigs.k8s.io/structured-merge-diff/v6 v6.3.1/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=