containerimage: set attestation subjects based on image name

Signed-off-by: Justin Chadwell <me@jedevc.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Justin Chadwell
2022-08-30 11:30:44 +01:00
committed by Tonis Tiigi
parent 64082ae1e4
commit d80b59fa5e
3 changed files with 71 additions and 25 deletions

View File

@@ -50,6 +50,7 @@ import (
binfotypes "github.com/moby/buildkit/util/buildinfo/types"
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/purl"
"github.com/moby/buildkit/util/testutil"
"github.com/moby/buildkit/util/testutil/echoserver"
"github.com/moby/buildkit/util/testutil/httpserver"
@@ -6527,13 +6528,16 @@ func testExportAttestations(t *testing.T, sb integration.Sandbox) {
return res, nil
}
target := registry + "/buildkit/testattestations:latest"
targets := []string{
registry + "/buildkit/testattestationsfoo:latest",
registry + "/buildkit/testattestationsbar:latest",
}
_, err = c.Build(sb.Context(), SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterImage,
Attrs: map[string]string{
"name": target,
"name": strings.Join(targets, ","),
"push": "true",
},
},
@@ -6541,7 +6545,7 @@ func testExportAttestations(t *testing.T, sb integration.Sandbox) {
}, "", frontend, nil)
require.NoError(t, err)
desc, provider, err := contentutil.ProviderFromRef(target)
desc, provider, err := contentutil.ProviderFromRef(targets[0])
require.NoError(t, err)
imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
@@ -6574,15 +6578,29 @@ func testExportAttestations(t *testing.T, sb integration.Sandbox) {
var attest intoto.Statement
require.NoError(t, json.Unmarshal(att.LayersRaw[0], &attest))
purls := map[string]string{}
for _, k := range targets {
p, _ := purl.RefToPURL(k, &ps[i])
purls[k] = p
}
require.Equal(t, "https://in-toto.io/Statement/v0.1", attest.Type)
require.Equal(t, "https://example.com/attestations/v1.0", attest.PredicateType)
require.Equal(t, map[string]interface{}{"success": true}, attest.Predicate)
subjects := []intoto.Subject{{
Name: "_",
Digest: map[string]string{
"sha256": bases[i].Desc.Digest.Encoded(),
subjects := []intoto.Subject{
{
Name: purls[targets[0]],
Digest: map[string]string{
"sha256": bases[i].Desc.Digest.Encoded(),
},
},
}}
{
Name: purls[targets[1]],
Digest: map[string]string{
"sha256": bases[i].Desc.Digest.Encoded(),
},
},
}
require.Equal(t, subjects, attest.Subject)
var attest2 intoto.Statement
@@ -6609,9 +6627,10 @@ func testExportAttestations(t *testing.T, sb integration.Sandbox) {
defer client.Close()
ctx := namespaces.WithNamespace(sb.Context(), "buildkit")
err = client.ImageService().Delete(ctx, target, images.SynchronousDelete())
require.NoError(t, err)
for _, target := range targets {
err = client.ImageService().Delete(ctx, target, images.SynchronousDelete())
require.NoError(t, err)
}
checkAllReleasable(t, c, sb, true)
}
@@ -6737,8 +6756,11 @@ func testAttestationDefaultSubject(t *testing.T, sb integration.Sandbox) {
require.Equal(t, "https://in-toto.io/Statement/v0.1", attest.Type)
require.Equal(t, "https://example.com/attestations/v1.0", attest.PredicateType)
require.Equal(t, map[string]interface{}{"success": true}, attest.Predicate)
name, _ := purl.RefToPURL(target, &ps[0])
subjects := []intoto.Subject{{
Name: "_",
Name: name,
Digest: map[string]string{
"sha256": bases[i].Desc.Digest.Encoded(),
},

View File

@@ -30,6 +30,7 @@ import (
binfotypes "github.com/moby/buildkit/util/buildinfo/types"
"github.com/moby/buildkit/util/compression"
"github.com/moby/buildkit/util/progress"
"github.com/moby/buildkit/util/purl"
"github.com/moby/buildkit/util/system"
"github.com/moby/buildkit/util/tracing"
digest "github.com/opencontainers/go-digest"
@@ -290,13 +291,6 @@ func (ic *ImageWriter) extractAttestations(ctx context.Context, opts *ImageCommi
if len(predicate) == 0 {
predicate = nil
}
statements[i] = intoto.Statement{
StatementHeader: intoto.StatementHeader{
Type: intoto.StatementInTotoV01,
PredicateType: att.InToto.PredicateType,
},
Predicate: json.RawMessage(predicate),
}
if len(att.InToto.Subjects) == 0 {
att.InToto.Subjects = []result.InTotoSubject{{
@@ -304,21 +298,50 @@ func (ic *ImageWriter) extractAttestations(ctx context.Context, opts *ImageCommi
}}
}
statements[i].Subject = make([]intoto.Subject, len(att.InToto.Subjects))
for j, subject := range att.InToto.Subjects {
statements[i].Subject[j].Name = "_"
subjects := make([]intoto.Subject, 0, len(att.InToto.Subjects))
for _, subject := range att.InToto.Subjects {
name := "_"
if subject.Name != "" {
statements[i].Subject[j].Name = subject.Name
name = subject.Name
}
switch subject.Kind {
case gatewaypb.InTotoSubjectKindSelf:
statements[i].Subject[j].Digest = result.DigestMap(desc.Digest)
var names []string
if opts.ImageName != "" {
for _, name := range strings.Split(opts.ImageName, ",") {
name, err := purl.RefToPURL(name, desc.Platform)
if err != nil {
return err
}
names = append(names, name)
}
} else {
names = []string{name}
}
for _, name := range names {
subjects = append(subjects, intoto.Subject{
Name: name,
Digest: result.DigestMap(desc.Digest),
})
}
case gatewaypb.InTotoSubjectKindRaw:
statements[i].Subject[j].Digest = result.DigestMap(subject.Digest...)
subjects = append(subjects, intoto.Subject{
Name: name,
Digest: result.DigestMap(subject.Digest...),
})
default:
return errors.Errorf("unknown attestation subject kind %q", subject.Kind)
}
}
statements[i] = intoto.Statement{
StatementHeader: intoto.StatementHeader{
Type: intoto.StatementInTotoV01,
PredicateType: att.InToto.PredicateType,
Subject: subjects,
},
Predicate: json.RawMessage(predicate),
}
}
return nil
})

View File

@@ -90,6 +90,7 @@ func TestRefToPURL(t *testing.T) {
func TestPURLToRef(t *testing.T) {
testDgst := digest.FromBytes([]byte("test")).String()
p := platforms.Normalize(platforms.DefaultSpec())
p.OSVersion = "" // OSVersion is not supported in PURL
testPlatform := &p
encPlatform := url.QueryEscape(platforms.Format(platforms.Normalize(p)))