NodeJS में सेवा प्रिंसिपल का उपयोग करके Azure SQL से कनेक्ट करना, लेकिन टोकन अस्वीकार कर दिया गया है

Aug 16 2020

मुझे सेवा प्रिंसिपल का उपयोग करके एक एज़्योर SQL डेटाबेस से कनेक्ट करने के लिए मेरे नोड्स एप्लिकेशन को प्राप्त करने में परेशानी हो रही है। हालांकि, जब मैं सी # स्निपेट के साथ एक ही काम करने की कोशिश करता हूं, तो यह ठीक काम करता है। मैंने जो देखा है, वह यह है कि दोनों भाषाओं के आधार पर टोकन लौटाया जाना थोड़ा अलग है, और अगर मैं C # से सही टोकन लेता हूं और हार्ड कोड को NodeJS में ले लेता हूं, तो मेरा SQL कनेक्शन अब सफल हो जाता है।

मैं अपना प्रमाणीकरण करने के लिए, और अपने मुवक्किल आईडेंट, टेनेंटआईड और क्लायंटसेक्रेट प्रदान करने के लिए सबसे पहले एमएस-बाकी-एज़्योर का उपयोग कर रहा हूं। यह एक वैध क्रेडेंशियल वापस करता है, जिसमें से मैं एक्सेसटोकन निकाल रहा हूं।

फिर, मैं * .database.windows.net पर Azure SQL से कनेक्ट करने और कॉन्फ़िगरेशन में एक्सेसटोकन मान प्रदान करने की कोशिश करने के लिए थकाऊ का उपयोग कर रहा हूं।

मैं उपयोगकर्ता के लिए लॉगिन विफल हो गया '<टोकन-पहचाने गए प्रिंसिपल>'

एमएस-रेस्ट-अज़ुरे लॉगिन में मैं गलत क्या कर रहा हूँ मुझे अज़ुरे एसक्यूएल द्वारा अस्वीकार कर दिया गया टोकन देने के लिए? एक बात मैंने देखी है कि काम करने वाले टोकन में डेटाबेस का एक श्रोता होता है। Windows.net , जहाँ एमएस-रेस्ट-अज़ुरे से प्रबंधन- core.windows.net है ।

मैं कुछ दिनों के लिए अटक गया हूं, अगर किसी के यहाँ कोई सुराग है जो भयानक होगा। Ms-rest-azure पर प्रलेखन काफी गैर-मौजूद है और बस आपको Azure बिक्री पृष्ठों पर अपवाह देता है।

const msRestAzure = require('ms-rest-azure');
const { reject } = require('async');


let clientSecret = "xxx";
let serverName = "xxx.database.windows.net";
let databaseName = "xxx";
let clientId = "xxx";
let tenantId = "xxx";

azureCredentials = msRestAzure.loginWithServicePrincipalSecret(clientId, clientSecret, tenantId, function(err, credentials) {
    if (err) return console.log(err);
    credentials.getToken((err, results) => {
        if(err) return reject(err);
        
        let accessToken = results.accessToken;

        var Connection = require('tedious').Connection;
        var Request = require('tedious').Request;

        var config = {
            server: serverName,
            authentication: {
                type: 'azure-active-directory-access-token',
                options: {
                    token: accessToken
                }
            }
            ,options: {
                debug: {
                packet: true,
                data: true,
                payload: true,
                token: false,
                log: true
                },
                database: databaseName,
                encrypt: true
            }  
        };

        var connection = new Connection(config);

        connection.connect();

        connection.on('connect', function(err) {
            if(err) {
                console.log(err);
            }
            executeStatement();
        }
        );

        connection.on('debug', function(text) {
            console.log(text);
        }
        );

        function executeStatement() {
        request = new Request("select * from Text", function(err, rowCount) {
            if (err) {
            console.log(err);
            } else {
            console.log(rowCount + ' rows');
            }

            connection.close();
        });

        request.on('row', function(columns) {
            columns.forEach(function(column) {
            if (column.value === null) {
                console.log('NULL');
            } else {
                console.log(column.value);
            }
            });
        });

        request.on('done', function(rowCount, more) {
            console.log(rowCount + ' rows returned');
        });

        connection.execSql(request);
        }
    });   
})

