diff --git a/hack/vendor.sh b/hack/vendor.sh index 00b7729b3919a..57636dd06951f 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -167,7 +167,7 @@ clone git github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42 clone git github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff # signatures -clone git github.com/containers/image 6f5f102da5ee57ddca4f23d2c0e4cc7da9cb54b4 +clone git github.com/containers/image untagged-reference-sig-check https://github.com/mtrmac/image clone git github.com/opencontainers/image-spec 756744a5dcf23a6c8e4b11ef403522ca3ca33fd9 clone git k8s.io/kubernetes 4a3f9c5b19c7ff804cbc1bf37a15c044ca5d2353 https://github.com/openshift/kubernetes clone git github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed diff --git a/integration-cli/docker_cli_pull_local_test.go b/integration-cli/docker_cli_pull_local_test.go index e5b91c8a0ebf1..a22fc475c2c38 100644 --- a/integration-cli/docker_cli_pull_local_test.go +++ b/integration-cli/docker_cli_pull_local_test.go @@ -723,7 +723,10 @@ func (s *DockerRegistriesSuite) TestPullWithPolicy(c *check.C) { "docker": { "%s/busybox": [ { - "referencesByDigest": "reject", + "signedIdentity": { + "type": "matchExact", + "allowReferencesByDigest": false + }, "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/root/personal-pubkey.gpg" diff --git a/vendor/src/github.com/containers/image/signature/policy_config.go b/vendor/src/github.com/containers/image/signature/policy_config.go index d5e20489bd1da..cec529fd14afe 100644 --- a/vendor/src/github.com/containers/image/signature/policy_config.go +++ b/vendor/src/github.com/containers/image/signature/policy_config.go @@ -386,7 +386,7 @@ func (pr *prSignedBy) UnmarshalJSON(data []byte) error { return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) } if signedIdentity == nil { - tmp.SignedIdentity = NewPRMMatchExact() + tmp.SignedIdentity = NewPRMMatchExact(true) } else { si, err := newPolicyReferenceMatchFromJSON(signedIdentity) if err != nil { @@ -501,7 +501,7 @@ func (pr *prSignedBaseLayer) UnmarshalJSON(data []byte) error { return nil } -// newPolicyRequirementFromJSON parses JSON data into a PolicyReferenceMatch implementation. +// newPolicyReferenceFromJSON parses JSON data into a PolicyReferenceMatch implementation. func newPolicyReferenceMatchFromJSON(data []byte) (PolicyReferenceMatch, error) { var typeField prmCommon if err := json.Unmarshal(data, &typeField); err != nil { @@ -527,13 +527,16 @@ func newPolicyReferenceMatchFromJSON(data []byte) (PolicyReferenceMatch, error) } // newPRMMatchExact is NewPRMMatchExact, except it resturns the private type. -func newPRMMatchExact() *prmMatchExact { - return &prmMatchExact{prmCommon{Type: prmTypeMatchExact}} +func newPRMMatchExact(allowReferencesByDigest bool) *prmMatchExact { + return &prmMatchExact{ + prmCommon: prmCommon{Type: prmTypeMatchExact}, + AllowReferencesByDigest: allowReferencesByDigest, + } } // NewPRMMatchExact returns a new "matchExact" PolicyReferenceMatch. -func NewPRMMatchExact() PolicyReferenceMatch { - return newPRMMatchExact() +func NewPRMMatchExact(allowReferencesByDigest bool) PolicyReferenceMatch { + return newPRMMatchExact(allowReferencesByDigest) } // Compile-time check that prmMatchExact implements json.Unmarshaler. @@ -542,11 +545,13 @@ var _ json.Unmarshaler = (*prmMatchExact)(nil) // UnmarshalJSON implements the json.Unmarshaler interface. func (prm *prmMatchExact) UnmarshalJSON(data []byte) error { *prm = prmMatchExact{} - var tmp prmMatchExact + tmp := prmMatchExact{AllowReferencesByDigest: true} // NOTE: The JSON default is different from the Golang default if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { switch key { case "type": return &tmp.Type + case "allowReferencesByDigest": + return &tmp.AllowReferencesByDigest default: return nil } @@ -557,7 +562,7 @@ func (prm *prmMatchExact) UnmarshalJSON(data []byte) error { if tmp.Type != prmTypeMatchExact { return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) } - *prm = *newPRMMatchExact() + *prm = *newPRMMatchExact(tmp.AllowReferencesByDigest) return nil } diff --git a/vendor/src/github.com/containers/image/signature/policy_reference_match.go b/vendor/src/github.com/containers/image/signature/policy_reference_match.go index aedda8d09b6fa..ad9489ea59f6e 100644 --- a/vendor/src/github.com/containers/image/signature/policy_reference_match.go +++ b/vendor/src/github.com/containers/image/signature/policy_reference_match.go @@ -29,11 +29,23 @@ func (prm *prmMatchExact) matchesDockerReference(image types.UnparsedImage, sign if err != nil { return false } + // Do not add default tags: image.Reference().DockerReference() should contain it already, and signatureDockerReference should be exact; so, verify that now. - if reference.IsNameOnly(intended) || reference.IsNameOnly(signature) { + if reference.IsNameOnly(signature) { + return false + } + switch intended.(type) { + case reference.NamedTagged: // Includes the case when intended has both a tag and a digest. + return signature.String() == intended.String() + case reference.Canonical: + // We don’t actually compare the manifest digest against the signature here; that happens prSignedBy.in UnparsedImage.Manifest. + // Becase UnparsedImage.Manifest verifies the intended.Digest() against the manifest, and prSignedBy verifies the signature digest against the manifest, + // we know that signature digest matches intended.Digest() (but intended.Digest() and signature digest may use different algorithms) + // FIXME? Compare the digests here anyway, for extra safety against code changes, at the cost of not supporting pull-by-digest using a different algorithm than the signature? + return prm.AllowReferencesByDigest + default: // !reference.IsNameOnly(intended) return false } - return signature.String() == intended.String() } func (prm *prmMatchRepository) matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool { diff --git a/vendor/src/github.com/containers/image/signature/policy_types.go b/vendor/src/github.com/containers/image/signature/policy_types.go index 5775ab21dd549..b96358df4ad0c 100644 --- a/vendor/src/github.com/containers/image/signature/policy_types.go +++ b/vendor/src/github.com/containers/image/signature/policy_types.go @@ -122,9 +122,11 @@ const ( prmTypeExactRepository prmTypeIdentifier = "exactRepository" ) -// prmMatchExact is a PolicyReferenceMatch with type = prmMatchExact: the two references must match exactly. +// prmMatchExact is a PolicyReferenceMatch with type = prmMatchExact: the two references must match exactly, +// except that digest references may be accepted regardless of tag if AllowReferencesByDigest type prmMatchExact struct { prmCommon + AllowReferencesByDigest bool `json:"allowReferencesByDigest"` // NOTE: If missing in JSON, this defaults to true (but defaults to false in Golang!) } // prmMatchRepository is a PolicyReferenceMatch with type = prmMatchRepository: the two references must use the same repository, may differ in the tag.