@@ -128,25 +128,50 @@ func (o *VerifyImageSignatureOptions) verifySignature(signature []byte) (string,
128
128
129
129
// verifySignatureContent verifies that the signature content matches the given image.
130
130
// 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 ) {
132
132
// TODO: The types here are just to decompose the JSON. The fields should not change but
133
133
// we need to use containers/image library here to guarantee compatibility in future.
134
134
type criticalImage struct {
135
135
Digest string `json:"docker-manifest-digest"`
136
136
}
137
+ type criticalIdentity struct {
138
+ DockerReference string `json:"docker-reference"`
139
+ }
137
140
type critical struct {
138
- Image criticalImage `json:"image"`
141
+ Image criticalImage `json:"image"`
142
+ Identity criticalIdentity `json:"identity"`
139
143
}
140
144
type message struct {
141
145
Critical critical `json:"critical"`
142
146
}
143
147
m := message {}
144
148
if err := json .Unmarshal (content , & m ); err != nil {
145
- return err
149
+ return "" , "" , err
146
150
}
147
151
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
149
164
}
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
+
150
175
return nil
151
176
}
152
177
@@ -183,14 +208,19 @@ func (o *VerifyImageSignatureOptions) Run() error {
183
208
}
184
209
185
210
// 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 {
188
213
fmt .Fprintf (o .ErrOut , "%s signature content cannot be verified: %v\n " , o .InputImage , signatureContentErr )
189
214
}
190
215
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
+
191
221
// If we have error and --confirm then remove the signature from the image which
192
222
// changes the image to "unverified" state.
193
- if signatureErr != nil || signatureContentErr != nil {
223
+ if signatureErr != nil || signatureContentErr != nil || identityError != nil {
194
224
o .removeImageSignature (& img .Signatures [i ])
195
225
continue
196
226
}
0 commit comments