Commit de033c2c authored by Oren Shomron's avatar Oren Shomron
Browse files

Add --tls-skip-verify global option affecting outgoing HTTP requests


Signed-off-by: default avatarOren Shomron <shomron@gmail.com>
parent 746561a9
......@@ -16,7 +16,11 @@
package actions
import (
"crypto/tls"
"fmt"
"net"
"net/http"
"time"
"github.com/ksonnet/ksonnet/pkg/app"
"github.com/ksonnet/ksonnet/pkg/client"
......@@ -110,6 +114,8 @@ const (
OptionTlaVarFiles = "tla-var-files"
// OptionTlaVars is jsonnet tla vars.
OptionTlaVars = "tla-vars"
// OptionTLSSkipVerify specifies that tls server certifactes should not be verified.
OptionTLSSkipVerify = "tls-skip-verify"
// OptionUnset is unset option.
OptionUnset = "unset"
// OptionURI is uri option. Used for setting registry URI.
......@@ -342,6 +348,38 @@ func (o *optionLoader) LoadApp() app.App {
return a
}
// LoadHTTPClient loads an HTTP client based on common configuration for certificates, tls verification, timeouts, etc.
func (o *optionLoader) LoadHTTPClient() *http.Client {
tlsSkipVerify := o.LoadOptionalBool(OptionTLSSkipVerify)
tlsConfig := &tls.Config{
InsecureSkipVerify: tlsSkipVerify,
}
timeoutSeconds := 10
var defaultTransport http.RoundTripper = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSClientConfig: tlsConfig,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
c := &http.Client{
Timeout: time.Duration(timeoutSeconds) * time.Second,
Transport: defaultTransport,
}
return c
}
func (o *optionLoader) load(key string) interface{} {
if o.err != nil {
return nil
......
......@@ -48,6 +48,8 @@ type PkgDescribe struct {
func NewPkgDescribe(m map[string]interface{}) (*PkgDescribe, error) {
ol := newOptionLoader(m)
httpClientOpt := registry.HTTPClientOpt(ol.LoadHTTPClient())
app := ol.LoadApp()
pd := &PkgDescribe{
app: app,
......@@ -55,7 +57,7 @@ func NewPkgDescribe(m map[string]interface{}) (*PkgDescribe, error) {
templateSrc: pkgDescribeTemplate,
out: os.Stdout,
packageManager: registry.NewPackageManager(app),
packageManager: registry.NewPackageManager(app, httpClientOpt),
}
if ol.err != nil {
......
......@@ -153,8 +153,9 @@ func TestPkgDescribe(t *testing.T) {
a.On("Libraries").Return(libraries, nil)
in := map[string]interface{}{
OptionApp: a,
OptionPackageName: "apache",
OptionApp: a,
OptionPackageName: "apache",
OptionTLSSkipVerify: false,
}
pd, err := NewPkgDescribe(in)
......
......@@ -55,6 +55,8 @@ func NewPkgInstall(m map[string]interface{}) (*PkgInstall, error) {
if ol.err != nil {
return nil, ol.err
}
httpClient := ol.LoadHTTPClient()
httpClientOpt := registry.HTTPClientOpt(httpClient)
nl := &PkgInstall{
app: a,
......@@ -62,9 +64,11 @@ func NewPkgInstall(m map[string]interface{}) (*PkgInstall, error) {
customName: ol.LoadString(OptionName),
force: ol.LoadBool(OptionForce),
envName: ol.LoadOptionalString(OptionEnvName),
checker: registry.NewPackageManager(a),
checker: registry.NewPackageManager(a, httpClientOpt),
libCacherFn: registry.CacheDependency,
libCacherFn: func(a app.App, checker registry.InstalledChecker, d pkg.Descriptor, customName string, force bool) (*app.LibraryConfig, error) {
return registry.CacheDependency(a, checker, d, customName, force, httpClient)
},
libUpdateFn: a.UpdateLib,
}
......
......@@ -32,10 +32,11 @@ func TestPkgInstall(t *testing.T) {
customName := "customName"
in := map[string]interface{}{
OptionApp: appMock,
OptionLibName: libName,
OptionName: customName,
OptionForce: false,
OptionApp: appMock,
OptionLibName: libName,
OptionName: customName,
OptionForce: false,
OptionTLSSkipVerify: false,
}
a, err := NewPkgInstall(in)
......
......@@ -58,15 +58,20 @@ type PkgList struct {
func NewPkgList(m map[string]interface{}) (*PkgList, error) {
ol := newOptionLoader(m)
app := ol.LoadApp()
a := ol.LoadApp()
httpClient := ol.LoadHTTPClient()
httpClientOpt := registry.HTTPClientOpt(httpClient)
rl := &PkgList{
app: app,
pm: registry.NewPackageManager(app),
app: a,
pm: registry.NewPackageManager(a, httpClientOpt),
onlyInstalled: ol.LoadBool(OptionInstalled),
outputType: ol.LoadOptionalString(OptionOutput),
registryListFn: registry.List,
out: os.Stdout,
registryListFn: func(ksApp app.App) ([]registry.Registry, error) {
return registry.List(ksApp, httpClient)
},
out: os.Stdout,
}
if ol.err != nil {
......
......@@ -152,9 +152,10 @@ func TestPkgList(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
in := map[string]interface{}{
OptionApp: appMock,
OptionInstalled: tc.onlyInstalled,
OptionOutput: tc.outputType,
OptionApp: appMock,
OptionInstalled: tc.onlyInstalled,
OptionOutput: tc.outputType,
OptionTLSSkipVerify: false,
}
a, err := NewPkgList(in)
......
......@@ -51,12 +51,14 @@ func NewPrototypeDescribe(m map[string]interface{}) (*PrototypeDescribe, error)
ol := newOptionLoader(m)
app := ol.LoadApp()
httpClientOpt := registry.HTTPClientOpt(ol.LoadHTTPClient())
pd := &PrototypeDescribe{
app: app,
query: ol.LoadString(OptionQuery),
out: os.Stdout,
packageManager: registry.NewPackageManager(app),
packageManager: registry.NewPackageManager(app, httpClientOpt),
}
if ol.err != nil {
......
......@@ -33,8 +33,9 @@ func TestPrototypeDescribe(t *testing.T) {
manager.On("Prototypes").Return(prototypes, nil)
in := map[string]interface{}{
OptionApp: appMock,
OptionQuery: "namespace",
OptionApp: appMock,
OptionQuery: "namespace",
OptionTLSSkipVerify: false,
}
a, err := NewPrototypeDescribe(in)
......
......@@ -51,12 +51,14 @@ func NewPrototypeList(m map[string]interface{}) (*PrototypeList, error) {
ol := newOptionLoader(m)
app := ol.LoadApp()
httpClientOpt := registry.HTTPClientOpt(ol.LoadHTTPClient())
pl := &PrototypeList{
app: app,
out: os.Stdout,
outputType: ol.LoadOptionalString(OptionOutput),
packageManager: registry.NewPackageManager(app),
packageManager: registry.NewPackageManager(app, httpClientOpt),
}
if ol.err != nil {
......
......@@ -58,8 +58,9 @@ func TestPrototypeList(t *testing.T) {
manager.On("Prototypes").Return(prototypes, nil)
in := map[string]interface{}{
OptionApp: appMock,
OptionOutput: tc.outputType,
OptionApp: appMock,
OptionOutput: tc.outputType,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypeList(in)
......
......@@ -62,13 +62,15 @@ func NewPrototypePreview(m map[string]interface{}) (*PrototypePreview, error) {
ol := newOptionLoader(m)
app := ol.LoadApp()
httpClientOpt := registry.HTTPClientOpt(ol.LoadHTTPClient())
pp := &PrototypePreview{
app: app,
query: ol.LoadString(OptionQuery),
args: ol.LoadStringSlice(OptionArguments),
out: os.Stdout,
packageManager: registry.NewPackageManager(app),
packageManager: registry.NewPackageManager(app, httpClientOpt),
bindFlagsFn: prototype.BindFlags,
extractParametersFn: prototype.ExtractParameters,
}
......
......@@ -41,9 +41,10 @@ func TestPrototypePreview(t *testing.T) {
}
in := map[string]interface{}{
OptionApp: appMock,
OptionQuery: "single-port-deployment",
OptionArguments: args,
OptionApp: appMock,
OptionQuery: "single-port-deployment",
OptionArguments: args,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypePreview(in)
......@@ -74,9 +75,10 @@ func TestPrototypePreview_bind_flags_failed(t *testing.T) {
}
in := map[string]interface{}{
OptionApp: appMock,
OptionQuery: "single-port-deployment",
OptionArguments: args,
OptionApp: appMock,
OptionQuery: "single-port-deployment",
OptionArguments: args,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypePreview(in)
......
......@@ -54,13 +54,15 @@ func NewPrototypeSearch(m map[string]interface{}) (*PrototypeSearch, error) {
ol := newOptionLoader(m)
app := ol.LoadApp()
httpClientOpt := registry.HTTPClientOpt(ol.LoadHTTPClient())
ps := &PrototypeSearch{
app: app,
query: ol.LoadString(OptionQuery),
outputType: ol.LoadOptionalString(OptionOutput),
out: os.Stdout,
packageManager: registry.NewPackageManager(app),
packageManager: registry.NewPackageManager(app, httpClientOpt),
protoSearchFn: protoSearch,
}
......
......@@ -58,9 +58,10 @@ func TestPrototypeSearch(t *testing.T) {
manager.On("Prototypes").Return(prototypes, nil)
in := map[string]interface{}{
OptionApp: appMock,
OptionQuery: "search",
OptionOutput: tc.outputType,
OptionApp: appMock,
OptionQuery: "search",
OptionOutput: tc.outputType,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypeSearch(in)
......
......@@ -57,12 +57,14 @@ func NewPrototypeUse(m map[string]interface{}) (*PrototypeUse, error) {
ol := newOptionLoader(m)
app := ol.LoadApp()
httpClientOpt := registry.HTTPClientOpt(ol.LoadHTTPClient())
pl := &PrototypeUse{
app: app,
args: ol.LoadStringSlice(OptionArguments),
out: os.Stdout,
packageManager: registry.NewPackageManager(app),
packageManager: registry.NewPackageManager(app, httpClientOpt),
createComponentFn: component.Create,
bindFlagsFn: prototype.BindFlags,
extractParametersFn: prototype.ExtractParameters,
......
......@@ -45,8 +45,9 @@ func TestPrototypeUse(t *testing.T) {
}
in := map[string]interface{}{
OptionApp: appMock,
OptionArguments: args,
OptionApp: appMock,
OptionArguments: args,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypeUse(in)
......@@ -92,8 +93,9 @@ func TestPrototypeUse_bind_flags_failed(t *testing.T) {
}
in := map[string]interface{}{
OptionApp: appMock,
OptionArguments: args,
OptionApp: appMock,
OptionArguments: args,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypeUse(in)
......@@ -143,8 +145,9 @@ func TestPrototypeUse_with_module_in_name(t *testing.T) {
}
in := map[string]interface{}{
OptionApp: appMock,
OptionArguments: args,
OptionApp: appMock,
OptionArguments: args,
OptionTLSSkipVerify: false,
}
a, err := NewPrototypeUse(in)
......
......@@ -16,6 +16,7 @@
package actions
import (
"net/http"
"net/url"
"strings"
......@@ -36,11 +37,13 @@ func RunRegistryAdd(m map[string]interface{}) error {
// RegistryAdd adds a registry.
type RegistryAdd struct {
app app.App
name string
uri string
isOverride bool
registryAddFn func(a app.App, protocol registry.Protocol, name string, uri string, isOverride bool) (*registry.Spec, error)
app app.App
name string
uri string
isOverride bool
httpClient *http.Client
registryAddFn func(a app.App, protocol registry.Protocol, name string, uri string, isOverride bool, httpClient *http.Client) (*registry.Spec, error)
}
// NewRegistryAdd creates an instance of RegistryAdd.
......@@ -52,6 +55,7 @@ func NewRegistryAdd(m map[string]interface{}) (*RegistryAdd, error) {
name: ol.LoadString(OptionName),
uri: ol.LoadString(OptionURI),
isOverride: ol.LoadBool(OptionOverride),
httpClient: ol.LoadHTTPClient(),
registryAddFn: registry.Add,
}
......@@ -70,7 +74,7 @@ func (ra *RegistryAdd) Run() error {
return errors.Wrap(err, "detect registry protocol")
}
_, err = ra.registryAddFn(ra.app, rd.Protocol, ra.name, rd.URI, ra.isOverride)
_, err = ra.registryAddFn(ra.app, rd.Protocol, ra.name, rd.URI, ra.isOverride, ra.httpClient)
return err
}
......
......@@ -16,6 +16,7 @@
package actions
import (
"net/http"
"testing"
"github.com/ksonnet/ksonnet/pkg/app"
......@@ -85,17 +86,18 @@ func TestRegistryAdd(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
in := map[string]interface{}{
OptionApp: appMock,
OptionName: name,
OptionURI: tc.uri,
OptionVersion: tc.version,
OptionOverride: tc.isOverride,
OptionApp: appMock,
OptionName: name,
OptionURI: tc.uri,
OptionVersion: tc.version,
OptionOverride: tc.isOverride,
OptionTLSSkipVerify: false,
}
a, err := NewRegistryAdd(in)
require.NoError(t, err)
a.registryAddFn = func(a app.App, protocol registry.Protocol, name string, uri string, isOverride bool) (*registry.Spec, error) {
a.registryAddFn = func(a app.App, protocol registry.Protocol, name string, uri string, isOverride bool, httpClient *http.Client) (*registry.Spec, error) {
assert.Equal(t, "new", name)
assert.Equal(t, tc.protocol, protocol)
assert.Equal(t, tc.expectedURI, uri)
......
......@@ -18,6 +18,7 @@ package actions
import (
"fmt"
"io"
"net/http"
"os"
"sort"
......@@ -48,12 +49,15 @@ type RegistryDescribe struct {
func NewRegistryDescribe(m map[string]interface{}) (*RegistryDescribe, error) {
ol := newOptionLoader(m)
httpClient := ol.LoadHTTPClient()
rd := &RegistryDescribe{
app: ol.LoadApp(),
name: ol.LoadString(OptionName),
out: os.Stdout,
fetchRegistrySpecFn: fetchRegistrySpec,
out: os.Stdout,
fetchRegistrySpecFn: func(a app.App, name string) (*registry.Spec, *app.RegistryConfig, error) {
return fetchRegistrySpec(a, name, httpClient)
},
}
if ol.err != nil {
......@@ -93,7 +97,7 @@ func (rd *RegistryDescribe) Run() error {
return nil
}
func fetchRegistrySpec(a app.App, name string) (*registry.Spec, *app.RegistryConfig, error) {
func fetchRegistrySpec(a app.App, name string, httpClient *http.Client) (*registry.Spec, *app.RegistryConfig, error) {
appRegistries, err := a.Registries()
if err != nil {
return nil, nil, err
......@@ -103,7 +107,7 @@ func fetchRegistrySpec(a app.App, name string) (*registry.Spec, *app.RegistryCon
return nil, nil, errors.Errorf("registry %q doesn't exist", name)
}
r, err := registry.Locate(a, regRef)
r, err := registry.Locate(a, regRef, httpClient)
if err != nil {
return nil, nil, err
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment