feat: `invoke` - allow insecure connections over SSL (#1255)

Signed-off-by: Zbynek Roubalik <zroubalik@gmail.com>

Signed-off-by: Zbynek Roubalik <zroubalik@gmail.com>
This commit is contained in:
Zbynek Roubalik 2022-09-20 14:25:10 +02:00 committed by GitHub
parent 3d6ef471b7
commit 50243c740a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 14 deletions

View File

@ -28,6 +28,9 @@ type ClientConfig struct {
// Verbose logging. By default logging output is kept to the bare minimum.
// Use this flag to configure verbose logging throughout.
Verbose bool
// Allow insecure server connections when using SSL
InsecureSkipVerify bool
}
// ClientFactory defines a constructor which assists in the creation of a Client
@ -63,7 +66,7 @@ func NewClientFactory(n func() *fn.Client) ClientFactory {
func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
var (
p = progress.New(cfg.Verbose) // updates the CLI
t = newTransport() // may provide a custom impl which proxies
t = newTransport(cfg.InsecureSkipVerify) // may provide a custom impl which proxies
c = newCredentialsProvider(t) // for accessing registries
d = newKnativeDeployer(cfg.Namespace, cfg.Verbose)
pp = newTektonPipelinesProvider(cfg.Namespace, p, c, cfg.Verbose)
@ -103,14 +106,14 @@ func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
// newTransport returns a transport with cluster-flavor-specific variations
// which take advantage of additional features offered by cluster variants.
func newTransport() fnhttp.RoundTripCloser {
func newTransport(insecureSkipVerify bool) fnhttp.RoundTripCloser {
if openshift.IsOpenShift() {
return fnhttp.NewRoundTripper(openshift.WithOpenShiftServiceCA())
return fnhttp.NewRoundTripper(fnhttp.WithInsecureSkipVerify(insecureSkipVerify), openshift.WithOpenShiftServiceCA())
}
// Other cluster variants ...
return fnhttp.NewRoundTripper() // Default (vanilla k8s)
return fnhttp.NewRoundTripper(fnhttp.WithInsecureSkipVerify(insecureSkipVerify)) // Default (vanilla k8s)
}
// newCredentialsProvider returns a credentials provider which possibly

View File

@ -26,7 +26,7 @@ NAME
SYNOPSIS
{{.Name}} invoke [-t|--target] [-f|--format]
[--id] [--source] [--type] [--data] [--file] [--content-type]
[-s|--save] [-p|--path] [-c|--confirm] [-v|--verbose]
[-s|--save] [-p|--path] [-i|--insecure] [-c|--confirm] [-v|--verbose]
DESCRIPTION
Invokes the function by sending a test request to the currently running
@ -97,9 +97,12 @@ EXAMPLES
o Invoke an arbitrary endpoint (CloudEvent)
$ {{.Name}} invoke -f=cloudevent -t="https://my-event-broker.example.com"
o Allow insecure server connections when using SSL
$ {{.Name}} invoke --insecure
`,
SuggestFor: []string{"emit", "emti", "send", "emit", "exec", "nivoke", "onvoke", "unvoke", "knvoke", "imvoke", "ihvoke", "ibvoke"},
PreRunE: bindEnv("path", "format", "target", "id", "source", "type", "data", "content-type", "file", "confirm"),
PreRunE: bindEnv("path", "format", "target", "id", "source", "type", "data", "content-type", "file", "insecure", "confirm"),
}
// Flags
@ -112,6 +115,7 @@ EXAMPLES
cmd.Flags().StringP("content-type", "", fn.DefaultInvokeContentType, "Content Type of the data. (Env: $FUNC_CONTENT_TYPE)")
cmd.Flags().StringP("data", "", fn.DefaultInvokeData, "Data to send in the request. (Env: $FUNC_DATA)")
cmd.Flags().StringP("file", "", "", "Path to a file to use as data. Overrides --data flag and should be sent with a correct --content-type. (Env: $FUNC_FILE)")
cmd.Flags().BoolP("insecure", "i", false, "Allow insecure server connections when using SSL. (Env: $FUNC_INSECURE)")
cmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all options interactively. (Env: $FUNC_CONFIRM)")
cmd.SetHelpFunc(defaultTemplatedHelp)
@ -132,7 +136,7 @@ func runInvoke(cmd *cobra.Command, args []string, newClient ClientFactory) (err
}
// Client instance from env vars, flags, args and user prompts (if --confirm)
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose, InsecureSkipVerify: cfg.Insecure})
defer done()
// Message to send the running function built from parameters gathered
@ -201,6 +205,7 @@ type invokeConfig struct {
Namespace string
Confirm bool
Verbose bool
Insecure bool
}
func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
@ -217,6 +222,7 @@ func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
Confirm: viper.GetBool("confirm"),
Verbose: viper.GetBool("verbose"),
Namespace: viper.GetString("namespace"),
Insecure: viper.GetBool("insecure"),
}
// If file was passed, read it in as data
@ -234,7 +240,7 @@ func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
}
// Client instance for use during prompting.
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose, InsecureSkipVerify: cfg.Insecure})
defer done()
// If in interactive terminal mode, prompt to modify defaults.
@ -252,6 +258,7 @@ func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
fmt.Printf("Data: %v\n", cfg.Data)
fmt.Printf("Content Type: %v\n", cfg.ContentType)
fmt.Printf("File: %v\n", cfg.File)
fmt.Printf("Insecure: %v\n", cfg.Insecure)
return
}
@ -375,5 +382,17 @@ func (c invokeConfig) prompt(client *fn.Client) (invokeConfig, error) {
return c, err
}
qs = []*survey.Question{
{
Name: "Insecure",
Prompt: &survey.Confirm{
Message: "Allow insecure server connections when using SSL",
Default: c.Insecure,
},
}}
if err := survey.Ask(qs, &c); err != nil {
return c, err
}
return c, nil
}

View File

@ -11,7 +11,7 @@ NAME
SYNOPSIS
func invoke [-t|--target] [-f|--format]
[--id] [--source] [--type] [--data] [--file] [--content-type]
[-s|--save] [-p|--path] [-c|--confirm] [-v|--verbose]
[-s|--save] [-p|--path] [-i|--insecure] [-c|--confirm] [-v|--verbose]
DESCRIPTION
Invokes the function by sending a test request to the currently running
@ -82,6 +82,9 @@ EXAMPLES
o Invoke an arbitrary endpoint (CloudEvent)
$ func invoke -f=cloudevent -t="https://my-event-broker.example.com"
o Allow insecure server connections when using SSL
$ func invoke --insecure
```
@ -98,6 +101,7 @@ func invoke
-f, --format string Format of message to send, 'http' or 'cloudevent'. Default is to choose automatically. (Env: $FUNC_FORMAT)
-h, --help help for invoke
--id string ID for the request data. (Env: $FUNC_ID)
-i, --insecure Allow insecure server connections when using SSL. (Env: $FUNC_INSECURE)
-p, --path string Path to the project directory (Env: $FUNC_PATH) (default ".")
--source string Source value for the request data. (Env: $FUNC_SOURCE) (default "/boson/fn")
-t, --target string Function instance to invoke. Can be 'local', 'remote' or a URL. Defaults to auto-discovery if not provided. (Env: $FUNC_TARGET)

View File

@ -27,6 +27,7 @@ type RoundTripCloser interface {
type options struct {
selectCA func(ctx context.Context, serverName string) (*x509.Certificate, error)
inClusterDialer ContextDialer
insecureSkipVerify bool
}
type Option func(*options)
@ -43,6 +44,12 @@ func WithInClusterDialer(inClusterDialer ContextDialer) Option {
}
}
func WithInsecureSkipVerify(insecureSkipVerify bool) Option {
return func(o *options) {
o.insecureSkipVerify = insecureSkipVerify
}
}
// NewRoundTripper returns new closable RoundTripper that first tries to dial connection in standard way,
// if the dial operation fails due to hostname resolution the RoundTripper tries to dial from in cluster pod.
//
@ -50,6 +57,7 @@ func WithInClusterDialer(inClusterDialer ContextDialer) Option {
func NewRoundTripper(opts ...Option) RoundTripCloser {
o := options{
inClusterDialer: k8s.NewLazyInitInClusterDialer(),
insecureSkipVerify: false,
}
for _, option := range opts {
option(&o)
@ -62,6 +70,8 @@ func NewRoundTripper(opts ...Option) RoundTripCloser {
combinedDialer := newDialerWithFallback(primaryDialer, secondaryDialer)
httpTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: o.insecureSkipVerify}
httpTransport.DialContext = combinedDialer.DialContext
httpTransport.DialTLSContext = newDialTLSContext(combinedDialer, httpTransport.TLSClientConfig, o.selectCA)