mirror of https://github.com/knative/func.git
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:
parent
3d6ef471b7
commit
50243c740a
|
@ -28,6 +28,9 @@ type ClientConfig struct {
|
||||||
// Verbose logging. By default logging output is kept to the bare minimum.
|
// Verbose logging. By default logging output is kept to the bare minimum.
|
||||||
// Use this flag to configure verbose logging throughout.
|
// Use this flag to configure verbose logging throughout.
|
||||||
Verbose bool
|
Verbose bool
|
||||||
|
|
||||||
|
// Allow insecure server connections when using SSL
|
||||||
|
InsecureSkipVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientFactory defines a constructor which assists in the creation of a Client
|
// ClientFactory defines a constructor which assists in the creation of a Client
|
||||||
|
@ -62,9 +65,9 @@ func NewClientFactory(n func() *fn.Client) ClientFactory {
|
||||||
// defer done()
|
// defer done()
|
||||||
func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||||
var (
|
var (
|
||||||
p = progress.New(cfg.Verbose) // updates the CLI
|
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
|
c = newCredentialsProvider(t) // for accessing registries
|
||||||
d = newKnativeDeployer(cfg.Namespace, cfg.Verbose)
|
d = newKnativeDeployer(cfg.Namespace, cfg.Verbose)
|
||||||
pp = newTektonPipelinesProvider(cfg.Namespace, p, c, cfg.Verbose)
|
pp = newTektonPipelinesProvider(cfg.Namespace, p, c, cfg.Verbose)
|
||||||
o = []fn.Option{ // standard (shared) options for all commands
|
o = []fn.Option{ // standard (shared) options for all commands
|
||||||
|
@ -103,14 +106,14 @@ func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||||
|
|
||||||
// newTransport returns a transport with cluster-flavor-specific variations
|
// newTransport returns a transport with cluster-flavor-specific variations
|
||||||
// which take advantage of additional features offered by cluster variants.
|
// which take advantage of additional features offered by cluster variants.
|
||||||
func newTransport() fnhttp.RoundTripCloser {
|
func newTransport(insecureSkipVerify bool) fnhttp.RoundTripCloser {
|
||||||
if openshift.IsOpenShift() {
|
if openshift.IsOpenShift() {
|
||||||
return fnhttp.NewRoundTripper(openshift.WithOpenShiftServiceCA())
|
return fnhttp.NewRoundTripper(fnhttp.WithInsecureSkipVerify(insecureSkipVerify), openshift.WithOpenShiftServiceCA())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other cluster variants ...
|
// 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
|
// newCredentialsProvider returns a credentials provider which possibly
|
||||||
|
|
|
@ -26,7 +26,7 @@ NAME
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
{{.Name}} invoke [-t|--target] [-f|--format]
|
{{.Name}} invoke [-t|--target] [-f|--format]
|
||||||
[--id] [--source] [--type] [--data] [--file] [--content-type]
|
[--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
|
DESCRIPTION
|
||||||
Invokes the function by sending a test request to the currently running
|
Invokes the function by sending a test request to the currently running
|
||||||
|
@ -97,9 +97,12 @@ EXAMPLES
|
||||||
o Invoke an arbitrary endpoint (CloudEvent)
|
o Invoke an arbitrary endpoint (CloudEvent)
|
||||||
$ {{.Name}} invoke -f=cloudevent -t="https://my-event-broker.example.com"
|
$ {{.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"},
|
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
|
// 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("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("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().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.Flags().BoolP("confirm", "c", false, "Prompt to confirm all options interactively. (Env: $FUNC_CONFIRM)")
|
||||||
|
|
||||||
cmd.SetHelpFunc(defaultTemplatedHelp)
|
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 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()
|
defer done()
|
||||||
|
|
||||||
// Message to send the running function built from parameters gathered
|
// Message to send the running function built from parameters gathered
|
||||||
|
@ -201,6 +205,7 @@ type invokeConfig struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
Confirm bool
|
Confirm bool
|
||||||
Verbose bool
|
Verbose bool
|
||||||
|
Insecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
|
func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
|
||||||
|
@ -217,6 +222,7 @@ func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
|
||||||
Confirm: viper.GetBool("confirm"),
|
Confirm: viper.GetBool("confirm"),
|
||||||
Verbose: viper.GetBool("verbose"),
|
Verbose: viper.GetBool("verbose"),
|
||||||
Namespace: viper.GetString("namespace"),
|
Namespace: viper.GetString("namespace"),
|
||||||
|
Insecure: viper.GetBool("insecure"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// If file was passed, read it in as data
|
// 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 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()
|
defer done()
|
||||||
|
|
||||||
// If in interactive terminal mode, prompt to modify defaults.
|
// 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("Data: %v\n", cfg.Data)
|
||||||
fmt.Printf("Content Type: %v\n", cfg.ContentType)
|
fmt.Printf("Content Type: %v\n", cfg.ContentType)
|
||||||
fmt.Printf("File: %v\n", cfg.File)
|
fmt.Printf("File: %v\n", cfg.File)
|
||||||
|
fmt.Printf("Insecure: %v\n", cfg.Insecure)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,5 +382,17 @@ func (c invokeConfig) prompt(client *fn.Client) (invokeConfig, error) {
|
||||||
return c, err
|
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
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ NAME
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
func invoke [-t|--target] [-f|--format]
|
func invoke [-t|--target] [-f|--format]
|
||||||
[--id] [--source] [--type] [--data] [--file] [--content-type]
|
[--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
|
DESCRIPTION
|
||||||
Invokes the function by sending a test request to the currently running
|
Invokes the function by sending a test request to the currently running
|
||||||
|
@ -82,6 +82,9 @@ EXAMPLES
|
||||||
o Invoke an arbitrary endpoint (CloudEvent)
|
o Invoke an arbitrary endpoint (CloudEvent)
|
||||||
$ func invoke -f=cloudevent -t="https://my-event-broker.example.com"
|
$ 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)
|
-f, --format string Format of message to send, 'http' or 'cloudevent'. Default is to choose automatically. (Env: $FUNC_FORMAT)
|
||||||
-h, --help help for invoke
|
-h, --help help for invoke
|
||||||
--id string ID for the request data. (Env: $FUNC_ID)
|
--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 ".")
|
-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")
|
--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)
|
-t, --target string Function instance to invoke. Can be 'local', 'remote' or a URL. Defaults to auto-discovery if not provided. (Env: $FUNC_TARGET)
|
||||||
|
|
|
@ -25,8 +25,9 @@ type RoundTripCloser interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
selectCA func(ctx context.Context, serverName string) (*x509.Certificate, error)
|
selectCA func(ctx context.Context, serverName string) (*x509.Certificate, error)
|
||||||
inClusterDialer ContextDialer
|
inClusterDialer ContextDialer
|
||||||
|
insecureSkipVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Option func(*options)
|
type Option func(*options)
|
||||||
|
@ -43,13 +44,20 @@ 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,
|
// 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.
|
// if the dial operation fails due to hostname resolution the RoundTripper tries to dial from in cluster pod.
|
||||||
//
|
//
|
||||||
// This is useful for accessing cluster internal services (pushing a CloudEvent into Knative broker).
|
// This is useful for accessing cluster internal services (pushing a CloudEvent into Knative broker).
|
||||||
func NewRoundTripper(opts ...Option) RoundTripCloser {
|
func NewRoundTripper(opts ...Option) RoundTripCloser {
|
||||||
o := options{
|
o := options{
|
||||||
inClusterDialer: k8s.NewLazyInitInClusterDialer(),
|
inClusterDialer: k8s.NewLazyInitInClusterDialer(),
|
||||||
|
insecureSkipVerify: false,
|
||||||
}
|
}
|
||||||
for _, option := range opts {
|
for _, option := range opts {
|
||||||
option(&o)
|
option(&o)
|
||||||
|
@ -62,6 +70,8 @@ func NewRoundTripper(opts ...Option) RoundTripCloser {
|
||||||
|
|
||||||
combinedDialer := newDialerWithFallback(primaryDialer, secondaryDialer)
|
combinedDialer := newDialerWithFallback(primaryDialer, secondaryDialer)
|
||||||
|
|
||||||
|
httpTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: o.insecureSkipVerify}
|
||||||
|
|
||||||
httpTransport.DialContext = combinedDialer.DialContext
|
httpTransport.DialContext = combinedDialer.DialContext
|
||||||
|
|
||||||
httpTransport.DialTLSContext = newDialTLSContext(combinedDialer, httpTransport.TLSClientConfig, o.selectCA)
|
httpTransport.DialTLSContext = newDialTLSContext(combinedDialer, httpTransport.TLSClientConfig, o.selectCA)
|
||||||
|
|
Loading…
Reference in New Issue