Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpGetter with Basic Auth + tests #34

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`)

Expand Down
47 changes: 44 additions & 3 deletions get_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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"
Copy link
Contributor

@catsby catsby Sep 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to document the format for users so that they know how to use this authentication.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added documentation in README.md


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 {
Expand Down
45 changes: 45 additions & 0 deletions get_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down