feat: add --registry-insecure param

Signed-off-by: lengrongfu <1275177125@qq.com>
pull/11183/head
lengrongfu 3 years ago
parent 9fe4f2ea72
commit 0da8febe16

@ -17,7 +17,23 @@ limitations under the License.
package main package main
import ( import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net"
"os"
"testing" "testing"
"time"
"helm.sh/helm/v3/pkg/action"
helmRegistry "helm.sh/helm/v3/pkg/registry"
"github.com/distribution/distribution/v3/configuration"
"github.com/distribution/distribution/v3/registry"
"github.com/phayes/freeport"
"github.com/stretchr/testify/suite"
) )
func TestPushFileCompletion(t *testing.T) { func TestPushFileCompletion(t *testing.T) {
@ -25,3 +41,121 @@ func TestPushFileCompletion(t *testing.T) {
checkFileCompletion(t, "push package.tgz", false) checkFileCompletion(t, "push package.tgz", false)
checkFileCompletion(t, "push package.tgz oci://localhost:5000", false) checkFileCompletion(t, "push package.tgz oci://localhost:5000", false)
} }
const (
testWorkspaceDir = "helm-registry-test"
)
type HelmPushTestSuite struct {
suite.Suite
Out io.Writer
DockerRegistryHost string
CompromisedRegistryHost string
WorkspaceDir string
RegistryClient *helmRegistry.Client
PushClient *action.Push
}
func getLocalIP() (string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return "", err
}
for _, address := range addrs {
// filter loopback ip
if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
return ipNet.IP.String(), nil
}
}
}
return "", errors.New("can not find the client ip address")
}
func TestGetLocalIP(t *testing.T) {
ip, err := getLocalIP()
if err != nil {
t.Errorf("get local ip error %+v", err)
}
t.Log(ip)
}
func (suite *HelmPushTestSuite) SetupSuite() {
suite.WorkspaceDir = testWorkspaceDir
os.RemoveAll(suite.WorkspaceDir)
os.Mkdir(suite.WorkspaceDir, 0700)
var out bytes.Buffer
suite.Out = &out
// Registry config
config := &configuration.Configuration{}
port, err := freeport.GetFreePort()
suite.Nil(err, "no error finding free port for test registry")
ip, err := getLocalIP()
suite.Nil(err, "get host ip error")
suite.DockerRegistryHost = fmt.Sprintf("%s:%d", ip, port)
config.HTTP.Addr = fmt.Sprintf("%s:%d", ip, port)
config.HTTP.DrainTimeout = time.Duration(10) * time.Second
config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}}
dockerRegistry, err := registry.NewRegistry(context.Background(), config)
suite.Nil(err, "no error creating test registry")
suite.CompromisedRegistryHost = fmt.Sprintf("%s:%d", ip, port)
// Start Docker registry
go dockerRegistry.ListenAndServe()
}
func (suite *HelmPushTestSuite) TestSecretPush() {
// init test client
var err error
suite.RegistryClient, err = helmRegistry.NewClient(
helmRegistry.ClientOptDebug(true),
helmRegistry.ClientOptEnableCache(true),
helmRegistry.ClientOptWriter(suite.Out),
)
suite.Nil(err, "no error creating registry client")
// init push client
cfg := &action.Configuration{
RegistryClient: suite.RegistryClient,
}
suite.PushClient = action.NewPushWithOpts(action.WithPushConfig(cfg))
ref := fmt.Sprintf("oci://%s/testrepo", suite.DockerRegistryHost)
// Load a test chart
_, err = suite.PushClient.Run("./testdata/testcharts/examplechart-0.1.0.tgz", ref)
suite.ErrorContains(err, "http: server gave HTTP response to HTTPS client")
}
func (suite *HelmPushTestSuite) TestInsecretPush() {
// init test client
var err error
suite.RegistryClient, err = helmRegistry.NewClient(
helmRegistry.ClientOptDebug(true),
helmRegistry.ClientOptEnableCache(true),
helmRegistry.ClientOptWriter(suite.Out),
helmRegistry.ClientPlainHTTP(),
)
suite.Nil(err, "no error creating registry client")
// init push client
cfg := &action.Configuration{
RegistryClient: suite.RegistryClient,
}
suite.PushClient = action.NewPushWithOpts(action.WithPushConfig(cfg))
ref := fmt.Sprintf("oci://%s/testrepo", suite.DockerRegistryHost)
// Load a test chart
_, err = suite.PushClient.Run("./testdata/testcharts/examplechart-0.1.0.tgz", ref)
suite.Nil(err, "no error loading test chart")
}
func TestHelmPushTestSuite(t *testing.T) {
suite.Run(t, new(HelmPushTestSuite))
}

