Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Upload Attachments from ServiceNow to Azure Blob Storage

Alessandro22
Tera Contributor

Hello,
I created this code to be able to send a json file to my azure storage. When I try to generate the token with the generateSasToken function I get an undefined signature.
Can anyone help me with this?

 

(function() {
 
    var azureStorageAccountName = 'my_storage_name';
    var azureStorageAccountKey = 'my_storage_key';
    var azureStorageContainerName = 'my_container';
    var jsonFileName = 'incident_list.json';
   
    var incidentQuery = 'sys_updated_onONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()^ORDERBYnumber';
   
    var incidentGR = new GlideRecord('incident');
    incidentGR.addEncodedQuery(incidentQuery);
    incidentGR.setLimit(1);
    incidentGR.query();

    var incidentList = [];

    while (incidentGR.next()) {
        var incident = {
            "number": incidentGR.getValue('number'),
            "opened_at": incidentGR.getValue('opened_at'),
            "short_description": incidentGR.getValue('short_description'),
            "caller_id": incidentGR.getValue('caller_id'),
            "priority": incidentGR.getValue('priority'),
            "state": incidentGR.getValue('state'),
            "category": incidentGR.getValue('category'),
            "assignment_group": incidentGR.getValue('assignment_group'),
            "assigned_to": incidentGR.getValue('assigned_to')
        };
        incidentList.push(incident);
    }

    var jsonString = JSON.stringify(incidentList);
 
    var blobServiceEndpoint = 'https://' + azureStorageAccountName + '.blob.core.windows.net';
    var blobSasToken = generateSasToken(azureStorageAccountName, azureStorageAccountKey, azureStorageContainerName, jsonFileName);

    var blobUrl = blobServiceEndpoint + '/' + azureStorageContainerName + '/' + jsonFileName + blobSasToken;
    gs.info('Blob URL: ' + blobUrl);

    try {
        var httpRequest = new sn_ws.RESTMessageV2();
        httpRequest.setEndpoint(blobUrl);
        httpRequest.setHttpMethod('PUT');
        httpRequest.setRequestHeader('x-ms-blob-type', 'BlockBlob');
        httpRequest.setRequestBody(jsonString);
 
        var response = httpRequest.execute();
 
        var httpResponseStatus = response.getStatusCode();
        var httpResponseContentType = response.getHeader('Content-Type');
        var httpResponse = response.getBody();
 
    } catch (error) {
        gs.error('Error loading certificate: ' + error);
        gs.error('Stack trace: ' + error.getStackTrace());
    }
    
    function generateSasToken(accountName, accountKey, containerName, blobName) {

        var startDate = new Date();
        var expiryDate = new Date();
        startDate.setMinutes(startDate.getMinutes() - 5);
        expiryDate.setFullYear(expiryDate.getFullYear() + 1);

        var signedPermissions = 'rwdlac';
        var signedService = 'b';
        var signedResourceType = 'c';

        var signedStart = formatDate(startDate);
        var signedExpiry = formatDate(expiryDate);

        var canonicalizedResource = '/' + accountName + '/' + containerName + '/' + blobName;

        var stringToSign = signedPermissions + '\n' +
                           signedStart + '\n' +
                           signedExpiry + '\n' +
                           canonicalizedResource + '\n' +
                           '\n' +
                           signedService + '\n' +
                           signedResourceType;
       
       
        var hmac = new GlideDigest();
        hmac.setAlgorithm('HmacSHA256');
        var signature = hmac.base64Digest(accountKey, stringToSign);

        gs.info('String to sign: ' + stringToSign);
        gs.info('Generated Signature: ' + signature);
        gs.info('accountKey: --> ' + accountKey);

        var sasToken = 'sv=' + signedStart +
                       '&se=' + signedExpiry +
                       '&sr=' + signedResourceType +
                       '&sp=' + signedPermissions +
                       '&spr=' + signedService +
                       '&sig=' + encodeURIComponent(signature);

        gs.info('Token --> ' + sasToken);

        return '?' + sasToken;
    }
 
    function formatDate(date) {
        gs.info('date: ' + date);
        var formattedDate = date.toISOString();
        formattedDate = formattedDate.replace(/\.\d{3}Z$/, 'Z');
        return formattedDate;
    }
})();
5 REPLIES 5

Alessandro22
Tera Contributor

Hi Iraj,

thanks for your help but the code is still not working.

I replaced my code as you suggested but the signature is "undefined".

Below is my code with the secret key:

 

   

 

    var azureStorageAccountName = 'my_storage';
    var azureStorageAccountKey = 'mJqa800ItOc3XuK1u7pAeKdYcfwINa0wMxOaxGgjfaQW65GOhjkPYqD/C4qMCnmGevnyD3QnJWJp+AStJB4ExA==';
    var azureStorageContainerName = 'my_container';
    var fileDate = new GlideDate();
    var jsonFileName = 'incident_list_' + fileDate.getByFormat('yyyyMMdd') + '.json';

    var incidentQuery = 'active=true^ORDERBYnumber';
    var incidentList = [];

    var incidentGR = new GlideRecord('incident');
    incidentGR.addEncodedQuery(incidentQuery);
    incidentGR.setLimit(1);
    incidentGR.query();  
    while (incidentGR.next()) {
        var incident = {
            "number": incidentGR.getValue('number'),
            "opened_at": incidentGR.getValue('opened_at'),
            "short_description": incidentGR.getValue('short_description'),
            "caller_id": incidentGR.getDisplayValue('caller_id'),
            "priority": incidentGR.getDisplayValue('priority'),
            "state": incidentGR.getDisplayValue('state'),
            "category": incidentGR.getValue('category'),
            "assignment_group": incidentGR.getDisplayValue('assignment_group'),
            "assigned_to": incidentGR.getDisplayValue('assigned_to')
        };
        incidentList.push(incident);
    }

    var jsonString = JSON.stringify(incidentList);

    var blobServiceEndpoint = 'https://' + azureStorageAccountName + '.blob.core.windows.net';
    var blobSasToken = generateSasToken(azureStorageAccountName, azureStorageAccountKey, azureStorageContainerName, jsonFileName);
    var blobUrl = blobServiceEndpoint + '/' + azureStorageContainerName + '/' + jsonFileName + blobSasToken;
    gs.info('Blob URL: ' + blobUrl);


function generateSasToken(accountName, accountKey, containerName, blobName) {

        var startDate = new Date();
        var expiryDate = new Date();
        startDate.setMinutes(startDate.getMinutes() - 5);
        expiryDate.setFullYear(expiryDate.getFullYear() + 1);

        var signedPermissions = 'racw';
        var signedService = 'b';
        var signedResourceType = 'c';
        var signedStart = formatDate(startDate);
        var signedExpiry = formatDate(expiryDate);
        var signedVersion = '2022-11-02';
        var canonicalizedResource = '/' + accountName + '/' + containerName + '/' + blobName;

        var stringToSign = signedPermissions + '\n' +
                           signedStart + '\n' +
                           signedExpiry + '\n' +
                           canonicalizedResource + '\n' +
                           accountName + '\n' +
                           '\n' + // Identifier
                           '\n' + // IP
                           '\n' + // Protocol
                           signedVersion + '\n' + // Version
                           '\n';  // Resource
         
        var hmac = new GlideDigest();
        hmac.setAlgorithm('HmacSHA256');
        var decodedKey = GlideStringUtil.base64Decode(accountKey); // Decode the base64 account key
        var signature = hmac.getHMACBase64(decodedKey, stringToSign); // Generate the HMAC signature

        gs.info('decodedKey: ' + decodedKey);
        gs.info('String to sign: ' + stringToSign);
        gs.info('Generated Signature: ' + signature);

        var sasToken = 'sp=' + signedPermissions +
                    '&st=' + encodeURIComponent(signedStart) +
                    '&se=' + encodeURIComponent(signedExpiry) +
                    '&spr=' + signedService +
                    '&sv=' + signedVersion +
                    '&sr=' + signedResourceType +
                    '&sig=' + encodeURIComponent(signature); // URL encode the signature

        gs.info('Token --> ' + sasToken);

        return '?' + sasToken;
    }

    function formatDate(date) {
        gs.info('date: ' + date);
        var formattedDate = date.toISOString();
        formattedDate = formattedDate.replace(/\.\d{3}Z$/, 'Z');
        return formattedDate;
    }

 

String to sign: racw
2024-01-24T06:45:37Z
2025-01-24T06:50:37Z
/my_storage/my_container/incident_list_20240124.json
my_storage



2022-11-02