Add lookaside and lookaside-staging, hide sigstore and sigstore-staging

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
Miloslav Trmač 2022-07-11 20:30:54 +02:00
parent c1a12dccd3
commit 3766acbf59
6 changed files with 92 additions and 68 deletions

View File

@ -1,14 +1,14 @@
docker:
example.com:
sigstore: https://sigstore.example.com
lookaside: https://lookaside.example.com
registry.test.example.com:
sigstore: http://registry.test.example.com/sigstore
lookaside: http://registry.test.example.com/lookaside
registry.test.example.com:8888:
sigstore: http://registry.test.example.com:8889/sigstore
sigstore-staging: https://registry.test.example.com:8889/sigstore/specialAPIserverWhichDoesNotExist
lookaside: http://registry.test.example.com:8889/lookaside
lookaside-staging: https://registry.test.example.com:8889/lookaside/specialAPIserverWhichDoesNotExist
localhost:
sigstore: file:///home/mitr/mydevelopment1
lookaside: file:///home/mitr/mydevelopment1
localhost:8080:
sigstore: file:///home/mitr/mydevelopment2
lookaside: file:///home/mitr/mydevelopment2
localhost/invalid/url/test:
sigstore: ":emptyscheme"
lookaside: ":emptyscheme"

View File

@ -1,12 +1,12 @@
default-docker:
sigstore: file:///mnt/companywide/signatures/for/other/repositories
lookaside: file:///mnt/companywide/signatures/for/other/repositories
docker:
docker.io/contoso:
sigstore: https://sigstore.contoso.com/fordocker
lookaside: https://lookaside.contoso.com/fordocker
docker.io/centos:
sigstore: https://sigstore.centos.org/
lookaside: https://lookaside.centos.org/
docker.io/centos/mybetaproduct:
sigstore: http://localhost:9999/mybetaWIP/sigstore
sigstore-staging: file:///srv/mybetaWIP/sigstore
lookaside: http://localhost:9999/mybetaWIP/lookaside
lookaside-staging: file:///srv/mybetaWIP/lookaside
docker.io/centos/mybetaproduct:latest:
sigstore: https://sigstore.centos.org/
lookaside: https://lookaside.centos.org/

View File

