如何使用来自容器化 Node.js Azure Function 的证书进行 MS Graph 身份验证?

时间:2021-05-28 07:20:48

标签: node.js azure-functions microsoft-graph-api azure-keyvault azure-container-registry

我们有一个容器化的 Azure 函数,实现为 Node.js 应用程序。容器是从 Azure 容器注册表中拉取的。

这个在容器中运行的 Node.js 应用程序需要访问 Microsoft Graph(作为应用程序,没有用户上下文)。基本上就像这里所示:

https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-nodejs-console

但有以下区别:

  • 我们想使用证书进行身份验证(无客户端机密)
  • 证书来自 Azure Key Vault,直接或通过 Function App 的 TLS 设置(也可以从 Key Vault 中提取)
  • 我们需要从内部容器

(为什么选择 Azure Key Vault?因为我们想使用它的自动续订等功能。)

我们将如何实现这一点?容器部分似乎让事情变得复杂。

1 个答案:

答案 0 :(得分:1)

你可以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();

然后使用 adal 获取 Microsoft Graph 的访问令牌,不要忘记将 resource 更改为 https://graph.microsoft.com,并将值更改为您的值。

'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);
  }
});