Skip to content

Commit 1dc186d

Browse files
committed
add --expected-identity parameter
1 parent e9cc14f commit 1dc186d

File tree

1 file changed

+16
-22
lines changed

1 file changed

+16
-22
lines changed

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

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ var (
3131
`)
3232

3333
verifyImageSignatureExample = templates.Examples(`
34-
# Verify the image signature using the public key and record the status as a condition to image
35-
%[1]s sha256:c841e9b64e4579bd56c794bdd7c36e1c257110fd2404bebbb8b613e4935228c4 --public-key=production.gpg --confirm
34+
# Verify the image signature using the local GNUPG keychan and record the status as a condition to image
35+
%[1]s sha256:c841e9b64e4579bd56c794bdd7c36e1c257110fd2404bebbb8b613e4935228c4 --expected-identity=registry.local:5000/foo/bar:v1
3636
`)
3737
)
3838

3939
type VerifyImageSignatureOptions struct {
4040
InputImage string
41+
ExpectedIdentity string
4142
PublicKeyFilename string
4243
PublicKey []byte
4344
Confirm bool
@@ -65,6 +66,7 @@ func NewCmdVerifyImageSignature(name, fullName string, f *clientcmd.Factory, out
6566
cmd.Flags().BoolVar(&opts.Confirm, "confirm", opts.Confirm, "If true, the result of the verification will be recorded to an image object.")
6667
cmd.Flags().BoolVar(&opts.Remove, "remove", opts.Remove, "If set, the current signature verification will be removed from the image.")
6768
cmd.Flags().StringVar(&opts.PublicKeyFilename, "public-key", opts.PublicKeyFilename, "A path to a public GPG key to be used for verification.")
69+
cmd.Flags().StringVar(&opts.ExpectedIdentity, "expected-identity", opts.ExpectedIdentity, "An expected image docker reference to verify.")
6870
return cmd
6971
}
7072

@@ -73,6 +75,9 @@ func (o *VerifyImageSignatureOptions) Complete(f *clientcmd.Factory, cmd *cobra.
7375
return kcmdutil.UsageError(cmd, "exactly one image must be specified")
7476
}
7577
o.InputImage = args[0]
78+
if len(o.ExpectedIdentity) == 0 {
79+
return kcmdutil.UsageError(cmd, "the --expected-identity must be specified")
80+
}
7681
var err error
7782

7883
// If --public-key is provided only this key will be used for verification and the
@@ -128,7 +133,7 @@ func (o *VerifyImageSignatureOptions) verifySignature(signature []byte) (string,
128133

129134
// verifySignatureContent verifies that the signature content matches the given image.
130135
// TODO: This should be done by calling the 'containers/image' library in future.
131-
func (o *VerifyImageSignatureOptions) verifySignatureContent(content []byte) (string, string, error) {
136+
func (o *VerifyImageSignatureOptions) verifySignatureContent(content []byte) (string, error) {
132137
// TODO: The types here are just to decompose the JSON. The fields should not change but
133138
// we need to use containers/image library here to guarantee compatibility in future.
134139
type criticalImage struct {
@@ -146,31 +151,20 @@ func (o *VerifyImageSignatureOptions) verifySignatureContent(content []byte) (st
146151
}
147152
m := message{}
148153
if err := json.Unmarshal(content, &m); err != nil {
149-
return "", "", err
154+
return "", err
150155
}
151156
if o.InputImage != m.Critical.Image.Digest {
152-
return "", "", fmt.Errorf("signature is valid for digest %q not for %q", m.Critical.Image.Digest, o.InputImage)
157+
return "", fmt.Errorf("signature is valid for digest %q not for %q", m.Critical.Image.Digest, o.InputImage)
153158
}
154-
return m.Critical.Image.Digest, m.Critical.Identity.DockerReference, nil
159+
return m.Critical.Identity.DockerReference, nil
155160
}
156161

157162
// verifyImageIdentity verifies the source of the image specified in the signature is
158163
// valid.
159-
func (o *VerifyImageSignatureOptions) verifyImageIdentity(reference, digest string) error {
160-
ref, err := imageapi.ParseDockerImageReference(reference)
161-
if err != nil {
162-
return err
164+
func (o *VerifyImageSignatureOptions) verifyImageIdentity(reference string) error {
165+
if reference != o.ExpectedIdentity {
166+
return fmt.Errorf("signature identity %q does not match expected image identity %q", reference, o.ExpectedIdentity)
163167
}
164-
// Verify the tag exists
165-
tag, err := o.Client.ImageStreamTags(ref.Namespace).Get(ref.Name, ref.Tag)
166-
if err != nil {
167-
return err
168-
}
169-
170-
if tag.Image.Name != o.InputImage {
171-
return fmt.Errorf("signature identity %q does not match image %q", reference, tag.Image.Name)
172-
}
173-
174168
return nil
175169
}
176170

@@ -207,12 +201,12 @@ func (o *VerifyImageSignatureOptions) Run() error {
207201
}
208202

209203
// Verify the signed message content matches with the provided image id
210-
digest, identity, signatureContentErr := o.verifySignatureContent(content)
204+
identity, signatureContentErr := o.verifySignatureContent(content)
211205
if signatureContentErr != nil {
212206
fmt.Fprintf(o.ErrOut, "%s signature content cannot be verified: %v\n", o.InputImage, signatureContentErr)
213207
}
214208

215-
identityError := o.verifyImageIdentity(identity, digest)
209+
identityError := o.verifyImageIdentity(identity)
216210
if identityError != nil {
217211
fmt.Fprintf(o.ErrOut, "%s identity cannot be verified: %v\n", o.InputImage, identityError)
218212
}

0 commit comments

Comments
 (0)