@ -47,8 +47,10 @@ type registryConfiguration struct {
// registryNamespace defines lookaside locations for a single namespace.
type registryNamespace struct {
SigStore string `json:"sigstore"` // For reading, and if SigStoreStaging is not present, for writing.
SigStoreStaging string `json:"sigstore-staging"` // For writing only.
Lookaside string `json:"lookaside"` // For reading, and if LookasideStaging is not present, for writing.
LookasideStaging string `json:"lookaside-staging"` // For writing only.
SigStore string `json:"sigstore"` // For compatibility, deprecated in favor of Lookaside.
SigStoreStaging string `json:"sigstore-staging"` // For compatibility, deprecated in favor of LookasideStaging.
UseCosignAttachments *bool `json:"use-cosign-attachments,omitempty"`
}
@ -261,12 +263,22 @@ func (config *registryConfiguration) useCosignAttachments(ref dockerReference) b
// ns.signatureTopLevel returns an URL string configured in ns for ref, for write access if “write”.
// or "" if nothing has been configured.
func (ns registryNamespace) signatureTopLevel(write bool) string {
if write && ns.SigStoreStaging != "" {
logrus.Debugf(` Using %s`, ns.SigStoreStaging)
return ns.SigStoreStaging
if write {
if ns.LookasideStaging != "" {
logrus.Debugf(` Using "lookaside-staging" %s`, ns.LookasideStaging)
return ns.LookasideStaging
}
if ns.SigStoreStaging != "" {
logrus.Debugf(` Using "sigstore-staging" %s`, ns.SigStoreStaging)
return ns.SigStoreStaging
}
}
if ns.Lookaside != "" {
logrus.Debugf(` Using "lookaside" %s`, ns.Lookaside)
return ns.Lookaside
}
if ns.SigStore != "" {
logrus.Debugf(` Using %s`, ns.SigStore)
logrus.Debugf(` Using "sigstore" %s`, ns.SigStore)
return ns.SigStore
}
return ""

View File

@ -45,7 +45,7 @@ func TestSignatureStorageBaseURL(t *testing.T) {
dockerRefFromString(t, "//example.com/my/project"), false)
assert.NoError(t, err)
require.NotNil(t, base)
assert.Equal(t, "https://sigstore.example.com/my/project", base.String())
assert.Equal(t, "https://lookaside.example.com/my/project", base.String())
}
func TestRegistriesDirPath(t *testing.T) {
@ -157,10 +157,10 @@ func TestLoadAndMergeConfig(t *testing.T) {
err = os.Mkdir(duplicateDefault, 0755)
require.NoError(t, err)
err = os.WriteFile(filepath.Join(duplicateDefault, "0.yaml"),
[]byte("default-docker:\n sigstore: file:////tmp/something"), 0644)
[]byte("default-docker:\n lookaside: file:////tmp/something"), 0644)
require.NoError(t, err)
err = os.WriteFile(filepath.Join(duplicateDefault, "1.yaml"),
[]byte("default-docker:\n sigstore: file:////tmp/different"), 0644)
[]byte("default-docker:\n lookaside: file:////tmp/different"), 0644)
require.NoError(t, err)
_, err = loadAndMergeConfig(duplicateDefault)
assert.ErrorContains(t, err, "0.yaml")
@ -171,10 +171,10 @@ func TestLoadAndMergeConfig(t *testing.T) {
err = os.Mkdir(duplicateNS, 0755)
require.NoError(t, err)
err = os.WriteFile(filepath.Join(duplicateNS, "0.yaml"),
[]byte("docker:\n example.com:\n sigstore: file:////tmp/something"), 0644)
[]byte("docker:\n example.com:\n lookaside: file:////tmp/something"), 0644)
require.NoError(t, err)
err = os.WriteFile(filepath.Join(duplicateNS, "1.yaml"),
[]byte("docker:\n example.com:\n sigstore: file:////tmp/different"), 0644)
[]byte("docker:\n example.com:\n lookaside: file:////tmp/different"), 0644)
require.NoError(t, err)
_, err = loadAndMergeConfig(duplicateNS)
assert.ErrorContains(t, err, "0.yaml")
@ -184,28 +184,28 @@ func TestLoadAndMergeConfig(t *testing.T) {
config, err = loadAndMergeConfig("fixtures/registries.d")
require.NoError(t, err)
assert.Equal(t, &registryConfiguration{
DefaultDocker: &registryNamespace{SigStore: "file:///mnt/companywide/signatures/for/other/repositories"},
DefaultDocker: &registryNamespace{Lookaside: "file:///mnt/companywide/signatures/for/other/repositories"},
Docker: map[string]registryNamespace{
"example.com": {SigStore: "https://sigstore.example.com"},
"registry.test.example.com": {SigStore: "http://registry.test.example.com/sigstore"},
"registry.test.example.com:8888": {SigStore: "http://registry.test.example.com:8889/sigstore", SigStoreStaging: "https://registry.test.example.com:8889/sigstore/specialAPIserverWhichDoesNotExist"},
"localhost": {SigStore: "file:///home/mitr/mydevelopment1"},
"localhost:8080": {SigStore: "file:///home/mitr/mydevelopment2"},
"localhost/invalid/url/test": {SigStore: ":emptyscheme"},
"docker.io/contoso": {SigStore: "https://sigstore.contoso.com/fordocker"},
"docker.io/centos": {SigStore: "https://sigstore.centos.org/"},
"example.com": {Lookaside: "https://lookaside.example.com"},
"registry.test.example.com": {Lookaside: "http://registry.test.example.com/lookaside"},
"registry.test.example.com:8888": {Lookaside: "http://registry.test.example.com:8889/lookaside", LookasideStaging: "https://registry.test.example.com:8889/lookaside/specialAPIserverWhichDoesNotExist"},
"localhost": {Lookaside: "file:///home/mitr/mydevelopment1"},
"localhost:8080": {Lookaside: "file:///home/mitr/mydevelopment2"},
"localhost/invalid/url/test": {Lookaside: ":emptyscheme"},
"docker.io/contoso": {Lookaside: "https://lookaside.contoso.com/fordocker"},
"docker.io/centos": {Lookaside: "https://lookaside.centos.org/"},
"docker.io/centos/mybetaproduct": {
SigStore: "http://localhost:9999/mybetaWIP/sigstore",
SigStoreStaging: "file:///srv/mybetaWIP/sigstore",
Lookaside: "http://localhost:9999/mybetaWIP/lookaside",
LookasideStaging: "file:///srv/mybetaWIP/lookaside",
},
"docker.io/centos/mybetaproduct:latest": {SigStore: "https://sigstore.centos.org/"},
"docker.io/centos/mybetaproduct:latest": {Lookaside: "https://lookaside.centos.org/"},
},
}, config)
}
func TestRegistryConfigurationSignatureTopLevel(t *testing.T) {
config := registryConfiguration{
DefaultDocker: &registryNamespace{SigStore: "=default", SigStoreStaging: "=default+w"},
DefaultDocker: &registryNamespace{Lookaside: "=default", LookasideStaging: "=default+w"},
Docker: map[string]registryNamespace{},
}
for _, ns := range []string{
@ -217,7 +217,7 @@ func TestRegistryConfigurationSignatureTopLevel(t *testing.T) {
"example.com/ns1/ns2/repo",
"example.com/ns1/ns2/repo:notlatest",
} {
config.Docker[ns] = registryNamespace{SigStore: ns, SigStoreStaging: ns + "+w"}
config.Docker[ns] = registryNamespace{Lookaside: ns, LookasideStaging: ns + "+w"}
}
for _, c := range []struct{ input, expected string }{
@ -241,7 +241,7 @@ func TestRegistryConfigurationSignatureTopLevel(t *testing.T) {
config = registryConfiguration{
Docker: map[string]registryNamespace{
"unmatched": {SigStore: "a", SigStoreStaging: "b"},
"unmatched": {Lookaside: "a", LookasideStaging: "b"},
},
}
dr := dockerRefFromString(t, "//thisisnotmatched")
@ -257,14 +257,24 @@ func TestRegistryNamespaceSignatureTopLevel(t *testing.T) {
forWriting bool
expected string
}{
{registryNamespace{SigStoreStaging: "a", SigStore: "b"}, true, "a"},
{registryNamespace{SigStoreStaging: "a", SigStore: "b"}, false, "b"},
{registryNamespace{SigStore: "b"}, true, "b"},
{registryNamespace{SigStore: "b"}, false, "b"},
{registryNamespace{SigStoreStaging: "a"}, true, "a"},
{registryNamespace{SigStoreStaging: "a"}, false, ""},
{registryNamespace{LookasideStaging: "a", Lookaside: "b"}, true, "a"},
{registryNamespace{LookasideStaging: "a", Lookaside: "b"}, false, "b"},
{registryNamespace{Lookaside: "b"}, true, "b"},
{registryNamespace{Lookaside: "b"}, false, "b"},
{registryNamespace{LookasideStaging: "a"}, true, "a"},
{registryNamespace{LookasideStaging: "a"}, false, ""},
{registryNamespace{}, true, ""},
{registryNamespace{}, false, ""},
{registryNamespace{LookasideStaging: "a", Lookaside: "b", SigStoreStaging: "c", SigStore: "d"}, true, "a"},
{registryNamespace{Lookaside: "b", SigStoreStaging: "c", SigStore: "d"}, true, "c"},
{registryNamespace{Lookaside: "b", SigStore: "d"}, true, "b"},
{registryNamespace{SigStore: "d"}, true, "d"},
{registryNamespace{LookasideStaging: "a", Lookaside: "b", SigStoreStaging: "c", SigStore: "d"}, false, "b"},
{registryNamespace{Lookaside: "b", SigStoreStaging: "c", SigStore: "d"}, false, "b"},
{registryNamespace{Lookaside: "b", SigStore: "d"}, false, "b"},
{registryNamespace{SigStore: "d"}, false, "d"},
} {
res := c.ns.signatureTopLevel(c.forWriting)
assert.Equal(t, c.expected, res, fmt.Sprintf("%#v %v", c.ns, c.forWriting))

View File

@ -73,16 +73,18 @@ If no `docker` section can be found for the container image, and no `default-doc
A single configuration section is selected for a container image using the process
described above. The configuration section is a YAML mapping, with the following keys:
- `sigstore-staging` defines an URL of of the signature storage, used for editing it (adding or deleting signatures).
<!-- `sigstore` and `sigstore-staging` are deprecated and intentionally not documented here. -->
This key is optional; if it is missing, `sigstore` below is used.
- `lookaside-staging` defines an URL of of the signature storage, used for editing it (adding or deleting signatures).
- `sigstore` defines an URL of the signature storage.
This key is optional; if it is missing, `lookaside` below is used.
- `lookaside` defines an URL of the signature storage.
This URL is used for reading existing signatures,
and if `sigstore-staging` does not exist, also for adding or removing them.
and if `lookaside-staging` does not exist, also for adding or removing them.
This key is optional; if it is missing, no signature storage is defined (no signatures
are download along with images, adding new signatures is possible only if `sigstore-staging` is defined).
are download along with images, adding new signatures is possible only if `lookaside-staging` is defined).
- `use-cosign-attachments` specifies whether Cosign image attachments (signatures, attestations and the like) are going to be read/written along with the image.
If disabled, the images are treated as if no attachments exist; attempts to write attachments fail.
@ -96,11 +98,11 @@ The following demonstrates how to to consume and run images from various registr
```yaml
docker:
registry.database-supplier.com:
sigstore: https://sigstore.database-supplier.com
lookaside: https://lookaside.database-supplier.com
distribution.great-middleware.org:
sigstore: https://security-team.great-middleware.org/sigstore
lookaside: https://security-team.great-middleware.org/lookaside
docker.io/web-framework:
sigstore: https://sigstore.web-framework.io:8080
lookaside: https://lookaside.web-framework.io:8080
```
### Developing and Signing Containers, Staging Signatures
@ -114,13 +116,13 @@ For developers in `example.com`:
```yaml
docker:
registry.example.com:
sigstore: https://registry-sigstore.example.com
lookaside: https://registry-lookaside.example.com
registry.example.com/mydepartment:
sigstore: https://sigstore.mydepartment.example.com
sigstore-staging: file:///mnt/mydepartment/sigstore-staging
lookaside: https://lookaside.mydepartment.example.com
lookaside-staging: file:///mnt/mydepartment/lookaside-staging
registry.example.com/mydepartment/myproject:mybranch:
sigstore: http://localhost:4242/sigstore
sigstore-staging: file:///home/useraccount/webroot/sigstore
lookaside: http://localhost:4242/lookaside
lookaside-staging: file:///home/useraccount/webroot/lookaside
```
### A Global Default
@ -130,7 +132,7 @@ without listing each domain individually. This is expected to rarely happen, usu
```yaml
default-docker:
sigstore-staging: file:///mnt/company/common-sigstore-staging
lookaside-staging: file:///mnt/company/common-lookaside-staging
```
# AUTHORS

View File

@ -26,13 +26,13 @@ a simple static web server serving a directory structure created by writing to a
e.g. a HTTP server reading signatures from a database.)
The usual workflow for producing and distributing images using the separate storage mechanism
is to configure the repository in `registries.d` with `sigstore-staging` URL pointing to a private
`file:///` staging area, and a `sigstore` URL pointing to a public web server.
is to configure the repository in `registries.d` with `lookaside-staging` URL pointing to a private
`file:///` staging area, and a `lookaside` URL pointing to a public web server.
To publish an image, the image author would sign the image as necessary (e.g. using `skopeo copy`),
and then copy the created directory structure from the `file:///` staging area
to a subdirectory of a webroot of the public web server so that they are accessible using the public `sigstore` URL.
to a subdirectory of a webroot of the public web server so that they are accessible using the public `lookaside` URL.
The author would also instruct consumers of the image to, or provide a `registries.d` configuration file to,
set up a `sigstore` URL pointing to the public web server.
set up a `lookaside` URL pointing to the public web server.
### Path structure
@ -63,15 +63,15 @@ and no way to download all of the signatures at once.
For a docker/distribution image available as `busybox@sha256:817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e`
(or as `busybox:latest` if the `latest` tag points to to a manifest with the same digest),
and with a `registries.d` configuration specifying a `sigstore` URL `https://example.com/sigstore` for the same image,
and with a `registries.d` configuration specifying a `lookaside` URL `https://example.com/lookaside` for the same image,
the following URLs would be accessed to download all signatures:
> - `https://example.com/sigstore/library/busybox@sha256=817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e/signature-1`
> - `https://example.com/sigstore/library/busybox@sha256=817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e/signature-2`
> - `https://example.com/lookaside/library/busybox@sha256=817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e/signature-1`
> - `https://example.com/lookaside/library/busybox@sha256=817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e/signature-2`
> - …
For a docker/distribution image available as `example.com/ns1/ns2/ns3/repo@somedigest:digestvalue` and the same
`sigstore` URL, the signatures would be available at
> `https://example.com/sigstore/ns1/ns2/ns3/repo@somedigest=digestvalue/signature-1`
`lookaside` URL, the signatures would be available at
> `https://example.com/lookaside/ns1/ns2/ns3/repo@somedigest=digestvalue/signature-1`
and so on.