Skip to content

Commit b73ce56

Browse files
committed
verify the critical.image.identity against image stream tag
1 parent 562ebf6 commit b73ce56

File tree

1 file changed

+37
-7
lines changed

1 file changed

+37
-7
lines changed

pkg/cmd/admin/image/verify-signature.go

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,25 +128,50 @@ func (o *VerifyImageSignatureOptions) verifySignature(signature []byte) (string,
128128

129129
// verifySignatureContent verifies that the signature content matches the given image.
130130
// TODO: This should be done by calling the 'containers/image' library in future.
131-
func (o *VerifyImageSignatureOptions) verifySignatureContent(content []byte) error {
131+
func (o *VerifyImageSignatureOptions) verifySignatureContent(content []byte) (string, string, error) {
132132
// TODO: The types here are just to decompose the JSON. The fields should not change but
133133
// we need to use containers/image library here to guarantee compatibility in future.
134134
type criticalImage struct {
135135
Digest string `json:"docker-manifest-digest"`
136136
}
137+
type criticalIdentity struct {
138+
DockerReference string `json:"docker-reference"`
139+
}
137140
type critical struct {
138-
Image criticalImage `json:"image"`
141+
Image criticalImage `json:"image"`
142+
Identity criticalIdentity `json:"identity"`
139143
}
140144
type message struct {
141145
Critical critical `json:"critical"`
142146
}
143147
m := message{}
144148
if err := json.Unmarshal(content, &m); err != nil {
145-
return err
149+
return "", "", err
146150
}
147151
if o.InputImage != m.Critical.Image.Digest {
148-
return fmt.Errorf("signature is valid for digest %q not for %q", m.Critical.Image.Digest, o.InputImage)
152+
return "", "", fmt.Errorf("signature is valid for digest %q not for %q", m.Critical.Image.Digest, o.InputImage)
153+
}
154+
fmt.Printf("critical=%#+v\n", m.Critical)
155+
return m.Critical.Image.Digest, m.Critical.Identity.DockerReference, nil
156+
}
157+
158+
// verifyImageIdentity verifies the source of the image specified in the signature is
159+
// valid.
160+
func (o *VerifyImageSignatureOptions) verifyImageIdentity(reference, digest string) error {
161+
ref, err := imageapi.ParseDockerImageReference(reference)
162+
if err != nil {
163+
return err
149164
}
165+
// Verify the tag exists
166+
tag, err := o.Client.ImageStreamTags(ref.Namespace).Get(ref.Name, ref.Tag)
167+
if err != nil {
168+
return err
169+
}
170+
171+
if tag.Image.Name != digest {
172+
return fmt.Errorf("signature identity %q does not match image %q", reference, tag.Image.Name)
173+
}
174+
150175
return nil
151176
}
152177

@@ -183,14 +208,19 @@ func (o *VerifyImageSignatureOptions) Run() error {
183208
}
184209

185210
// Verify the signed message content matches with the provided image id
186-
var signatureContentErr error
187-
if signatureContentErr = o.verifySignatureContent(content); signatureContentErr != nil {
211+
digest, identity, signatureContentErr := o.verifySignatureContent(content)
212+
if signatureContentErr != nil {
188213
fmt.Fprintf(o.ErrOut, "%s signature content cannot be verified: %v\n", o.InputImage, signatureContentErr)
189214
}
190215

216+
identityError := o.verifyImageIdentity(identity, digest)
217+
if identityError != nil {
218+
fmt.Fprintf(o.ErrOut, "%s identity cannot be verified: %v\n", o.InputImage, identityError)
219+
}
220+
191221
// If we have error and --confirm then remove the signature from the image which
192222
// changes the image to "unverified" state.
193-
if signatureErr != nil || signatureContentErr != nil {
223+
if signatureErr != nil || signatureContentErr != nil || identityError != nil {
194224
o.removeImageSignature(&img.Signatures[i])
195225
continue
196226
}

0 commit comments

Comments
 (0)