Rename argument. Only use any with public key file. Double check fingerprint is in public key file.

Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
This commit is contained in:
James Hewitt
2023-03-25 14:27:41 +00:00
parent 3097b7a4e9
commit 9b1f1fa1a9
3 changed files with 28 additions and 16 deletions

View File

@@ -67,7 +67,7 @@ func (opts *standaloneSignOptions) run(args []string, stdout io.Writer) error {
} }
type standaloneVerifyOptions struct { type standaloneVerifyOptions struct {
truststore string publickeyfile string
} }
func standaloneVerifyCmd() *cobra.Command { func standaloneVerifyCmd() *cobra.Command {
@@ -77,11 +77,11 @@ func standaloneVerifyCmd() *cobra.Command {
Short: "Verify a signature using local files", Short: "Verify a signature using local files",
Long: `Verify a signature using local files Long: `Verify a signature using local files
KEY-FINGERPRINT can be an exact fingerprint, or "any" if you trust all the keys in the trust store.`, KEY-FINGERPRINT can be an exact fingerprint, or "any" if you trust all the keys in the public key file.`,
RunE: commandAction(opts.run), RunE: commandAction(opts.run),
} }
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVar(&opts.truststore, "truststore", "", "Trust store of public keys. Defaults to using local gpg keys.") flags.StringVar(&opts.publickeyfile, "public-key-file", "", `File containing public keys. If not specified, will use local GPG keys. When using a public key file, you can specify "any" as the fingerprint to trust any key in the public key file.`)
adjustUsage(cmd) adjustUsage(cmd)
return cmd return cmd
} }
@@ -105,12 +105,13 @@ func (opts *standaloneVerifyOptions) run(args []string, stdout io.Writer) error
} }
var mech signature.SigningMechanism var mech signature.SigningMechanism
if opts.truststore != "" { var fingerprints []string
truststore, err := os.ReadFile(opts.truststore) if opts.publickeyfile != "" {
publicKeys, err := os.ReadFile(opts.publickeyfile)
if err != nil { if err != nil {
return fmt.Errorf("Error reading trust store from %s: %v", opts.truststore, err) return fmt.Errorf("Error reading public keys from %s: %v", opts.publickeyfile, err)
} }
mech, _, err = signature.NewEphemeralGPGSigningMechanism(truststore) mech, fingerprints, err = signature.NewEphemeralGPGSigningMechanism(publicKeys)
} else { } else {
mech, err = signature.NewGPGSigningMechanism() mech, err = signature.NewGPGSigningMechanism()
} }
@@ -119,11 +120,21 @@ func (opts *standaloneVerifyOptions) run(args []string, stdout io.Writer) error
} }
defer mech.Close() defer mech.Close()
if expectedFingerprint == "any" { if opts.publickeyfile != "" && expectedFingerprint == "any" {
_, expectedFingerprint, err = mech.Verify(unverifiedSignature) _, expectedFingerprint, err = mech.Verify(unverifiedSignature)
if err != nil { if err != nil {
return fmt.Errorf("Could not determine fingerprint from signature: %v", err) return fmt.Errorf("Could not determine fingerprint from signature: %v", err)
} }
found := false
for _, fingerprint := range fingerprints {
if expectedFingerprint == fingerprint {
found = true
}
}
if !found {
// This is theoretically impossible because mech.Verify only works if it can identify the key based on the signature
return fmt.Errorf("Signature fingerprint not found in public key file: %s", expectedFingerprint)
}
} }
sig, err := signature.VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest, expectedDockerReference, mech, expectedFingerprint) sig, err := signature.VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest, expectedDockerReference, mech, expectedFingerprint)

View File

@@ -133,15 +133,16 @@ func TestStandaloneVerify(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "Signature verified using fingerprint 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8, digest "+fixturesTestImageManifestDigest.String()+"\n", out) assert.Equal(t, "Signature verified using fingerprint 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8, digest "+fixturesTestImageManifestDigest.String()+"\n", out)
// Using any known fingerprint // Using a public key file
out, err = runSkopeo("standalone-verify", manifestPath, t.Setenv("GNUPGHOME", "")
dockerReference, "any", signaturePath) out, err = runSkopeo("standalone-verify", "--public-key-file", "fixtures/pubring.gpg", manifestPath,
dockerReference, fixturesTestKeyFingerprint, signaturePath)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "Signature verified using fingerprint 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8, digest "+fixturesTestImageManifestDigest.String()+"\n", out) assert.Equal(t, "Signature verified using fingerprint 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8, digest "+fixturesTestImageManifestDigest.String()+"\n", out)
// Using a trust store // Using a public key file matching any public key
t.Setenv("GNUPGHOME", "") t.Setenv("GNUPGHOME", "")
out, err = runSkopeo("standalone-verify", "--truststore", "fixtures/pubring.gpg", manifestPath, out, err = runSkopeo("standalone-verify", "--public-key-file", "fixtures/pubring.gpg", manifestPath,
dockerReference, "any", signaturePath) dockerReference, "any", signaturePath)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "Signature verified using fingerprint 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8, digest "+fixturesTestImageManifestDigest.String()+"\n", out) assert.Equal(t, "Signature verified using fingerprint 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8, digest "+fixturesTestImageManifestDigest.String()+"\n", out)

View File

@@ -16,7 +16,7 @@ as per containers-policy.json(5).
_docker-reference_ A docker reference expected to identify the image in the signature _docker-reference_ A docker reference expected to identify the image in the signature
_key-fingerprint_ Expected identity of the signing key, or "any" to trust any known key _key-fingerprint_ Expected identity of the signing key, or "any" to trust any known key when using a public key file
_signature_ Path to signature file _signature_ Path to signature file
@@ -28,9 +28,9 @@ as per containers-policy.json(5).
Print usage statement Print usage statement
**--truststore** _truststore_ **--public-key-file** _public key file_
Trust store of public keys to use when verifying signatures. If this is not specified, keys from gpg home are used. File containing the public keys to use when verifying signatures. If this is not specified, keys from the GPG homedir are used.
## EXAMPLES ## EXAMPLES