Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 30 additions & 18 deletions image-mapper/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# image-mapper

An example of matching non-Chainguard images to their Chainguard equivalents.
A tool for matching non-Chainguard images to their Chainguard equivalents.

## Usage

Expand All @@ -14,18 +14,26 @@ Then, provide the images to map on the command line.

```
$ ./image-mapper ghcr.io/stakater/reloader:v1.4.1 registry.k8s.io/sig-storage/livenessprobe:v2.13.1
ghcr.io/stakater/reloader:v1.4.1 -> stakater-reloader
ghcr.io/stakater/reloader:v1.4.1 -> stakater-reloader-fips
registry.k8s.io/sig-storage/livenessprobe:v2.13.1 -> kubernetes-csi-livenessprobe
ghcr.io/stakater/reloader:v1.4.1 -> cgr.dev/chainguard/stakater-reloader-fips:v1.4.12
ghcr.io/stakater/reloader:v1.4.1 -> cgr.dev/chainguard/stakater-reloader:v1.4.12
registry.k8s.io/sig-storage/livenessprobe:v2.13.1 -> cgr.dev/chainguard/kubernetes-csi-livenessprobe:v2.17.0
```

You can provide a list of images (one image per line) via stdin when the first
You'll notice that the mapper increments the tag to the closest version
supported by Chainguard. To benefit from continued CVE remediation, it's
important, where possible, to use tags that are being actively maintained.

You can also provide a list of images (one image per line) via stdin when the first
argument is `-`.

```
$ cat ./images.txt | ./image-mapper -
```

## Options

### Output

Configure the output format with the `-o` flag. Supported formats are: `csv`,
`json` and `text`.

Expand All @@ -35,49 +43,53 @@ $ ./image-mapper ghcr.io/stakater/reloader:v1.4.1 registry.k8s.io/sig-storage/li
{
"image": "ghcr.io/stakater/reloader:v1.4.1",
"results": [
"stakater-reloader",
"stakater-reloader-fips"
"cgr.dev/chainguard/stakater-reloader-fips:v1.4.12",
"cgr.dev/chainguard/stakater-reloader:v1.4.12"
]
},
{
"image": "registry.k8s.io/sig-storage/livenessprobe:v2.13.1",
"results": [
"kubernetes-csi-livenessprobe"
"cgr.dev/chainguard/kubernetes-csi-livenessprobe:v2.17.0"
]
}
]
```

```
$ ./image-mapper ghcr.io/stakater/reloader:v1.4.1 registry.k8s.io/sig-storage/livenessprobe:v2.13.1 -o csv
ghcr.io/stakater/reloader:v1.4.1,[stakater-reloader stakater-reloader-fips]
registry.k8s.io/sig-storage/livenessprobe:v2.13.1,[kubernetes-csi-livenessprobe]
ghcr.io/stakater/reloader:v1.4.1,[cgr.dev/chainguard/stakater-reloader-fips:v1.4.12 cgr.dev/chainguard/stakater-reloader:v1.4.12]
registry.k8s.io/sig-storage/livenessprobe:v2.13.1,[cgr.dev/chainguard/kubernetes-csi-livenessprobe:v2.17.0]
```

### Ignore Tiers (i.e FIPS)

The output will map both FIPS and non-FIPS variants. You can exclude FIPS with
the `--ignore-tiers` flag.

```
$ ./image-mapper prom/prometheus
prom/prometheus -> prometheus
prom/prometheus -> prometheus-fips
prom/prometheus -> prometheus-iamguarded
prom/prometheus -> prometheus-iamguarded-fips
prom/prometheus -> cgr.dev/chainguard/prometheus-fips:latest
prom/prometheus -> cgr.dev/chainguard/prometheus-iamguarded-fips:latest
prom/prometheus -> cgr.dev/chainguard/prometheus-iamguarded:latest
prom/prometheus -> cgr.dev/chainguard/prometheus:latest

$ ./image-mapper prom/prometheus --ignore-tiers=FIPS
prom/prometheus -> prometheus
prom/prometheus -> prometheus-iamguarded
prom/prometheus -> cgr.dev/chainguard/prometheus-iamguarded:latest
prom/prometheus -> cgr.dev/chainguard/prometheus:latest
```

### Ignore Iamguarded

The mapper will also return matches for our `-iamguarded` images. These images
are designed specifically to work with Chainguard's Helm charts. If you aren't
interested in using our charts, you can exclude those matches with
`--ignore-iamguarded`.

```
$ ./image-mapper prom/prometheus --ignore-iamguarded
prom/prometheus -> prometheus
prom/prometheus -> prometheus-fips
prom/prometheus -> cgr.dev/chainguard/prometheus-fips:latest
prom/prometheus -> cgr.dev/chainguard/prometheus:latest
```

## Docker
Expand Down
25 changes: 20 additions & 5 deletions image-mapper/internal/mapper/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"slices"
"strings"

"github.com/google/go-containerregistry/pkg/name"
)
Expand All @@ -18,6 +19,7 @@ type Mapping struct {
type Mapper struct {
repos []Repo
ignoreFns []IgnoreFn
repoName string
}

// NewMapper creates a new mapper
Expand All @@ -35,6 +37,7 @@ func NewMapper(ctx context.Context, opts ...Option) (*Mapper, error) {
m := &Mapper{
repos: repos,
ignoreFns: o.ignoreFns,
repoName: "cgr.dev/chainguard",
}

return m, nil
Expand Down Expand Up @@ -71,12 +74,14 @@ func (m *Mapper) MapAll(it Iterator) ([]*Mapping, error) {

// Map an upstream image to the corresponding images in chainguard-private
func (m *Mapper) Map(image string) (*Mapping, error) {
ref, err := name.ParseReference(image)
ref, err := name.NewTag(strings.Split(image, "@")[0])
if err != nil {
return nil, fmt.Errorf("parsing %s: %w", image, err)
}

matches := map[string]struct{}{}
// Identify repositories in the Chainguard catalog that match the
// provided image
matches := map[string]Repo{}
for _, cgrrepo := range m.repos {
// There are some images that may appear in the results but are
// not accessible in the catalog. We can exclude them by
Expand All @@ -92,12 +97,22 @@ func (m *Mapper) Map(image string) (*Mapping, error) {
if !Match(ref, cgrrepo) {
continue
}
matches[cgrrepo.Name] = struct{}{}
matches[cgrrepo.Name] = cgrrepo
}

// Format the matches into the results we'll include in the mappings

results := []string{}
for match := range matches {
results = append(results, match)
for _, cgrrepo := range matches {
// Append the repository name to the rest of the reference
result := fmt.Sprintf("%s/%s", m.repoName, cgrrepo.Name)

// Try and match the provided tag to one of the active tags
tag := MatchTag(cgrrepo.ActiveTags, ref.TagStr())
if tag != "" {
result = fmt.Sprintf("%s:%s", result, tag)
}
results = append(results, result)
}
slices.Sort(results)

Expand Down
Loading
Loading