AWS New Relic Synthetic Monitoring Integration


AWS New Relic Synthetic Monitoring Integration


// Import necessary Node.js core modules
var assert = require('assert');
var crypto = require('crypto');

// **Secure Credentials**: Replace 'YOUR_ACCESS_KEY_ID' and 'YOUR_SECRET_ACCESS_KEY' with the names of your secure credentials.
// For example, if you've stored them as 'AWS_ACCESS_KEY_ID' and 'AWS_SECRET_ACCESS_KEY' in New Relic, use $secure.AWS_ACCESS_KEY_ID and $secure.AWS_SECRET_ACCESS_KEY
var accessKey = $secure.AWS_ACCESS; // Replace with your secure credential name
var secretKey = $secure.AWS_SECRET; // Replace with your secure credential name

// Configuration for the AWS service and request
var region = 'us-east-1'; // Replace with your AWS region
var service = 'connect';  // AWS service name, e.g., 'connect' for Amazon Connect
var host = 'connect.us-east-1.amazonaws.com'; // The endpoint of the AWS service
var path = '/instance/abcdefgh-igkl-mnop-qrst-uvwxyzabcdef'; // The API path you're accessing
var method = 'GET'; // HTTP method
var querystring = ''; // Query parameters, if any (for this example, it's empty)
var payload = ''; // Request payload (empty for GET requests)

// Helper function to format dates in the required AWS format
function getAmzDate(date) {
    return date.toISOString().replace(/[:-]|\.\d{3}/g, '');
}

// Helper function to get date in YYYYMMDD format
function getDateStamp(date) {
    return date.toISOString().substring(0, 10).replace(/-/g, '');
}

// Function to hash the payload using SHA256
function hash(payload) {
    return crypto.createHash('sha256').update(payload, 'utf8').digest('hex');
}

// Function to create canonical headers
function getCanonicalHeaders(headers) {
    var keys = Object.keys(headers).sort();
    var canonicalHeaders = '';
    keys.forEach(function(key) {
        canonicalHeaders += key.toLowerCase() + ':' + headers[key].trim() + '\n';
    });
    return canonicalHeaders;
}

// Function to get the signing key
function getSignatureKey(key, dateStamp, regionName, serviceName) {
    var kDate = crypto.createHmac('sha256', 'AWS4' + key).update(dateStamp).digest();
    var kRegion = crypto.createHmac('sha256', kDate).update(regionName).digest();
    var kService = crypto.createHmac('sha256', kRegion).update(serviceName).digest();
    var kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest();
    return kSigning;
}

// Current date and time in UTC
var currentDate = new Date();
var amzdate = getAmzDate(currentDate); // Format: YYYYMMDD'T'HHMMSS'Z'
var datestamp = getDateStamp(currentDate); // Format: YYYYMMDD

// Initial headers required for the request
var headers = {
    'Host': host,
    'X-Amz-Date': amzdate
};

// Specify which headers are being signed
var signedHeaders = 'host;x-amz-date';

// Create the canonical headers string
var canonicalHeaders = getCanonicalHeaders(headers);

// Hash the payload (empty string for GET requests)
var payloadHash = hash(payload);

// Construct the canonical request
var canonicalRequest = method + '\n' + path + '\n' + querystring + '\n' + canonicalHeaders + '\n' + signedHeaders + '\n' + payloadHash;

// Hash the canonical request
var hashedCanonicalRequest = hash(canonicalRequest);

// Create the string to sign
var credentialScope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
var stringToSign = 'AWS4-HMAC-SHA256' + '\n' +  amzdate + '\n' +  credentialScope + '\n' +  hashedCanonicalRequest;

// Calculate the signature
var signingKey = getSignatureKey(secretKey, datestamp, region, service);
var signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex');

// Construct the Authorization header
var authorizationHeader = 'AWS4-HMAC-SHA256 ' + 'Credential=' + accessKey + '/' + credentialScope + ', ' +  'SignedHeaders=' + signedHeaders + ', ' + 'Signature=' + signature;

// Add the Authorization header to the existing headers
headers['Authorization'] = authorizationHeader;

// The full URL for the request
var url = 'https://' + host + path;

// **Debugging Logs**: Uncomment the following lines if you need to debug the signing process
/*
console.log('--- DEBUGGING INFORMATION ---');
console.log('URL:', url);
console.log('Headers:', headers);
console.log('Canonical Request:', canonicalRequest);
console.log('String to Sign:', stringToSign);
console.log('Authorization Header:', authorizationHeader);
console.log('-----------------------------');
*/

// Make the HTTP GET request using New Relic's $http object
$http.get(
    url,
    {
        headers: headers
    },
    function (err, response, body) {
        if (err) {
            console.error('Error during HTTP request:', err);
        } else {
            console.log('HTTP Response Status Code:', response.statusCode);
            console.log('HTTP Response Body:', body);
            
            // Assert that the response status code is 200 OK
            //assert.equal(response.statusCode, 200, 'Expected a 200 OK response');
            
            // Attempt to parse the response body as JSON
            try {
                console.log('Instance ID:', body.Instance.Id);
                console.log('Instance Status:', body.Instance.InstanceStatus);
                
                // **Additional Assertions**: Add any specific assertions based on the expected response
                assert.equal(body.Instance.InstanceStatus, 'ACTIVE', 'Expected the instance status to be ACTIVE');
                
            } catch (error) {
                console.error('Error accessing properties of response body:', error);
            }
        }
    }
);