जवाब

2 JimXu Aug 18 2020 at 02:34

जब हम ms-rest-azureटोकन प्राप्त करने के लिए पैकेज में प्रमाण पत्र का उपयोग करते हैं , तो डिफ़ॉल्ट रूप से, टोकन के दर्शक हैं https://management.core.windows.net/, इसका उपयोग केवल एज़ुर बाकी आपी को कॉल करने के लिए किया जा सकता है। यदि हम sql को जोड़ने के लिए Azure AD टोकन का उपयोग करना चाहते हैं, तो टोकन के दर्शक होने चाहिए https://database.windows.net/। इसलिए हमें टोकन प्राप्त करने के लिए उपयोग किए गए कोड को अपडेट करना चाहिए

msrestAzure.loginWithServicePrincipalSecret(
    clientId,
    clientSecret,
    tenantId,
    {
      tokenAudience: "https://database.windows.net/",
    },

उदाहरण के लिए

  1. एक सेवा प्रमुख बनाएँ
az login
az ad sp create-for-rbac -n 'MyApp' --skip-assignment
  1. SQL डेटाबेस कॉन्फ़िगर करें

ए। Azure SQL vai SSMS को जोड़ने के लिए अपने Azure Sql AD व्यवस्थापक का उपयोग करें

बी सेवा प्रिंसिपल को उस डेटाबेस में जोड़ें जिसका आपको उपयोग करने की आवश्यकता है

create user [<Azure_AD_principal_name>] from external provider
ALTER ROLE db_owner ADD MEMBER [<Azure_AD_principal_name>]
     
  1. कोड
var msrestAzure = require("ms-rest-azure");
var { Connection, Request } = require("tedious");

let clientSecret = "xxx";
let serverName = "xxx.database.windows.net";
let databaseName = "xxx";
let clientId = "xxx";
let tenantId = "xxx";

async function getConnect() {
  // way for Azure Service Principal
  let databaseCredentials = await msrestAzure.loginWithServicePrincipalSecret(
    clientId,
    clientSecret,
    tenantId,
    {
      tokenAudience: "https://database.windows.net/",
    },
  );

  // getting access token
  let databaseAccessToken = await new Promise((resolve, reject) => {
    databaseCredentials.getToken((err, results) => {
      if (err) return reject(err);
      resolve(results.accessToken);
    });
  });
  var config = {
    server: serverName,
    authentication: {
      type: "azure-active-directory-access-token",
      options: {
        token: databaseAccessToken,
      },
    },
    options: {
      debug: {
        packet: true,
        data: true,
        payload: true,
        token: false,
        log: true,
      },
      database: databaseName,
      encrypt: true,
    },
  };

  var connection = new Connection(config);
  connection.connect();
  connection.on("connect", function (err) {
    if (err) {
      console.log(err);
    }
    executeStatement(connection);
  });

  connection.on("debug", function (text) {
    console.log(text);
  });
}
function executeStatement(connection) {
  request = new Request("select * from CSVTest", function (err, rowCount) {
    if (err) {
      console.log(err);
    } else {
      console.log(rowCount + " rows");
    }

    connection.close();
  });

  request.on("row", function (columns) {
    columns.forEach(function (column) {
      if (column.value === null) {
        console.log("NULL");
      } else {
        console.log(column.value);
      }
    });
  });

  request.on("done", function (rowCount, more) {
    console.log(rowCount + " rows returned");
  });

  connection.execSql(request);
}

getConnect()
  .then(() => {
    console.log("run successfully");
  })
  .catch((err) => {
    console.log(err);
  });

अधिक जानकारी के लिए, कृपया यहां देखें