Skip to content

Commit

Permalink
feat: oras using tls registry (#4633)
Browse files Browse the repository at this point in the history
* feat: oras using tls registry

when pushing artifacts to the embedded cluster registry we need to use
tls as it now uses a self signed registry.

* chore: use tls http server test

* fallback to pushing OCI artifacts with plain http

---------

Co-authored-by: Craig O'Donnell <[email protected]>
  • Loading branch information
ricardomaraschini and Craig O'Donnell authored May 23, 2024
1 parent 9d0130e commit 8d62dd3
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 9 deletions.
23 changes: 17 additions & 6 deletions pkg/image/airgap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"bufio"
"compress/gzip"
"context"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -167,12 +169,15 @@ func TagAndPushImagesFromBundle(airgapBundle string, options imagetypes.PushImag
return errors.Errorf("Airgap bundle format '%s' is not supported", airgap.Spec.Format)
}

transport := http.DefaultTransport.(*http.Transport).Clone()
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

pushEmbeddedArtifactsOpts := imagetypes.PushEmbeddedClusterArtifactsOptions{
Registry: options.Registry,
ChannelID: airgap.Spec.ChannelID,
UpdateCursor: airgap.Spec.UpdateCursor,
VersionLabel: airgap.Spec.VersionLabel,
HTTPClient: orasretry.DefaultClient,
HTTPClient: &http.Client{Transport: orasretry.NewTransport(transport)},
}
err = PushEmbeddedClusterArtifacts(airgapBundle, airgap.Spec.EmbeddedClusterArtifacts, pushEmbeddedArtifactsOpts)
if err != nil {
Expand Down Expand Up @@ -831,14 +836,20 @@ func pushOCIArtifact(opts imagetypes.PushOCIArtifactOptions) error {
Password: opts.Registry.Password,
}),
}
repository.PlainHTTP = true

_, err = oras.Copy(context.TODO(), orasFS, opts.Tag, repository, opts.Tag, oras.DefaultCopyOptions)
if err != nil {
return errors.Wrap(err, "failed to copy")
_, err1 := oras.Copy(context.TODO(), orasFS, opts.Tag, repository, opts.Tag, oras.DefaultCopyOptions)
if err1 == nil {
return nil
}

return nil
// try again with plain http
repository.PlainHTTP = true
_, err2 := oras.Copy(context.TODO(), orasFS, opts.Tag, repository, opts.Tag, oras.DefaultCopyOptions)
if err2 == nil {
return nil
}

return errors.Wrap(fmt.Errorf("https: %s, http: %s", err1, err2), "failed to copy")
}

type ProgressReport struct {
Expand Down
39 changes: 36 additions & 3 deletions pkg/image/airgap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestPushEmbeddedClusterArtifacts(t *testing.T) {
name string
airgapFiles map[string][]byte
artifactsToPush *kotsv1beta1.EmbeddedClusterArtifacts
useTLS bool
wantRegistryArtifacts map[string]string
wantErr bool
}{
Expand Down Expand Up @@ -70,6 +71,33 @@ func TestPushEmbeddedClusterArtifacts(t *testing.T) {
},
wantErr: false,
},
{
name: "has embedded cluster files and registry has TLS",
airgapFiles: map[string][]byte{
"airgap.yaml": []byte("this-is-the-airgap-metadata"),
"app.tar.gz": []byte("this-is-the-app-archive"),
"images/something": []byte("this-is-an-image"),
"embedded-cluster/test-app": []byte("this-is-the-binary"),
"embedded-cluster/charts.tar.gz": []byte("this-is-the-charts-bundle"),
"embedded-cluster/images-amd64.tar": []byte("this-is-the-images-bundle"),
"embedded-cluster/version-metadata.json": []byte("this-is-the-metadata"),
"embedded-cluster/some-file-TBD": []byte("this-is-an-arbitrary-file"),
},
artifactsToPush: &kotsv1beta1.EmbeddedClusterArtifacts{
BinaryAmd64: "embedded-cluster/test-app",
ImagesAmd64: "embedded-cluster/images-amd64.tar",
Charts: "embedded-cluster/charts.tar.gz",
Metadata: "embedded-cluster/version-metadata.json",
},
useTLS: true,
wantRegistryArtifacts: map[string]string{
fmt.Sprintf("%s/embedded-cluster/test-app", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel),
fmt.Sprintf("%s/embedded-cluster/charts.tar.gz", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel),
fmt.Sprintf("%s/embedded-cluster/images-amd64.tar", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel),
fmt.Sprintf("%s/embedded-cluster/version-metadata.json", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel),
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -80,7 +108,7 @@ func TestPushEmbeddedClusterArtifacts(t *testing.T) {
}

pushedRegistryArtifacts := make(map[string]string)
mockRegistryServer := newMockRegistryServer(pushedRegistryArtifacts)
mockRegistryServer := newMockRegistryServer(pushedRegistryArtifacts, tt.useTLS)
defer mockRegistryServer.Close()

u, err := url.Parse(mockRegistryServer.URL)
Expand Down Expand Up @@ -139,8 +167,13 @@ func createTestAirgapBundle(airgapFiles map[string][]byte, dstPath string) error
return nil
}

func newMockRegistryServer(pushedRegistryArtifacts map[string]string) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
func newMockRegistryServer(pushedRegistryArtifacts map[string]string, useTLS bool) *httptest.Server {
newServerFn := httptest.NewServer
if useTLS {
newServerFn = httptest.NewTLSServer
}

return newServerFn(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
blobsRegex := regexp.MustCompile(`/v2/(.+)/blobs/(.*)`)
manifestsRegex := regexp.MustCompile(`/v2/(.+)/manifests/(.*)`)

Expand Down

0 comments on commit 8d62dd3

Please sign in to comment.