@ -152,12 +152,16 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
flags.ParseErrorsWhitelist.UnknownFlags = true flags.ParseErrorsWhitelist.UnknownFlags = true
flags.Parse(args) flags.Parse(args)
registryClient, err := registry.NewClient( clientOptions := []registry.ClientOption{
registry.ClientOptDebug(settings.Debug), registry.ClientOptDebug(settings.Debug),
registry.ClientOptEnableCache(true), registry.ClientOptEnableCache(true),
registry.ClientOptWriter(out), registry.ClientOptWriter(out),
registry.ClientOptCredentialsFile(settings.RegistryConfig), registry.ClientOptCredentialsFile(settings.RegistryConfig),
) }
if settings.RegistryPlainHTTP {
clientOptions = append(clientOptions, registry.ClientPlainHTTP())
}
registryClient, err := registry.NewClient(clientOptions...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -80,6 +80,8 @@ type EnvSettings struct {
MaxHistory int MaxHistory int
// BurstLimit is the default client-side throttling limit. // BurstLimit is the default client-side throttling limit.
BurstLimit int BurstLimit int
// RegistryPlainHTTP is set transport data to registry use http transport schema
RegistryPlainHTTP bool
} }
func New() *EnvSettings { func New() *EnvSettings {
@ -99,6 +101,7 @@ func New() *EnvSettings {
RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")), RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")),
RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")), RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")),
BurstLimit: envIntOr("HELM_BURST_LIMIT", defaultBurstLimit), BurstLimit: envIntOr("HELM_BURST_LIMIT", defaultBurstLimit),
RegistryPlainHTTP: envBoolOr("HELM_REGISTRY_PLAIN_HTTP", false),
} }
env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG")) env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG"))
@ -139,6 +142,8 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.RepositoryConfig, "repository-config", s.RepositoryConfig, "path to the file containing repository names and URLs") fs.StringVar(&s.RepositoryConfig, "repository-config", s.RepositoryConfig, "path to the file containing repository names and URLs")
fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes") fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes")
fs.IntVar(&s.BurstLimit, "burst-limit", s.BurstLimit, "client-side default throttling limit") fs.IntVar(&s.BurstLimit, "burst-limit", s.BurstLimit, "client-side default throttling limit")
fs.BoolVar(&s.RegistryPlainHTTP, "registry-plainhttp", s.RegistryPlainHTTP, "set client data use http transport protocol to registry server")
} }
func envOr(name, def string) string { func envOr(name, def string) string {

@ -48,15 +48,16 @@ func TestEnvSettings(t *testing.T) {
envvars map[string]string envvars map[string]string
// expected values // expected values
ns, kcontext string ns, kcontext string
debug bool debug bool
maxhistory int maxhistory int
kubeAsUser string kubeAsUser string
kubeAsGroups []string kubeAsGroups []string
kubeCaFile string kubeCaFile string
kubeInsecure bool kubeInsecure bool
kubeTLSServer string kubeTLSServer string
burstLimit int burstLimit int
registryInsecure bool
}{ }{
{ {
name: "defaults", name: "defaults",
@ -78,31 +79,33 @@ func TestEnvSettings(t *testing.T) {
kubeInsecure: true, kubeInsecure: true,
}, },
{ {
name: "with envvars set", name: "with envvars set",
envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt", "HELM_BURST_LIMIT": "150", "HELM_KUBEINSECURE_SKIP_TLS_VERIFY": "true", "HELM_KUBETLS_SERVER_NAME": "example.org"}, envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt", "HELM_BURST_LIMIT": "150", "HELM_KUBEINSECURE_SKIP_TLS_VERIFY": "true", "HELM_KUBETLS_SERVER_NAME": "example.org", "HELM_REGISTRY_PLAIN_HTTP": "true"},
ns: "yourns", ns: "yourns",
maxhistory: 5, maxhistory: 5,
burstLimit: 150, burstLimit: 150,
debug: true, debug: true,
kubeAsUser: "pikachu", kubeAsUser: "pikachu",
kubeAsGroups: []string{"operators", "snackeaters", "partyanimals"}, kubeAsGroups: []string{"operators", "snackeaters", "partyanimals"},
kubeCaFile: "/tmp/ca.crt", kubeCaFile: "/tmp/ca.crt",
kubeTLSServer: "example.org", kubeTLSServer: "example.org",
kubeInsecure: true, kubeInsecure: true,
registryInsecure: true,
}, },
{ {
name: "with flags and envvars set", name: "with flags and envvars set",
args: "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/my/ca.crt --burst-limit 175 --kube-insecure-skip-tls-verify=true --kube-tls-server-name=example.org", args: "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/my/ca.crt --burst-limit 175 --kube-insecure-skip-tls-verify=true --kube-tls-server-name=example.org",
envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt", "HELM_BURST_LIMIT": "200", "HELM_KUBEINSECURE_SKIP_TLS_VERIFY": "true", "HELM_KUBETLS_SERVER_NAME": "example.org"}, envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt", "HELM_BURST_LIMIT": "200", "HELM_KUBEINSECURE_SKIP_TLS_VERIFY": "true", "HELM_KUBETLS_SERVER_NAME": "example.org", "HELM_REGISTRY_PLAIN_HTTP": "true"},
ns: "myns", ns: "myns",
debug: true, debug: true,
maxhistory: 5, maxhistory: 5,
burstLimit: 175, burstLimit: 175,
kubeAsUser: "poro", kubeAsUser: "poro",
kubeAsGroups: []string{"admins", "teatime", "snackeaters"}, kubeAsGroups: []string{"admins", "teatime", "snackeaters"},
kubeCaFile: "/my/ca.crt", kubeCaFile: "/my/ca.crt",
kubeTLSServer: "example.org", kubeTLSServer: "example.org",
kubeInsecure: true, kubeInsecure: true,
registryInsecure: true,
}, },
} }
@ -150,6 +153,9 @@ func TestEnvSettings(t *testing.T) {
if tt.kubeTLSServer != settings.KubeTLSServerName { if tt.kubeTLSServer != settings.KubeTLSServerName {
t.Errorf("expected kubeTLSServer %q, got %q", tt.kubeTLSServer, settings.KubeTLSServerName) t.Errorf("expected kubeTLSServer %q, got %q", tt.kubeTLSServer, settings.KubeTLSServerName)
} }
if tt.registryInsecure != settings.RegistryPlainHTTP {
t.Errorf("expected registryInsecure %t, got %t", tt.registryInsecure, settings.RegistryPlainHTTP)
}
}) })
} }
} }

