From 331babc2ce302ff70a88bba3e5c24c6223e4b8d9 Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Thu, 12 Sep 2019 12:37:46 +0200 Subject: [PATCH] allow blank access_token (no auth) for private vagrant box hosting --- post-processor/vagrant-cloud/client.go | 8 ++-- .../vagrant-cloud/post-processor.go | 9 ++-- .../vagrant-cloud/post-processor_test.go | 43 +++++++++++++++++++ .../post-processors/vagrant-cloud.html.md | 27 +++++++----- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/post-processor/vagrant-cloud/client.go b/post-processor/vagrant-cloud/client.go index e63196684..ec71b97e9 100644 --- a/post-processor/vagrant-cloud/client.go +++ b/post-processor/vagrant-cloud/client.go @@ -106,12 +106,10 @@ func (v *VagrantCloudClient) Delete(path string) (*http.Response, error) { scrubbedUrl := strings.Replace(reqUrl, v.AccessToken, "ACCESS_TOKEN", -1) log.Printf("Post-Processor Vagrant Cloud API DELETE: %s", scrubbedUrl) - req, err := http.NewRequest("DELETE", reqUrl, nil) + req, err := v.newRequest("DELETE", reqUrl, nil) if err != nil { return nil, err } - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", v.AccessToken)) resp, err := v.client.Do(req) log.Printf("Post-Processor Vagrant Cloud API Response: \n\n%+v", resp) @@ -196,6 +194,8 @@ func (v *VagrantCloudClient) newRequest(method, url string, body io.Reader) (*ht return nil, err } req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", v.AccessToken)) + if len(v.AccessToken) > 0 { + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", v.AccessToken)) + } return req, err } diff --git a/post-processor/vagrant-cloud/post-processor.go b/post-processor/vagrant-cloud/post-processor.go index 49c342e05..a02888148 100644 --- a/post-processor/vagrant-cloud/post-processor.go +++ b/post-processor/vagrant-cloud/post-processor.go @@ -98,9 +98,8 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { // Required configuration templates := map[string]*string{ - "box_tag": &p.config.Tag, - "version": &p.config.Version, - "access_token": &p.config.AccessToken, + "box_tag": &p.config.Tag, + "version": &p.config.Version, } for key, ptr := range templates { @@ -110,6 +109,10 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { } } + if p.config.VagrantCloudUrl == VAGRANT_CLOUD_URL && p.config.AccessToken == "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("access_token must be set if vagrant_cloud_url has not been overriden")) + } + // Create the HTTP client p.client, err = VagrantCloudClient{}.New(p.config.VagrantCloudUrl, p.config.AccessToken, p.insecureSkipTLSVerify) if err != nil { diff --git a/post-processor/vagrant-cloud/post-processor_test.go b/post-processor/vagrant-cloud/post-processor_test.go index 4c06abead..d4d1552f6 100644 --- a/post-processor/vagrant-cloud/post-processor_test.go +++ b/post-processor/vagrant-cloud/post-processor_test.go @@ -38,6 +38,14 @@ func testBadConfig() map[string]interface{} { } } +func testNoAccessTokenProvidedConfig() map[string]interface{} { + return map[string]interface{}{ + "box_tag": "baz", + "version_description": "bar", + "version": "0.5", + } +} + func newSecureServer(token string, handler http.HandlerFunc) *httptest.Server { token = fmt.Sprintf("Bearer %s", token) return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { @@ -64,6 +72,18 @@ func newSelfSignedSslServer(token string, handler http.HandlerFunc) *httptest.Se })) } +func newNoAuthServer(handler http.HandlerFunc) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if req.Header.Get("authorization") != "" { + http.Error(rw, "Authorization header was provider", http.StatusBadRequest) + return + } + if handler != nil { + handler(rw, req) + } + })) +} + func TestPostProcessor_Insecure_Ssl(t *testing.T) { var p PostProcessor server := newSelfSignedSslServer("foo", nil) @@ -147,6 +167,29 @@ func TestPostProcessor_Configure_Bad(t *testing.T) { } } +func TestPostProcessor_Configure_checkAccessTokenIsRequiredByDefault(t *testing.T) { + var p PostProcessor + server := newSecureServer("foo", nil) + defer server.Close() + + config := testNoAccessTokenProvidedConfig() + if err := p.Configure(config); err == nil { + t.Fatalf("Expected access token to be required.") + } +} + +func TestPostProcessor_Configure_checkAccessTokenIsNotRequiredForOverridenVagrantCloud(t *testing.T) { + var p PostProcessor + server := newNoAuthServer(nil) + defer server.Close() + + config := testNoAccessTokenProvidedConfig() + config["vagrant_cloud_url"] = server.URL + if err := p.Configure(config); err != nil { + t.Fatalf("Expected blank access token to be allowed and authenticate to pass: %s", err) + } +} + func TestPostProcessor_PostProcess_checkArtifactType(t *testing.T) { artifact := &packer.MockArtifact{ BuilderIdValue: "invalid.builder", diff --git a/website/source/docs/post-processors/vagrant-cloud.html.md b/website/source/docs/post-processors/vagrant-cloud.html.md index c3e30fd0e..f3ba90b3c 100644 --- a/website/source/docs/post-processors/vagrant-cloud.html.md +++ b/website/source/docs/post-processors/vagrant-cloud.html.md @@ -54,12 +54,6 @@ on Vagrant Cloud, as well as authentication and version information. ### Required: -- `access_token` (string) - Your access token for the Vagrant Cloud API. This - can be generated on your [tokens - page](https://app.vagrantup.com/settings/security). If not specified, the - environment will be searched. First, `VAGRANT_CLOUD_TOKEN` is checked, and - if nothing is found, finally `ATLAS_TOKEN` will be used. - - `box_tag` (string) - The shorthand tag for your box that maps to Vagrant Cloud, for example `hashicorp/precise64`, which is short for `vagrantcloud.com/hashicorp/precise64`. @@ -70,16 +64,29 @@ on Vagrant Cloud, as well as authentication and version information. be semver, and doesn't validate that the version comes after your previous versions. +- `access_token` (string) - Your access token for the Vagrant Cloud API. This + can be generated on your [tokens + page](https://app.vagrantup.com/settings/security). If not specified, the + environment will be searched. First, `VAGRANT_CLOUD_TOKEN` is checked, and + if nothing is found, finally `ATLAS_TOKEN` will be used. This is required + unless you are using a private hosting solution (i.e. `vagrant_cloud_url` + has been populated). + + **or** + +- `vagrant_cloud_url` (string) - Override the base URL for Vagrant Cloud. + This is useful if you're using Vagrant Private Cloud in your own network. + Defaults to `https://vagrantcloud.com/api/v1`. If this value is set to something + other than the default then `access_token` can be left blank and no + `Authorization` header will be added to requests sent by this post-processor. + + ### Optional: - `no_release` (string) - If set to true, does not release the version on Vagrant Cloud, making it active. You can manually release the version via the API or Web UI. Defaults to false. -- `vagrant_cloud_url` (string) - Override the base URL for Vagrant Cloud. - This is useful if you're using Vagrant Private Cloud in your own network. - Defaults to `https://vagrantcloud.com/api/v1` - - `insecure_skip_tls_verify` (boolean) - If set to true *and* `vagrant_cloud_url` is set to something different than its default, it will set TLS InsecureSkipVerify to true. In other words, this will disable security checks of SSL. You may need