We've got a containerized Azure Function, implemented as Node.js application. The container is pulled from Azure Container Registry.
This Node.js app - which runs in the container - needs to access Microsoft Graph (as application, without user context). Basically like shown here:
https://learn.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-nodejs-console
But with the following differences:
(Why Azure Key Vault? Because we want to use its features like automated renewal.)
How would we implement this? The container part is making things complicated it seems.
You could get the certificate from keyvault.
const { DefaultAzureCredential } = require("@azure/identity");
const { CertificateClient } = require("@azure/keyvault-certificates");
const credential = new DefaultAzureCredential();
const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;
const client = new CertificateClient(url, credential);
const certificateName = "MyCertificateName";
async function main() {
const latestCertificate = await client.getCertificate(certificateName);
console.log(`Latest version of the certificate ${certificateName}: `, latestCertificate);
const specificCertificate = await client.getCertificateVersion(
certificateName,
latestCertificate.properties.version
);
console.log(
`The certificate ${certificateName} at the version ${latestCertificate.properties.version}: `,
specificCertificate
);
}
main();
Then get the access token for Microsoft Graph with the adal, don't forget to change the resource
to https://graph.microsoft.com
, also change the values to yours.
'use strict';
var fs = require('fs');
var adal = require('adal-node');
var AuthenticationContext = adal.AuthenticationContext;
function turnOnLogging() {
var log = adal.Logging;
log.setLoggingOptions(
{
level : log.LOGGING_LEVEL.VERBOSE,
log : function(level, message, error) {
console.log(message);
if (error) {
console.log(error);
}
}
});
}
function getPrivateKey(filename) {
var privatePem = fs.readFileSync(filename, { encoding : 'utf8'});
return privatePem;
}
/*
* You can override the default account information by providing a JSON file
* with the same parameters as the sampleParameters variable below. Either
* through a command line argument, 'node sample.js parameters.json', or
* specifying in an environment variable.
* privateKeyFile must contain a PEM encoded cert with private key.
* thumbprint must be the thumbprint of the privateKeyFile.
* {
* tenant : 'naturalcauses.onmicrosoft.com',
* authorityHostUrl : 'https://login.windows.net',
* clientId : 'd6835713-b745-48d1-bb62-7a8248477d35',
* thumbprint : 'C1:5D:EA:86:56:AD:DF:67:BE:80:31:D8:5E:BD:DC:5A:D6:C4:36:E1',
* privateKeyFile : 'ncwebCTKey.pem'
* }
*/
var parametersFile = process.argv[2] || process.env['ADAL_SAMPLE_PARAMETERS_FILE'];
var sampleParameters;
if (parametersFile) {
var jsonFile = fs.readFileSync(parametersFile);
if (jsonFile) {
sampleParameters = JSON.parse(jsonFile);
} else {
console.log('File not found, falling back to defaults: ' + parametersFile);
}
}
sampleParameters = {
tenant : 'naturalcauses.com',
authorityHostUrl : 'https://login.windows.net',
clientId : 'd6835713-b745-48d1-bb62-7a8248477d35',
thumbprint : 'C15DEA8656ADDF67BE8031D85EBDDC5AD6C436E1',
privateKeyFile : ''
};
var authorityUrl = sampleParameters.authorityHostUrl + '/' + sampleParameters.tenant;
var resource = 'https://graph.microsoft.com';
turnOnLogging();
var context = new AuthenticationContext(authorityUrl);
var key = getPrivateKey(sampleParameters.privateKeyFile);
context.acquireTokenWithClientCertificate(resource, sampleParameters.clientId, key, sampleParameters.thumbprint, function(err, tokenResponse) {
if (err) {
console.log('well that didn\'t work: ' + err.stack);
} else {
console.log(tokenResponse);
}
});