Skip to content
Closed
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
19 changes: 13 additions & 6 deletions cloudstack/cloudstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,17 +464,24 @@ func (cs *CloudStackClient) newRawRequest(api string, post bool, params url.Valu
params.Set("command", api)
params.Set("response", "json")

// Generate signature for API call
// encode parameters
// * Serialize parameters, URL encoding only values and sort them by key, done by encodeValues
// * Replace encoded asterisk (*) back to literal.
// CloudStack’s internal encoder does not encode them; this results in an authentication failure for your API call.
// http://docs.cloudstack.apache.org/projects/archived-cloudstack-getting-started/en/latest/dev.html
// Not documented http://docs.cloudstack.apache.org/en/latest/developersguide/dev.html#the-cloudstack-api
encodedParams := encodeValues(params)
encodedParams = strings.Replace(encodedParams, "%2A", "*", -1)
Copy link
Member

@rohityadavcloud rohityadavcloud Mar 22, 2023

Choose a reason for hiding this comment

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

Would you think this also affects cmk cc @mlsorensen ? The referenced docs are quite old and written for Python, the more recent Go implementation in cmk uses this code for network request:
https://github.com/apache/cloudstack-cloudmonkey/blob/main/cmd/network.go

Copy link
Contributor

@mlsorensen mlsorensen Mar 22, 2023

Choose a reason for hiding this comment

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

It does, you can't set a value with an asterisk via the Go implementation of cloudmonkey.

Copy link
Member

Choose a reason for hiding this comment

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


// Generate signature for API call
// * Convert the entire argument string to lowercase
// * Replace all instances of '+' to '%20'
// * Calculate HMAC SHA1 of argument string with CloudStack secret
// * URL encode the string and convert to base64
s := encodeValues(params)
s2 := strings.ToLower(s)
s3 := strings.Replace(s2, "+", "%20", -1)
sigParams := strings.ToLower(encodedParams)
sigParams = strings.Replace(sigParams, "+", "%20", -1)
mac := hmac.New(sha1.New, []byte(cs.secret))
mac.Write([]byte(s3))
mac.Write([]byte(sigParams))
signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))

var err error
Expand All @@ -490,7 +497,7 @@ func (cs *CloudStackClient) newRawRequest(api string, post bool, params url.Valu
resp, err = cs.client.PostForm(cs.baseURL, params)
} else {
// Create the final URL before we issue the request
url := cs.baseURL + "?" + s + "&signature=" + url.QueryEscape(signature)
url := cs.baseURL + "?" + encodedParams + "&signature=" + url.QueryEscape(signature)

// Make a GET call
resp, err = cs.client.Get(url)
Expand Down