From 2e01150c06dea42c5e9fc58888951c272f1588d1 Mon Sep 17 00:00:00 2001 From: William Poussier Date: Wed, 9 Sep 2020 20:18:46 +0200 Subject: [PATCH] feat: add insecure_skip_verify option to the builtin HTTP plugin (#178) * feat: add insecure_skip_verify option to the builtin HTTP plugin * fix: use a string type for InsecureSkipVerify option * fix: use a copy of the htt.DefaultTransport * fix(plugin/http): create unsecure transport once and setup HTTP2 on it * chore: remove go1.12 from travis matrix and add go1.15 Signed-off-by: William Poussier --- .travis.yml | 2 +- go.mod | 3 +- go.sum | 4 +++ pkg/plugins/builtin/http/README.md | 27 ++++++++-------- pkg/plugins/builtin/http/http.go | 52 ++++++++++++++++++++++-------- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index 13e563d9..20802f21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,9 @@ dist: bionic language: go go: + - "1.15" - "1.14" - "1.13" - - "1.12" - "master" go_import_path: github.com/ovh/utask diff --git a/go.mod b/go.mod index 93a3270a..acfb78ef 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,8 @@ require ( github.com/wI2L/fizz v0.13.4 github.com/ybriffa/deepcopy v0.0.0-20200601125345-88c31e59651d github.com/ziutek/mymysql v1.5.4 // indirect - golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 + golang.org/x/net v0.0.0-20200904194848-62affa334b73 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a golang.org/x/sys v0.0.0-20200523222454-059865788121 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect diff --git a/go.sum b/go.sum index c7d61beb..9fd64747 100644 --- a/go.sum +++ b/go.sum @@ -366,6 +366,8 @@ golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -382,6 +384,8 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCT golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/pkg/plugins/builtin/http/README.md b/pkg/plugins/builtin/http/README.md index bf63c3b0..08b65500 100644 --- a/pkg/plugins/builtin/http/README.md +++ b/pkg/plugins/builtin/http/README.md @@ -4,19 +4,20 @@ This plugin permorms an HTTP request. ## Configuration -|Fields|Description -|---|--- -| `url` | destination for the http call, including host, path and query params; this all-in-one field conflicts with `host` and `path` -| `host` | destination host for the http call; this field conflicts with the all-in-one field `url` -| `path` | path for the http call; to use jointly with the `host` field; this field conflicts with the all-in-one field `url` -| `method` | http method (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) -| `body` | a string representing the payload to be sent with the request -| `headers` | a list of headers, represented as (`name`, `value`) pairs -| `timeout` | timeout expressed as a duration (e.g. `30s`) -| `auth` | a single object composed of either a `basic` object with `user` and `password` fields to enable HTTP basic auth, or `bearer` field to enable Bearer Token Authorization -| `follow_redirect` | if `true` (string) the plugin will follow up to 10 redirects (302, ...) -| `query_parameters` | a list of query parameters, represented as (`name`, `value`) pairs; these will appended the query parameters present in the `url` field; parameters can be repeated (in either `url` or `query_parameters`) which will produce e.g. `?param=value1¶m=value2` -| `trim_prefix`| prefix in the response that must be removed before unmarshalling (optional) +| Fields | Description | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `url` | destination for the http call, including host, path and query params; this all-in-one field conflicts with `host` and `path` | +| `host` | destination host for the http call; this field conflicts with the all-in-one field `url` | +| `path` | path for the http call; to use jointly with the `host` field; this field conflicts with the all-in-one field `url` | +| `method` | http method (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) | +| `body` | a string representing the payload to be sent with the request | +| `headers` | a list of headers, represented as (`name`, `value`) pairs | +| `timeout` | timeout expressed as a duration (e.g. `30s`) | +| `auth` | a single object composed of either a `basic` object with `user` and `password` fields to enable HTTP basic auth, or `bearer` field to enable Bearer Token Authorization | +| `follow_redirect` | if `true` (string) the plugin will follow up to 10 redirects (302, ...) | +| `query_parameters` | a list of query parameters, represented as (`name`, `value`) pairs; these will appended the query parameters present in the `url` field; parameters can be repeated (in either `url` or `query_parameters`) which will produce e.g. `?param=value1¶m=value2` | +| `trim_prefix` | prefix in the response that must be removed before unmarshalling (optional) | +| `insecure_skip_verify` | If `true` (string), disables server's certificate chain and host verification. | ## Example diff --git a/pkg/plugins/builtin/http/http.go b/pkg/plugins/builtin/http/http.go index 3b4f6f95..f3208064 100644 --- a/pkg/plugins/builtin/http/http.go +++ b/pkg/plugins/builtin/http/http.go @@ -2,6 +2,7 @@ package pluginhttp import ( "bytes" + "crypto/tls" "encoding/xml" "errors" "fmt" @@ -16,6 +17,7 @@ import ( "github.com/ovh/utask/pkg/plugins/builtin/httputil" "github.com/ovh/utask/pkg/plugins/taskplugin" "github.com/ovh/utask/pkg/utils" + "golang.org/x/net/http2" ) // the HTTP plugin performs an HTTP call @@ -26,6 +28,15 @@ var ( ) ) +var defaultUnsecureTransport http.RoundTripper + +func init() { + tr := http.DefaultTransport.(*http.Transport).Clone() + tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + _ = http2.ConfigureTransport(tr) + defaultUnsecureTransport = tr +} + const ( // TimeoutDefault represents the default value that will be used for HTTP call, if not defined in configuration TimeoutDefault = "30s" @@ -33,17 +44,18 @@ const ( // HTTPConfig is the configuration needed to perform an HTTP call type HTTPConfig struct { - URL string `json:"url"` - Host string `json:"host"` - Path string `json:"path"` - Method string `json:"method"` - Body string `json:"body,omitempty"` - Headers []parameter `json:"headers,omitempty"` - Timeout string `json:"timeout,omitempty"` - Auth auth `json:"auth,omitempty"` - FollowRedirect string `json:"follow_redirect,omitempty"` - QueryParameters []parameter `json:"query_parameters,omitempty"` - TrimPrefix string `json:"trim_prefix,omitempty"` + URL string `json:"url"` + Host string `json:"host"` + Path string `json:"path"` + Method string `json:"method"` + Body string `json:"body,omitempty"` + Headers []parameter `json:"headers,omitempty"` + Timeout string `json:"timeout,omitempty"` + Auth auth `json:"auth,omitempty"` + FollowRedirect string `json:"follow_redirect,omitempty"` + QueryParameters []parameter `json:"query_parameters,omitempty"` + TrimPrefix string `json:"trim_prefix,omitempty"` + InsecureSkipVerify string `json:"insecure_skip_verify,omitempty"` } // parameter represents either headers, query parameters, ... @@ -193,10 +205,24 @@ func exec(stepName string, config interface{}, ctx interface{}) (interface{}, in if cfg.FollowRedirect != "" { fr, err = strconv.ParseBool(cfg.FollowRedirect) if err != nil { - return nil, nil, fmt.Errorf("failed to parse allow redirect: %s", err) + return nil, nil, fmt.Errorf("failed to parse follow_redirect: %s", err) + } + } + var insecureSkipVerify bool + if cfg.InsecureSkipVerify != "" { + insecureSkipVerify, err = strconv.ParseBool(cfg.InsecureSkipVerify) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse insecure_skip_verify: %s", err) } } - httpClient := httputil.NewHTTPClient(httputil.HTTPClientConfig{Timeout: td, FollowRedirect: fr}) + httpClientConfig := httputil.HTTPClientConfig{ + Timeout: td, + FollowRedirect: fr, + } + if insecureSkipVerify { + httpClientConfig.Transport = defaultUnsecureTransport + } + httpClient := httputil.NewHTTPClient(httpClientConfig) resp, err := httpClient.Do(req) if err != nil {