From 7f9152c65570c354c6a77ae9fbcc6cfde68ef735 Mon Sep 17 00:00:00 2001 From: Jesse Alford Date: Mon, 13 Feb 2023 16:31:29 -0800 Subject: [PATCH] Handle vSphere usernames with URI-reserved chars Note the backticks for the username with a backslash in it; this type of literal seems clearer than the \\ escaping. The & sign has no special meaning in go and can be a "normal" interpreted string literal. --- vmlifecycle/configfetchers/initialize.go | 2 +- vmlifecycle/configfetchers/initialize_test.go | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/vmlifecycle/configfetchers/initialize.go b/vmlifecycle/configfetchers/initialize.go index 90c707da0..fd4036ade 100644 --- a/vmlifecycle/configfetchers/initialize.go +++ b/vmlifecycle/configfetchers/initialize.go @@ -311,5 +311,5 @@ func buildURL(creds *Credentials) (string, error) { return "", fmt.Errorf("the '--vsphere-url=%s' was not supplied a protocol (http or https), like https://vcenter.example.com", creds.VSphere.URL) } - return fmt.Sprintf("%s://%s:%s@%s/sdk", parsedURL.Scheme, creds.VSphere.Username, url.QueryEscape(creds.VSphere.Password), parsedURL.Host), nil + return fmt.Sprintf("%s://%s:%s@%s/sdk", parsedURL.Scheme, url.QueryEscape(creds.VSphere.Username), url.QueryEscape(creds.VSphere.Password), parsedURL.Host), nil } diff --git a/vmlifecycle/configfetchers/initialize_test.go b/vmlifecycle/configfetchers/initialize_test.go index b9334d8c1..ee363d3af 100644 --- a/vmlifecycle/configfetchers/initialize_test.go +++ b/vmlifecycle/configfetchers/initialize_test.go @@ -280,6 +280,39 @@ var _ = Describe("selects the correct config fetcher based on the state file", f }) }) + When("the username and password include URI-reserved characters", func() { + It("URI-encodes them for use in requests in the fetcher", func() { + state := &vmmanagers.StateInfo{ + IAAS: "vsphere", + ID: "/DC0/vm/DC0_H0_VM0", + } + + model := simulator.VPX() + err := model.Create() + Expect(err).ToNot(HaveOccurred()) + + model.Service.TLS = nil + s := model.Service.NewServer() + defer s.Close() + + creds := &configfetchers.Credentials{ + VSphere: &configfetchers.VCenterCredentialsWrapper{ + VcenterCredential: vmmanagers.VcenterCredential{ + URL: s.URL.String(), + Username: `some\username`, + Password: "some-password-with-ampersand-&", + }, + Insecure: true, + }, + } + + vSphereConfigFetcher, err := configfetchers.NewOpsmanConfigFetcher(state, creds) + Expect(err).ToNot(HaveOccurred()) + + Expect(reflect.TypeOf(vSphereConfigFetcher)).To(Equal(reflect.TypeOf(&configfetchers.VSphereConfigFetcher{}))) + }) + }) + When("the insecure value is set to false and the server url is https", func() { It("does not return an error", func() { state := &vmmanagers.StateInfo{