Skip to content

Commit

Permalink
Support different verification options per image
Browse files Browse the repository at this point in the history
Different images will require different verification options. This
commit adds configuration that allows you to define different
'verifiers' for specific image references, or image reference patterns.

At the moment it supports verification by public key, or the existing
options, but should be expanded to include all supported options.

Also modifies the response from the provider to include an error
per-image checked, rather than returning any error as a 'system' error.

I've also removed the _invalid suffix from the key returned in the
response when there's an error. The presence of the 'error' field
indicates this better, I think.

Signed-off-by: Rob Best <[email protected]>
  • Loading branch information
ribbybibby committed Jan 11, 2022
1 parent f26799b commit 36cf786
Show file tree
Hide file tree
Showing 7 changed files with 638 additions and 285 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ RUN go mod download

COPY . .

RUN go build -o provider provider.go
RUN go build -o provider .

FROM $BASEIMAGE

Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,32 @@ $ cosign sign --key cosign.key devopps/signed:latest
```

So, once you are ready, let's apply these manifests one by one. It should allow deploying Pod for valid.yaml, and deny for the other one.

## Configuration

The provider can be configured with a configuration file passed with the
`-config-file=<file>` flag.

The verification options for specific image references can be configured by
defining verifiers.

If a matching verifier can't be found then it will return an error for that image
in the response.

```yaml
verifiers:
# Verify images in the my-project GCR registry with GCP KMS
- image: "eu.gcr.io/my-project/*"
options:
key: "gcpkms://projects/my-project/locations/global/keyRings/my-keyring/cryptoKeys/my-key"

# Verify images from my-registry with cosign.pub
- image: "my-registry:12345/*"
options:
key: "/cosign.pub"

# Verify any other image with the rekor server
- image: "*"
options:
rekorURL: "https://rekor.sigstore.dev"
```
93 changes: 93 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package main

import (
"fmt"
"os"

"gopkg.in/yaml.v3"
)

var (
// DefaultOptions are the default verification options
DefaultOptions = &CheckOptions{
RekorURL: "https://rekor.sigstore.dev",
}

// DefaultConfig is the configuration used when none is provided
DefaultConfig = &Config{
Verifiers: []Verifier{
{
Options: DefaultOptions,
},
},
}
)

// LoadConfig loads configuration from a file. If a file isn't provided then it
// returns the default configuration.
func LoadConfig(confFile string) (*Config, error) {
if confFile == "" {
return DefaultConfig, nil
}

var c *Config

yamlReader, err := os.Open(confFile)
if err != nil {
return c, fmt.Errorf("error reading config file: %s", err)
}
defer yamlReader.Close()
decoder := yaml.NewDecoder(yamlReader)
decoder.KnownFields(true)

if err = decoder.Decode(&c); err != nil {
return c, fmt.Errorf("error parsing config file: %s", err)
}

return c, nil
}

// Config configures the provider
type Config struct {
// Verifiers is a list of verifiers. The validator will iterate over
// this list until it finds a verifier that matches the image its
// validating.
Verifiers []Verifier `yaml:"verifiers"`
}

// Verifier verifies an image
type Verifier struct {
// Image is an image reference, either to a specific image or a pattern.
// Supports '*' and '?' in the pattern string.
Image string `yaml:"image,omitempty"`

// Options defines verification options
Options *CheckOptions `yaml:"options,omitempty"`
}

// UnmarshalYAML sets default options for the verifier config when they aren't
// provided
func (v *Verifier) UnmarshalYAML(unmarshal func(interface{}) error) error {
type rawVerifier Verifier
var raw rawVerifier
if err := unmarshal(&raw); err != nil {
return err
}

if raw.Options == nil {
raw.Options = DefaultOptions
}

*v = Verifier(raw)

return nil
}

// CheckOptions are the options used to verify the signature of an image
type CheckOptions struct {
// Key is a path to a public key file, KMS URI or Kubernetes Secret
Key string `yaml:"key,omitempty"`

// RekorURL is the address of a rekor STL server
RekorURL string `yaml:"rekorURL,omitempty"`
}
Loading

0 comments on commit 36cf786

Please sign in to comment.