Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: allow HTTPS for localhost #1107

Merged
merged 10 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions cmd/oras/internal/option/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import (
// Remote options struct.
type Remote struct {
CACertFilePath string
PlainHTTP bool
qweeah marked this conversation as resolved.
Show resolved Hide resolved
Insecure bool
Configs []string
Username string
Expand All @@ -56,6 +55,7 @@ type Remote struct {
headerFlags []string
headers http.Header
warned map[string]*sync.Map
plainHTTP func() (plainHTTP bool, enforced bool)
}

// EnableDistributionSpecFlag set distribution specification flag as applicable.
Expand Down Expand Up @@ -98,7 +98,11 @@ func (opts *Remote) ApplyFlagsWithPrefix(fs *pflag.FlagSet, prefix, description
fs.StringVarP(&opts.Username, flagPrefix+"username", shortUser, "", notePrefix+"registry username")
fs.StringVarP(&opts.Password, flagPrefix+"password", shortPassword, "", notePrefix+"registry password or identity token")
fs.BoolVarP(&opts.Insecure, flagPrefix+"insecure", "", false, "allow connections to "+notePrefix+"SSL registry without certs")
fs.BoolVarP(&opts.PlainHTTP, flagPrefix+"plain-http", "", false, "allow insecure connections to "+notePrefix+"registry without SSL check")
plainHTTPFlagName := flagPrefix + "plain-http"
plainHTTP := fs.Bool(plainHTTPFlagName, false, "allow insecure connections to "+notePrefix+"registry without SSL check")
opts.plainHTTP = func() (bool, bool) {
return *plainHTTP, fs.Changed(plainHTTPFlagName)
}
fs.StringVarP(&opts.CACertFilePath, flagPrefix+"ca-file", "", "", "server certificate authority file for the remote "+notePrefix+"registry")
fs.StringArrayVarP(&opts.resolveFlag, flagPrefix+"resolve", "", nil, "customized DNS for "+notePrefix+"registry, formatted in `host:port:address[:address_port]`")
fs.StringArrayVarP(&opts.Configs, flagPrefix+"registry-config", "", nil, "`path` of the authentication file for "+notePrefix+"registry")
Expand Down Expand Up @@ -305,9 +309,14 @@ func (opts *Remote) NewRepository(reference string, common Common, logger logrus

// isPlainHttp returns the plain http flag for a given registry.
func (opts *Remote) isPlainHttp(registry string) bool {
plainHTTP, enforced := opts.plainHTTP()
if enforced {
return plainHTTP
}
host, _, _ := net.SplitHostPort(registry)
if host == "localhost" || registry == "localhost" {
// not specified, defaults to plain http for localhost
return true
}
return opts.PlainHTTP
return plainHTTP
}
47 changes: 45 additions & 2 deletions cmd/oras/internal/option/remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ func TestRemote_authClient_resolve(t *testing.T) {
}
}

func plainHTTPEnabled() (plainHTTP bool, fromFlag bool) {
return true, true
}
func HTTPSEnabled() (plainHTTP bool, fromFlag bool) {
return false, true
}
func plainHTTPNotSpecified() (plainHTTP bool, fromFlag bool) {
return false, false
}

func TestRemote_NewRegistry(t *testing.T) {
caPath := filepath.Join(t.TempDir(), "oras-test.pem")
if err := os.WriteFile(caPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: ts.Certificate().Raw}), 0644); err != nil {
Expand All @@ -174,6 +184,7 @@ func TestRemote_NewRegistry(t *testing.T) {
}{
Remote{
CACertFilePath: caPath,
plainHTTP: plainHTTPNotSpecified,
},
Common{},
}
Expand Down Expand Up @@ -201,6 +212,7 @@ func TestRemote_NewRepository(t *testing.T) {
}{
Remote{
CACertFilePath: caPath,
plainHTTP: plainHTTPNotSpecified,
},
Common{},
}
Expand Down Expand Up @@ -248,6 +260,7 @@ func TestRemote_NewRepository_Retry(t *testing.T) {
}{
Remote{
CACertFilePath: caPath,
plainHTTP: plainHTTPNotSpecified,
},
Common{},
}
Expand Down Expand Up @@ -276,8 +289,8 @@ func TestRemote_NewRepository_Retry(t *testing.T) {
}
}

func TestRemote_isPlainHttp_localhost(t *testing.T) {
opts := Remote{PlainHTTP: false}
func TestRemote_default_localhost(t *testing.T) {
opts := Remote{plainHTTP: plainHTTPNotSpecified}
got := opts.isPlainHttp("localhost")
if got != true {
t.Fatalf("tls should be disabled when domain is localhost")
Expand All @@ -291,6 +304,36 @@ func TestRemote_isPlainHttp_localhost(t *testing.T) {
}
}

func TestRemote_isPlainHTTP_localhost(t *testing.T) {
opts := Remote{plainHTTP: plainHTTPEnabled}
isplainHTTP := opts.isPlainHttp("localhost")
if isplainHTTP != true {
t.Fatalf("tls should be disabled when domain is localhost and --plain-http is used")

}

isplainHTTP = opts.isPlainHttp("localhost:9090")
if isplainHTTP != true {
t.Fatalf("tls should be disabled when domain is localhost and --plain-http is used")

}
}

func TestRemote_isHTTPS_localhost(t *testing.T) {
opts := Remote{plainHTTP: HTTPSEnabled}
got := opts.isPlainHttp("localhost")
if got != false {
t.Fatalf("tls should be enabled when domain is localhost and --plain-http=false is used")

}

got = opts.isPlainHttp("localhost:9090")
if got != false {
t.Fatalf("tls should be enabled when domain is localhost and --plain-http=false is used")

}
}

func TestRemote_parseResolve_err(t *testing.T) {
tests := []struct {
name string
Expand Down