Skip to content

Commit

Permalink
Merge pull request #264 from Infra-Red/specifiy-ca-certs
Browse files Browse the repository at this point in the history
Add ability to specify a CA certificate
  • Loading branch information
vito authored Feb 22, 2021
2 parents 3efedbd + 40734d2 commit d0107f5
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 16 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,24 @@ differences:
* `tls_key`: *Optional. Default `""`* TLS key for the notary server.
* `tls_cert`: *Optional. Default `""`* TLS certificate for the notary server.

* `ca_certs`: *Optional.* An array of PEM-encoded CA certificates:

```yaml
ca_certs:
- |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
- |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
```
Each entry specifies the x509 CA certificate for the trusted docker registry.
This is used to validate the certificate of the docker registry when the
registry's certificate is signed by a custom authority (or itself).
### Signing with Docker Hub
Configure Docker Content Trust for use with the [Docker Hub](https:/hub.docker.io) and Notary service by specifying the above source parameters as follows:
Expand Down
110 changes: 105 additions & 5 deletions check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package resource_test
import (
"bytes"
"encoding/json"
"encoding/pem"
"fmt"
"net/http"
"os/exec"
Expand All @@ -20,6 +21,8 @@ import (
)

var _ = Describe("Check", func() {
var actualErr error

var req struct {
Source resource.Source
Version *resource.Version
Expand Down Expand Up @@ -47,11 +50,11 @@ var _ = Describe("Check", func() {
cmd.Stdout = outBuf
cmd.Stderr = GinkgoWriter

err = cmd.Run()
Expect(err).ToNot(HaveOccurred())

err = json.Unmarshal(outBuf.Bytes(), &res)
Expect(err).ToNot(HaveOccurred())
actualErr = cmd.Run()
if actualErr == nil {
err = json.Unmarshal(outBuf.Bytes(), &res)
Expect(err).ToNot(HaveOccurred())
}
}

Describe("tracking a single tag", func() {
Expand All @@ -68,6 +71,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_STATIC_DIGEST},
}))
Expand All @@ -89,6 +94,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: PRIVATE_LATEST_STATIC_DIGEST},
}))
Expand Down Expand Up @@ -138,12 +145,69 @@ var _ = Describe("Check", func() {
})

It("falls back on fetching the manifest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_FAKE_DIGEST},
}))
})
})

Context("using a registry with self-signed certificate", func() {
var registry *ghttp.Server

BeforeEach(func() {
registry = ghttp.NewTLSServer()

registry.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/v2/"),
ghttp.RespondWith(http.StatusOK, `welcome to zombocom`),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/v2/"),
ghttp.RespondWith(http.StatusOK, `welcome to zombocom`),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("HEAD", "/v2/some/fake-image/manifests/latest"),
ghttp.RespondWith(http.StatusOK, ``, LATEST_FAKE_HEADERS),
),
)

req.Source.Repository = registry.Addr() + "/some/fake-image"
})

AfterEach(func() {
registry.Close()
})

When("the certificate is provided in 'source'", func() {
BeforeEach(func() {
certPem := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: registry.HTTPTestServer.Certificate().Raw,
})
Expect(certPem).ToNot(BeEmpty())

req.Source.DomainCerts = []string{string(certPem)}
})

It("it checks and returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_FAKE_DIGEST},
}))
})
})

When("the certificate is missing in 'source'", func() {
It("exits non-zero and returns an error", func() {
Expect(actualErr).To(HaveOccurred())
})
})
})

Context("against a mirror", func() {
var mirror *ghttp.Server

Expand Down Expand Up @@ -187,6 +251,8 @@ var _ = Describe("Check", func() {
})

It("it checks and returns the current digest using the registry declared in the repository and not using the mirror", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_FAKE_DIGEST},
}))
Expand Down Expand Up @@ -216,6 +282,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_FAKE_DIGEST},
}))
Expand Down Expand Up @@ -244,6 +312,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "1.32.0", Digest: latestDigest(req.Source.Name())},
}))
Expand All @@ -266,6 +336,8 @@ var _ = Describe("Check", func() {
})

