From 54f7fd0564f89d940944feebfe3ec46febd9328a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20L=C3=B3pez=20G=C3=B3mez?= Date: Fri, 23 Sep 2016 11:57:33 +0200 Subject: [PATCH] HttpGetter with Basic Auth + tests --- README.md | 6 +++++- get_http.go | 47 ++++++++++++++++++++++++++++++++++++++++++++--- get_http_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 30aed323f..7f6a7b63a 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,11 @@ None ### HTTP (`http`) -None +If the HTTP server is secured with Basic authorization, you can configure username +and password using these parameters: + + * `http_basic_auth_user` - HTTP Basic authorization username + * `http_basic_auth_pass` - HTTP Basic authorization password ### S3 (`s3`) diff --git a/get_http.go b/get_http.go index d64b23835..6b6c2f01d 100644 --- a/get_http.go +++ b/get_http.go @@ -17,7 +17,7 @@ import ( // // For file downloads, HTTP is used directly. // -// The protocol for downloading a directory from an HTTP endpoing is as follows: +// The protocol for downloading a directory from an HTTP endpoint is as follows: // // An HTTP GET request is made to the URL with the additional GET parameter // "terraform-get=1". This lets you handle that scenario specially if you @@ -55,8 +55,21 @@ func (g *HttpGetter) Get(dst string, u *url.URL) error { q.Add("terraform-get", "1") u.RawQuery = q.Encode() + // Create Request + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return err + } + + // Get HTTP BasicAuth creds from url + basicAuthUser, basicAuthPass := g.getHttpBasicAuth(u) + // Set HTTP Basic Auth to request + if basicAuthUser != "" && basicAuthPass != "" { + req.SetBasicAuth(basicAuthUser, basicAuthPass) + } + // Get the URL - resp, err := http.Get(u.String()) + resp, err := http.DefaultClient.Do(req) if err != nil { return err } @@ -91,7 +104,21 @@ func (g *HttpGetter) Get(dst string, u *url.URL) error { } func (g *HttpGetter) GetFile(dst string, u *url.URL) error { - resp, err := http.Get(u.String()) + // Create Request + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return err + } + + // Get HTTP BasicAuth creds from url + basicAuthUser, basicAuthPass := g.getHttpBasicAuth(u) + // Set HTTP Basic Auth to request + if basicAuthUser != "" && basicAuthPass != "" { + req.SetBasicAuth(basicAuthUser, basicAuthPass) + } + + // Get the URL + resp, err := http.DefaultClient.Do(req) if err != nil { return err } @@ -115,6 +142,20 @@ func (g *HttpGetter) GetFile(dst string, u *url.URL) error { return err } +func (g *HttpGetter) getHttpBasicAuth(u *url.URL) (basicAuthUser, basicAuthPass string) { + qUser := "http_basic_auth_user" + qPass := "http_basic_auth_pass" + + q := u.Query() + basicAuthUser = q.Get(qUser) + basicAuthPass = q.Get(qPass) + q.Del(qUser) + q.Del(qPass) + u.RawQuery = q.Encode() + + return +} + // getSubdir downloads the source into the destination, but with // the proper subdir. func (g *HttpGetter) getSubdir(dst, source, subDir string) error { diff --git a/get_http_test.go b/get_http_test.go index 2501c3593..9c169473e 100644 --- a/get_http_test.go +++ b/get_http_test.go @@ -153,6 +153,35 @@ func TestHttpGetter_auth(t *testing.T) { } } +func TestHttpGetter_basicAuth(t *testing.T) { + ln := testHttpServer(t) + defer ln.Close() + + g := new(HttpGetter) + dst := tempDir(t) + + var u url.URL + u.Scheme = "http" + u.Host = ln.Addr().String() + u.Path = "/file-basic-auth" + // set HTTP basic auth with query params + q := u.Query() + q.Add("http_basic_auth_user", "basicUser") + q.Add("http_basic_auth_pass", "basicPass") + u.RawQuery = q.Encode() + + // Get it! + if err := g.GetFile(dst, &u); err != nil { + t.Fatalf("err: %s", err) + } + + // Verify the main file exists + if _, err := os.Stat(dst); err != nil { + t.Fatalf("err: %s", err) + } + assertContents(t, dst, "HelloBasicAuth\n") +} + func TestHttpGetter_authNetrc(t *testing.T) { ln := testHttpServer(t) defer ln.Close() @@ -190,6 +219,7 @@ func testHttpServer(t *testing.T) net.Listener { mux := http.NewServeMux() mux.HandleFunc("/file", testHttpHandlerFile) + mux.HandleFunc("/file-basic-auth", testHttpHandlerFileBasicAuth) mux.HandleFunc("/header", testHttpHandlerHeader) mux.HandleFunc("/meta", testHttpHandlerMeta) mux.HandleFunc("/meta-auth", testHttpHandlerMetaAuth) @@ -206,6 +236,21 @@ func testHttpHandlerFile(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello\n")) } +func testHttpHandlerFileBasicAuth(w http.ResponseWriter, r *http.Request) { + user, pass, ok := r.BasicAuth() + if !ok { + w.WriteHeader(401) + return + } + + if user != "basicUser" || pass != "basicPass" { + w.WriteHeader(401) + return + } + + w.Write([]byte("HelloBasicAuth\n")) +} + func testHttpHandlerHeader(w http.ResponseWriter, r *http.Request) { w.Header().Add("X-Terraform-Get", testModuleURL("basic").String()) w.WriteHeader(200)