Skip to content
This repository has been archived by the owner on Jul 19, 2022. It is now read-only.

Commit

Permalink
Add support for registries with self-signed certs
Browse files Browse the repository at this point in the history
* add TLS transport option to ggcr client
* add global --ca-cert-path flag to irel
* add global --skip-tls-verify flag to irel

Note: the test certificate expires in over 2000 years, which should be long
enough.
  • Loading branch information
st3v authored and glyn committed Nov 5, 2019
1 parent 5e5032e commit dc3df03
Show file tree
Hide file tree
Showing 14 changed files with 351 additions and 69 deletions.
6 changes: 3 additions & 3 deletions pkg/irel/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ package irel

import (
"fmt"
"log"

"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)

func init() { Root.AddCommand(newCmdCopy()) }
Expand All @@ -47,7 +47,7 @@ func copy(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", dstStr, err)
}

regClient := ggcr.NewRegistryClient()
regClient := mustGetRegistryClient()
dig, _, err := regClient.Copy(src, dst)
if err != nil {
log.Fatalf("copy failed: %v", err)
Expand Down
6 changes: 3 additions & 3 deletions pkg/irel/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ package irel

import (
"fmt"
"log"

"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)

func init() { Root.AddCommand(newCmdDigest()) }
Expand All @@ -43,7 +43,7 @@ func digest(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", refStr, err)
}

regClient := ggcr.NewRegistryClient()
regClient := mustGetRegistryClient()
dig, err := regClient.Digest(ref)
if err != nil {
log.Fatalf("digest failed: %v", err)
Expand Down
3 changes: 1 addition & 2 deletions pkg/irel/layout_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"log"

"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
)

Expand All @@ -41,7 +40,7 @@ func layoutAdd(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", refStr, err)
}

regClient := ggcr.NewRegistryClient()
regClient := mustGetRegistryClient()
layout, err := regClient.ReadLayout(layoutPath)
if err != nil {
layout, err = regClient.NewLayout(layoutPath)
Expand Down
14 changes: 7 additions & 7 deletions pkg/irel/layout_find.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ package irel

import (
"fmt"
"log"

"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)

func newCmdLayoutFind() *cobra.Command {
return &cobra.Command{
Use: "find LAYOUT_PATH REF",
Short: "find an image in an OCI image layout",
Args: cobra.ExactArgs(2),
Run: layoutFind,
Use: "find LAYOUT_PATH REF",
Short: "find an image in an OCI image layout",
Args: cobra.ExactArgs(2),
Run: layoutFind,
}
}

Expand All @@ -40,7 +40,7 @@ func layoutFind(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", refStr, err)
}

regClient := ggcr.NewRegistryClient()
regClient := mustGetRegistryClient()
layout, err := regClient.ReadLayout(layoutPath)
if err != nil {
log.Fatalf("failed to create OCI image layout: %v", err)
Expand Down
14 changes: 7 additions & 7 deletions pkg/irel/layout_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ package irel

import (
"fmt"
"log"

"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)

func newCmdLayoutPush() *cobra.Command {
return &cobra.Command{
Use: "push LAYOUT_PATH CONTENT_DIGEST REF",
Short: "copy an image with a given content digest from an OCI image layout to a remote repository",
Args: cobra.ExactArgs(3),
Run: layoutPush,
Use: "push LAYOUT_PATH CONTENT_DIGEST REF",
Short: "copy an image with a given content digest from an OCI image layout to a remote repository",
Args: cobra.ExactArgs(3),
Run: layoutPush,
}
}

Expand All @@ -45,7 +45,7 @@ func layoutPush(cmd *cobra.Command, args []string) {
log.Fatalf("invalid digest %q: %v", digStr, err)
}

regClient := ggcr.NewRegistryClient()
regClient := mustGetRegistryClient()
layout, err := regClient.ReadLayout(layoutPath)
if err != nil {
log.Fatalf("failed to access OCI image layout: %v", err)
Expand Down
39 changes: 33 additions & 6 deletions pkg/irel/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,39 @@

package irel

import "github.com/spf13/cobra"
import (
"log"

var Root = &cobra.Command{
Use: "irel",
Short: "irel is a tool for relocating container images",
Run: func(cmd *cobra.Command, _ []string) { cmd.Usage() },
DisableAutoGenTag: true,
"github.com/pivotal/image-relocation/pkg/registry"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/pivotal/image-relocation/pkg/transport"

"github.com/spf13/cobra"
)

var (
caCertPaths []string
skipTLSVerify bool

Root = &cobra.Command{
Use: "irel",
Short: "irel is a tool for relocating container images",
Run: func(cmd *cobra.Command, _ []string) { cmd.Usage() },
DisableAutoGenTag: true,
}
)

func init() {
Root.PersistentFlags().StringSliceVarP(&caCertPaths, "ca-cert-path", "", nil, "Path to CA certificate for verifying registry TLS certificates (can be repeated for multiple certificates)")
Root.PersistentFlags().BoolVarP(&skipTLSVerify, "skip-tls-verify", "", false, "Skip TLS certificate verification for registries")
}

func mustGetRegistryClient() registry.Client {
tport, err := transport.NewHttpTransport(caCertPaths, skipTLSVerify)
if err != nil {
log.Fatal(err)
}

return ggcr.NewRegistryClient(ggcr.WithTransport(tport))
}

40 changes: 31 additions & 9 deletions pkg/registry/ggcr/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package ggcr

import (
"fmt"
"net/http"
"os"

v1 "github.com/google/go-containerregistry/pkg/v1"
Expand All @@ -43,28 +44,49 @@ type RegistryClient interface {
NewImageFromIndex(img v1.ImageIndex) registry.Image
}

type manifestWriter func(i v1.Image, n image.Name) error
type indexWriter func(i v1.ImageIndex, n image.Name) error
type manifestWriter func(v1.Image, image.Name) error
type indexWriter func(v1.ImageIndex, image.Name) error

type client struct {
readRemoteImage func(n image.Name) (registry.Image, error)
readRemoteImage func(image.Name) (registry.Image, error)
writeRemoteImage manifestWriter
writeRemoteIndex indexWriter
}

var (
// Ensure client conforms to the relevant interfaces.
_ RegistryClient = &client{}
_ RegistryClient = &client{}
_ registry.Client = &client{}
)

// Option represents a functional option for NewRegistryClient.
type Option func(*client)

// WithTransport overrides the default transport used for remote operations, default is http.DefaultTransport.
func WithTransport(transport http.RoundTripper) Option {
return func(c *client) {
writeRemoteImageFunc := writeRemoteImage(transport)
writeRemoteIndexFunc := writeRemoteIndex(transport)

c.readRemoteImage = readRemoteImage(writeRemoteImageFunc, writeRemoteIndexFunc, transport)
c.writeRemoteImage = writeRemoteImageFunc
c.writeRemoteIndex = writeRemoteIndexFunc
}
}

// NewRegistryClient returns a new Client.
func NewRegistryClient() *client {
return &client{
readRemoteImage: readRemoteImage(writeRemoteImage, writeRemoteIndex),
writeRemoteImage: writeRemoteImage,
writeRemoteIndex: writeRemoteIndex,
func NewRegistryClient(options ...Option) *client {
client := &client{}

// default transport
WithTransport(http.DefaultTransport)(client)

// apply functional options
for _, opt := range options {
opt(client)
}

return client
}

func (r *client) Digest(n image.Name) (image.Digest, error) {
Expand Down
54 changes: 29 additions & 25 deletions pkg/registry/ggcr/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ package ggcr

import (
"errors"
"net/http"

"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/pivotal/image-relocation/pkg/registry"
"net/http"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
Expand All @@ -30,15 +31,14 @@ import (
)

var (
repoImageFunc = remote.Image
resolveFunc = authn.DefaultKeychain.Resolve
repoGetFunc = remote.Get
repoWriteFunc = remote.Write
repoIndexWriteFunc = remote.WriteIndex
)

func readRemoteImage(mfstWriter manifestWriter, idxWriter indexWriter) func(n image.Name) (registry.Image, error) {
return func(n image.Name) (i registry.Image, e error) {
func readRemoteImage(mfstWriter manifestWriter, idxWriter indexWriter, transport http.RoundTripper) func(image.Name) (registry.Image, error) {
return func(n image.Name) (registry.Image, error) {
auth, err := resolve(n)
if err != nil {
return nil, err
Expand All @@ -56,7 +56,7 @@ func readRemoteImage(mfstWriter manifestWriter, idxWriter indexWriter) func(n im
return nil, err
}

desc, err := repoGetFunc(ref, remote.WithAuth(auth))
desc, err := repoGetFunc(ref, remote.WithAuth(auth), remote.WithTransport(transport))
if err != nil {
return nil, err
}
Expand All @@ -80,32 +80,36 @@ func readRemoteImage(mfstWriter manifestWriter, idxWriter indexWriter) func(n im
}
}

func writeRemoteImage(i v1.Image, n image.Name) error {
auth, err := resolve(n)
if err != nil {
return err
}
func writeRemoteImage(transport http.RoundTripper) func(v1.Image, image.Name) error {
return func(i v1.Image, n image.Name) error {
auth, err := resolve(n)
if err != nil {
return err
}

ref, err := getWriteReference(n)
if err != nil {
return err
}
ref, err := getWriteReference(n)
if err != nil {
return err
}

return repoWriteFunc(ref, i, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport))
return repoWriteFunc(ref, i, remote.WithAuth(auth), remote.WithTransport(transport))
}
}

func writeRemoteIndex(i v1.ImageIndex, n image.Name) error {
auth, err := resolve(n)
if err != nil {
return err
}
func writeRemoteIndex(transport http.RoundTripper) func(v1.ImageIndex, image.Name) error {
return func(i v1.ImageIndex, n image.Name) error {
auth, err := resolve(n)
if err != nil {
return err
}

ref, err := getWriteReference(n)
if err != nil {
return err
}
ref, err := getWriteReference(n)
if err != nil {
return err
}

return repoIndexWriteFunc(ref, i, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport))
return repoIndexWriteFunc(ref, i, remote.WithAuth(auth), remote.WithTransport(transport))
}
}

func resolve(n image.Name) (authn.Authenticator, error) {
Expand Down
15 changes: 8 additions & 7 deletions pkg/registry/ggcr/remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ggcr
import (
"errors"
"fmt"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
Expand All @@ -15,11 +16,11 @@ import (

var _ = Describe("remote utilities", func() {
var (
imageName image.Name
mockImage *ggcrfakes.FakeImage
imageName image.Name
mockImage *ggcrfakes.FakeImage
testDigest string
testError error
err error
testError error
err error
)

BeforeEach(func() {
Expand All @@ -40,7 +41,7 @@ var _ = Describe("remote utilities", func() {

Describe("readRemoteImage", func() {
JustBeforeEach(func() {
_, err = readRemoteImage(nil, nil)(imageName)
_, err = readRemoteImage(nil, nil, nil)(imageName)
})

BeforeEach(func() {
Expand Down Expand Up @@ -79,7 +80,7 @@ var _ = Describe("remote utilities", func() {

Describe("writeRemoteImage", func() {
JustBeforeEach(func() {
err = writeRemoteImage(mockImage, imageName)
err = writeRemoteImage(nil)(mockImage, imageName)
})

Context("when writing to the repository succeeds", func() {
Expand Down Expand Up @@ -141,7 +142,7 @@ var _ = Describe("remote utilities", func() {
})

JustBeforeEach(func() {
err = writeRemoteIndex(mockIndex, imageName)
err = writeRemoteIndex(nil)(mockIndex, imageName)
})

Context("when writing to the repository succeeds", func() {
Expand Down
Loading

0 comments on commit dc3df03

Please sign in to comment.