@ -61,6 +61,7 @@ type (
authorizer auth.Client authorizer auth.Client
registryAuthorizer *registryauth.Client registryAuthorizer *registryauth.Client
resolver remotes.Resolver resolver remotes.Resolver
PlainHTTP bool
} }
// ClientOption allows specifying various settings configurable by the user for overriding the defaults // ClientOption allows specifying various settings configurable by the user for overriding the defaults
@ -90,6 +91,9 @@ func NewClient(options ...ClientOption) (*Client, error) {
headers := http.Header{} headers := http.Header{}
headers.Set("User-Agent", version.GetUserAgent()) headers.Set("User-Agent", version.GetUserAgent())
opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)} opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)}
if client.PlainHTTP {
opts = append(opts, auth.WithResolverPlainHTTP())
}
resolver, err := client.authorizer.ResolverWithOpts(opts...) resolver, err := client.authorizer.ResolverWithOpts(opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -166,6 +170,13 @@ func ClientOptCredentialsFile(credentialsFile string) ClientOption {
} }
} }
// ClientPlainHTTP returns a function that sets the PlainHTTP setting to true on resolver. use http schema transport data
func ClientPlainHTTP() ClientOption {
return func(client *Client) {
client.PlainHTTP = true
}
}
type ( type (
// LoginOption allows specifying various settings on login // LoginOption allows specifying various settings on login
LoginOption func(*loginOperation) LoginOption func(*loginOperation)

Loading…
Cancel
Save