Skip to content

Instantly share code, notes, and snippets.

@ctcampbell
Last active January 26, 2023 02:13
Show Gist options
  • Save ctcampbell/c82d895b0940c08408fb1800aa6718b0 to your computer and use it in GitHub Desktop.
Save ctcampbell/c82d895b0940c08408fb1800aa6718b0 to your computer and use it in GitHub Desktop.
Postman pre-request to add Veracode HMAC header
var url = require('url');
var { Property } = require('postman-collection');
const id = pm.variables.get('veracodeApiKeyId');
const key = pm.variables.get('veracodeApiKeySecret');
const authorizationScheme = 'VERACODE-HMAC-SHA-256';
const requestVersion = "vcode_request_version_1";
const nonceSize = 16;
function computeHashHex(message, key_hex) {
return CryptoJS.HmacSHA256(message, CryptoJS.enc.Hex.parse(key_hex)).toString(CryptoJS.enc.Hex);
}
function calulateDataSignature(key, nonceBytes, dateStamp, data) {
let kNonce = computeHashHex(nonceBytes, key);
let kDate = computeHashHex(dateStamp, kNonce);
let kSig = computeHashHex(requestVersion, kDate);
let kFinal = computeHashHex(data, kSig);
return kFinal;
}
function newNonce() {
return CryptoJS.lib.WordArray.random(nonceSize).toString().toUpperCase();
}
function toHexBinary(input) {
return CryptoJS.enc.Hex.stringify(CryptoJS.enc.Utf8.parse(input));
}
function calculateVeracodeAuthHeader(httpMethod, requestUrl) {
let urlExpanded = Property.replaceSubstitutions(requestUrl, pm.variables.toObject());
let parsedUrl = url.parse(urlExpanded);
let data = `id=${id}&host=${parsedUrl.hostname}&url=${parsedUrl.path}&method=${httpMethod}`;
let dateStamp = Date.now().toString();
let nonceBytes = newNonce(nonceSize);
let dataSignature = calulateDataSignature(key, nonceBytes, dateStamp, data);
let authorizationParam = `id=${id},ts=${dateStamp},nonce=${toHexBinary(nonceBytes)},sig=${dataSignature}`;
let header = authorizationScheme + " " + authorizationParam;
return header;
}
pm.request.headers.add({
key: 'Authorization',
value: calculateVeracodeAuthHeader(request['method'], request['url'])
});
@GavinF17
Copy link

Found this script very useful working with the API, though I ran into an issue using variables in my URL to prevent having to retype https://analysiscenter.veracode.com/api/5.0/ in each request, as {{URL}}getapplist.do would be passed in to request['url'] and cause issues with the URL parsing.

I got around this by using the replaceSubstitutions function provided in Postman:

var {Property} = require('postman-collection');
const substitutedUrl = Property.replaceSubstitutions(request.url, pm.variables.toObject());
postman.setEnvironmentVariable('hmacAuthHeader', calculateVeracodeAuthHeader(request.method, substitutedUrl));

@ctcampbell
Copy link
Author

Thanks for that Gavin, looks useful.

@marleybobs
Copy link

Hi Gavin, this is great - I was struggling to get CryptoJS working to create correct Veracode HMAC headers, but this worked perfectly - cheers!
Just an FYI - at the time of posting this comment, there is a problem with the current build of CryptoJS that creates an error when running 'CryptoJS.lib.WordArray.random'.
(I just replaced it with a random hex generator for the time being.)
See brix/crypto-js#256

@vijayk007
Copy link

cryptoJs is not avaiable in servicenow. I created a script include with hmac 256 filel still not working can anyone help me in working this code

@tjarrettveracode
Copy link

One additional step that may help with this script: you need to add an additional header called Authorization and set its value to {{hmacAuthHeader}}. This will substitute in the environment variable that is created at the last step of this script, containing the HMAC authorization.

@vijayk007
Copy link

One additional step that may help with this script: you need to add an additional header called Authorization and set its value to {{hmacAuthHeader}}. This will substitute in the environment variable that is created at the last step of this script, containing the HMAC authorization.

Do you have any scriptinclude written for the crypto js or did you used the outof box servicenow global.SncAuthentication to encrypting

@ctcampbell
Copy link
Author

One additional step that may help with this script: you need to add an additional header called Authorization and set its value to {{hmacAuthHeader}}. This will substitute in the environment variable that is created at the last step of this script, containing the HMAC authorization.

I've updated the script to do this automatically now, so no need to add a header to each request. Also using variables in URLs works now.

@Fleurpot82
Copy link

This is a complete life saver for me as I'm trying to troubleshoot some issues with the Azure DevOps veracode pluggin, and I am not a developer however when I add the script to my postman it's returning "there was an error in evaluating the pre-request script:TypeError: Cannot read property 'length' of undefined...

@markdowd
Copy link

@Fleurpot82 Not sure if you've fixed this yet. You need to specify the two variable values so they can be retrieved in lines 4&5:

  • veracodeApiKeyId
  • veracodeApiKeySecret

If they are zero length it complains when tryoing to validate them.

@ravikumarkd
Copy link

Hi @markdowd, Can you pls share the code which you have executed. Even though i specified api key id and api secret value. it shows the error: "TypeError: Cannot read property 'length' of undefined". And i have given authorization as api key and used values from api credentials from my veracode account.

@markdowd
Copy link

markdowd commented Mar 4, 2022

Hi @ravikumarkd. The error tells you that the values have not been successfully retrieved in the script. Try temporarily replacing the pm.variables.get statements with literals to confirm this.

@ravikumarkd
Copy link

I m in india so the veracode api services will only work in US and European countries. Because the status code is 403 Forbidden even though i gave correct api credentials. the error message is "ApiCredential invalid". Can you please answer about this issue @markdowd, @ctcampbell ?.

@markdowd
Copy link

markdowd commented Mar 4, 2022

@ravikumarkd I'm an end user, but it sounds like you've answered your own question.

@tjarrettveracode
Copy link

Hi @ravikumarkd , there shouldn't be a geographic component to Veracode API services. However, your report makes me wonder if there is something wrong with the API credentials you're using. Are you able to connect to our APIs using those credentials in other ways, e.g. through Veracode integrations or using httpie with the --veracode_hmac authentication method?

If you aren't able to come to resolution on this it may be worth contacting Veracode support to see if they can help you further.

@S-Mughal
Copy link

S-Mughal commented Mar 15, 2022

Hi @ravikumarkd. The error tells you that the values have not been successfully retrieved in the script. Try temporarily replacing the pm.variables.get statements with literals to confirm this.

Any fix for this yet? Removing pm.variables.get gives a 401 error. As with id and key added, the error I receive is TypeError: Cannot read property 'length' of undefined.

@Fleurpot82
Copy link

@Fleurpot82 Not sure if you've fixed this yet. You need to specify the two variable values so they can be retrieved in lines 4&5:

  • veracodeApiKeyId
  • veracodeApiKeySecret

If they are zero length it complains when tryoing to validate them.

Thanks @markdowd, taken me a while to get back to this, I had the variables added, as below it worked fine when a pasted the values directly in. Deleted the variables in my project and re added and it works a treat. No idea what was wrong before as I'd created multiple collections in attempting it earlier!

@tjarrettveracode
Copy link

Please note that we've published an official project and how-to for using Veracode HMAC in Postman here: https://github.com/veracode/veracode-postman

Contributions are welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment