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