It("returns the given digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_STATIC_DIGEST},
}))
Expand All @@ -277,6 +349,8 @@ var _ = Describe("Check", func() {
})

It("includes the tag in the response version", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_STATIC_DIGEST},
}))
Expand Down Expand Up @@ -304,6 +378,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: PRIVATE_LATEST_STATIC_DIGEST},
}))
Expand Down Expand Up @@ -351,6 +427,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
*req.Version,
}))
Expand Down Expand Up @@ -384,6 +462,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
*req.Version,
}))
Expand All @@ -407,6 +487,8 @@ var _ = Describe("Check", func() {
})

It("returns the previous digest and the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: OLDER_STATIC_DIGEST},
{Tag: "latest", Digest: LATEST_STATIC_DIGEST},
Expand Down Expand Up @@ -435,6 +517,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: PRIVATE_OLDER_STATIC_DIGEST},
{Tag: "latest", Digest: PRIVATE_LATEST_STATIC_DIGEST},
Expand Down Expand Up @@ -488,6 +572,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: OLDER_FAKE_DIGEST},
{Tag: "latest", Digest: LATEST_FAKE_DIGEST},
Expand Down Expand Up @@ -520,6 +606,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "1.32.0", Digest: OLDER_LIBRARY_DIGEST},
{Tag: "1.32.0", Digest: latestDigest(req.Source.Name())},
Expand All @@ -543,6 +631,8 @@ var _ = Describe("Check", func() {
})

It("returns only the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_STATIC_DIGEST},
}))
Expand All @@ -564,6 +654,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: PRIVATE_LATEST_STATIC_DIGEST},
}))
Expand Down Expand Up @@ -614,6 +706,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "latest", Digest: LATEST_FAKE_DIGEST},
}))
Expand Down Expand Up @@ -642,6 +736,8 @@ var _ = Describe("Check", func() {
})

It("returns the current digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{
{Tag: "1.32.0", Digest: latestDigest(req.Source.Name())},
}))
Expand All @@ -660,6 +756,8 @@ var _ = Describe("Check", func() {
})

It("returns empty digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{}))
})

Expand All @@ -679,6 +777,8 @@ var _ = Describe("Check", func() {
})

It("returns empty digest", func() {
Expect(actualErr).ToNot(HaveOccurred())

Expect(res).To(Equal([]resource.Version{}))
})
})
Expand Down
23 changes: 20 additions & 3 deletions commands/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,18 @@ func put(req resource.OutRequest, img v1.Image, tags []name.Tag) error {
identifiers = append(identifiers, tag.Identifier())
}

repo, err := name.NewRepository(req.Source.Repository)
if err != nil {
return fmt.Errorf("resolve repository name: %w", err)
}

opts, err := req.Source.AuthOptions(repo)
if err != nil {
return err
}

logrus.Infof("pushing tag(s) %s", strings.Join(identifiers, ", "))
err := remote.MultiWrite(images, remote.WithAuth(createAuth(req)))
err = remote.MultiWrite(images, opts...)
if err != nil {
return fmt.Errorf("pushing tag(s): %w", err)
}
Expand Down Expand Up @@ -248,8 +258,15 @@ func createAuth(req resource.OutRequest) *authn.Basic {
func aliasesToBump(req resource.OutRequest, repo name.Repository, ver *semver.Version) ([]name.Tag, error) {
variant := req.Source.Variant

opts := []remote.Option{}
opts = append(opts, remote.WithAuth(createAuth(req)))
repo, err := name.NewRepository(req.Source.Repository)
if err != nil {
return nil, fmt.Errorf("resolve repository name: %w", err)
}

opts, err := req.Source.AuthOptions(repo)
if err != nil {
return nil, err
}

versions, err := remote.List(repo, opts...)
if err != nil {
Expand Down
Loading

0 comments on commit d0107f5

Please sign in to comment.