Skip to content

Commit

Permalink
Refine Security Model (#9)
Browse files Browse the repository at this point in the history
- Drop GnuPG
- Flatten to single manifest to be signed
- Update docuementation

Signed-off-by: Shiwei Zhang <shizh@microsoft.com>
  • Loading branch information
shizhMSFT committed Jul 25, 2020
1 parent 4b61e4e commit 2d508ed
Show file tree
Hide file tree
Showing 18 changed files with 160 additions and 534 deletions.
2 changes: 1 addition & 1 deletion cmd/nv2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func main() {
app := &cli.App{
Name: "nv2",
Usage: "Notary V2 - Prototype",
Version: "0.1.0",
Version: "0.1.1",
Authors: []*cli.Author{
{
Name: "Shiwei Zhang",
Expand Down
29 changes: 6 additions & 23 deletions cmd/nv2/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/notaryproject/nv2/pkg/signature"
"github.com/notaryproject/nv2/pkg/signature/gpg"
"github.com/notaryproject/nv2/pkg/signature/x509"
"github.com/urfave/cli/v2"
)
Expand All @@ -23,31 +22,19 @@ var signCommand = &cli.Command{
&cli.StringFlag{
Name: "method",
Aliases: []string{"m"},
Usage: "siging method",
Usage: "signing method",
Required: true,
},
&cli.StringFlag{
Name: "key",
Aliases: []string{"k"},
Usage: "siging key file [x509]",
Usage: "signing key file [x509]",
TakesFile: true,
},
&cli.StringFlag{
Name: "cert",
Aliases: []string{"c"},
Usage: "siging cert [x509]",
TakesFile: true,
},
&cli.StringFlag{
Name: "key-ring",
Usage: "gpg public key ring file [gpg]",
Value: gpg.DefaultSecretKeyRingPath(),
TakesFile: true,
},
&cli.StringFlag{
Name: "identity",
Aliases: []string{"i"},
Usage: "signer identity [gpg]",
Usage: "signing cert [x509]",
TakesFile: true,
},
&cli.DurationFlag{
Expand Down Expand Up @@ -100,13 +87,13 @@ func runSign(ctx *cli.Context) error {
}
path := ctx.String("output")
if path == "" {
path = strings.Split(content.Manifests[0].Digest, ":")[1] + ".nv2"
path = strings.Split(content.Manifest.Digest, ":")[1] + ".nv2"
}
if err := ioutil.WriteFile(path, sigmaJSON, 0666); err != nil {
return err
}

fmt.Println(content.Manifests[0].Digest)
fmt.Println(content.Manifest.Digest)
return nil
}

Expand All @@ -119,10 +106,8 @@ func prepareContentForSigning(ctx *cli.Context) (signature.Content, error) {
now := time.Now()
nowUnix := now.Unix()
content := signature.Content{
Manifest: manifest,
IssuedAt: nowUnix,
Manifests: []signature.Manifest{
manifest,
},
}
if expiry := ctx.Duration("expiry"); expiry != 0 {
content.NotBefore = nowUnix
Expand All @@ -140,8 +125,6 @@ func getSchemeForSigning(ctx *cli.Context) (*signature.Scheme, error) {
switch method := ctx.String("method"); method {
case "x509":
signer, err = x509.NewSignerFromFiles(ctx.String("key"), ctx.String("cert"))
case "gpg":
signer, err = gpg.NewSigner(ctx.String("key-ring"), ctx.String("identity"))
default:
return nil, fmt.Errorf("unsupported signing method: %s", method)
}
Expand Down
31 changes: 1 addition & 30 deletions cmd/nv2/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/notaryproject/nv2/internal/crypto"
"github.com/notaryproject/nv2/pkg/signature"
"github.com/notaryproject/nv2/pkg/signature/gpg"
x509nv2 "github.com/notaryproject/nv2/pkg/signature/x509"
"github.com/urfave/cli/v2"
)
Expand Down Expand Up @@ -36,16 +35,6 @@ var verifyCommand = &cli.Command{
Usage: "CA certs for verification [x509]",
TakesFile: true,
},
&cli.StringFlag{
Name: "key-ring",
Usage: "gpg public key ring file [gpg]",
Value: gpg.DefaultPublicKeyRingPath(),
TakesFile: true,
},
&cli.BoolFlag{
Name: "disable-gpg",
Usage: "disable GPG for verification [gpg]",
},
usernameFlag,
passwordFlag,
insecureFlag,
Expand Down Expand Up @@ -73,7 +62,7 @@ func runVerify(ctx *cli.Context) error {
if err != nil {
return err
}
if !containsManifest(content.Manifests, manifest) {
if content.Manifest.Digest != manifest.Digest || content.Manifest.Size != manifest.Size {
return fmt.Errorf("verification failure: manifest is not signed: %s", manifest.Digest)
}

Expand All @@ -82,15 +71,6 @@ func runVerify(ctx *cli.Context) error {
return nil
}

func containsManifest(set []signature.Manifest, target signature.Manifest) bool {
for _, manifest := range set {
if manifest.Digest == target.Digest && manifest.Size == target.Size {
return true
}
}
return false
}

func readSignatrueFile(path string) (sig signature.Signed, err error) {
file, err := os.Open(path)
if err != nil {
Expand All @@ -111,15 +91,6 @@ func getSchemeForVerification(ctx *cli.Context) (*signature.Scheme, error) {
}
scheme.RegisterVerifier(verifier)

// add gpg verifier
if !ctx.Bool("disable-gpg") {
verifier, err := gpg.NewVerifier(ctx.String("key-ring"))
if err != nil {
return nil, err
}
scheme.RegisterVerifier(verifier)
}

return scheme, nil
}

Expand Down
3 changes: 0 additions & 3 deletions docs/distribution/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,3 @@ paths:
x509_kid_config:
externalValue: "../signature/examples/x509_kid.nv2.json"
description: A x509 signature containing a signing key ID reference.
gpg_config:
externalValue: "../signature/examples/gpg.nv2.json"
description: A gpg signature containing the public key reference in the signature.
37 changes: 16 additions & 21 deletions docs/distribution/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,35 @@ docker build -t hello-world:dev .
Sign image `hello-world:dev`.

```shell
docker generate manifest hello-world:dev | nv2 sign -m gpg -i demo -o hello-world.nv2
docker generate manifest hello-world:dev | nv2 sign -m x509 -k key.pem -o hello-world.nv2
```

This creates a signature `hello-world.nv2`.

```json
{
"signed": {
"iat": 1595418878,
"manifests": [
{
"signed": {
"digest": "sha256:3351c53952446db17d21b86cfe5829ae70f823aff5d410fbf09dff820a39ab55",
"size": 528
}
"size": 528,
"iat": 1595562742
},
"signatures": [
{
"typ": "x509",
"sig": "UhKwzvYsYN/IBWT7N/19HuG6x/Jo15OrWlwB6X/AySMbnB76ZvzID6zHZxD1l9bDRugAL+HV1KGQV1Vv6P9b7NosT2Z0mbVeTdMltdZndRTZkv5ozZtUXgknuGg9EkvvNLP3THsfK6Tm5dU3uk+rdk//cJ+T9/sYizt0zzAXC0gR/MJ3SxXwaGyQ6TqqQr94QyzPgEpn5ActZwNJ4WRPRpTutic95Na99cxjAYLKyhusPUYbXu1BICUv2EkUviSISrtyM+yHe4tX1m5Q4Qc0+labgsD3K82ezCGhRYQb2jCPSlDw0r2x1s3KbK2dlGXpSgz9DrhM+x4L2UEyp0cnsg==",
"alg": "RS256",
"kid": "DD2E:DW7J:OVJK:KCZR:2PGY:SYC5:WFJF:RMMV:FH6W:VGYM:2WW4:7ZGC"
}
]
},
"signatures": [
{
"typ": "gpg",
"sig": "wsDcBAABCAAQBQJfGCj+CRDvXc1GQtqlQgAA+0QMABcsQ0wU2oY78SgHkm7MsYyHdsAkrWBpLG1hRT02InRj18LUmnwGrvpl6sZm7h5pYbfAg1tST9ta+KQCCXNzP4axGS6cNwilPh7V8kUCgXSPaYyzHIptpBbr5HIaOGBCNPIJTFmnvKGYum1AZng+YudRY2UalS1K4vYWMFEsS5xUJNwoHk06nr+DY68QEBUpBGf689iSH7eIGE9XN4+1mtpnOHhI33FbjCFf3ksh+caE91gch/H4H4CQ5RRfjuvnD0xEBVDCVA/0XygBR1IGT9upoVFUA8XNbuhtATej1MHpOd3mIfeg1rBb2sP0j5tZrbyjBBBB4EbI2GfRYfczlaqfRvmAug4AI9Ya7/RFaZTX15A9X+zTpLH0I34BWwh6BKF9TwoFybFPJODYdZ0+rOmE9Renlc4GwPn0LnXX/PVQ3h6rlWznpdaVUFSPYhPg4bbQnW3XL9nCM8zPu2oVoQGVVNqhIVZpq1es7zc0BkrTT+n3eJyBG/WiLpxwGJneNw==",
"iss": "Demo User <demo@example.com>"
}
]
}
```
```

### Validate

Validate image `hello-world:dev`.

```
$ docker generate manifest hello-world:dev | nv2 verify -f hello-world.nv2
$ docker generate manifest hello-world:dev | nv2 verify -f hello-world.nv2 -c cert.pem
sha256:3351c53952446db17d21b86cfe5829ae70f823aff5d410fbf09dff820a39ab55
```

Expand All @@ -61,7 +58,7 @@ sha256:3351c53952446db17d21b86cfe5829ae70f823aff5d410fbf09dff820a39ab55
Sign image `hello-world:dev`.

```shell
docker generate manifest hello-world:dev | nv2 sign -m gpg -i demo -o hello-world.nv2
docker generate manifest hello-world:dev | nv2 sign -m x509 -k key.pem -o hello-world.nv2
```

This creates a signature `hello-world.nv2`.
Expand Down Expand Up @@ -94,8 +91,6 @@ A consumer of the target artifact, such as an orchestrator deploying an image, c
Fetch the signatures on this artifact form the registry and verify each one of them (or a configured few). After fetching the signature artifact `hello-world.nv2`, the system will do the following equivalent

```
$ nv2 verify -f hello-world.nv2 --insecure docker://localhost:5000/hello-world:v1.0
$ nv2 verify -f hello-world.nv2 -c cert.pem --insecure docker://localhost:5000/hello-world:v1.0
sha256:3351c53952446db17d21b86cfe5829ae70f823aff5d410fbf09dff820a39ab55
```

As in our example, if `gpg` signatures are used, the consumer needs to have the verification keys configured in their local keyring.
Loading

0 comments on commit 2d508ed

Please sign in to comment.