身份验证问题 - 从 Azure 函数调用的 Azure REST API
Authentication issue - Azure REST API called from azure functions
我正在使用 azure 函数来调用 Azure SQL 数据仓库的其余 API 以在一天中的特定时间暂停和恢复服务器(2 个函数)。在我之前创建的 azure 函数中,我不必调用 REST API,因为我只使用了可用的输出选项。而 SQL DW 只有 REST API 选项。
我使用 nodejs 创建了一个函数应用程序,并从那里调用这些 REST APIs。我浏览了 azure REST API documentation 并尝试了那里解释的过程。
首先,我将函数应用程序作为租户添加到 azure 活动目录中,并获取了租户 ID(它是端点 url 的一部分)和应用程序 ID/客户端 ID,然后尝试调用登录名 URL,如此处所述https://docs.microsoft.com/en-us/azure/active-directory/active-directory-protocols-oauth-code#request-an-authorization-code
通过传递所需的 parameters.Though 它被称为 GET 我尝试了 GET 和 POST 但它们没有用。
module.exports = function(context) {
var unirest = require('unirest');
var subscriptionId='subscriptionId';
context.log("starting the function");
unirest.post('https://login.windows.net/tenantID/oauth2/authorize')
.headers({'Accept': 'application/json', 'Content-Type': 'application/json'})
.send({ "client_id": "clientID ", "response_type": "code","grant_type":"authorization_code" })
.end(function (response) {
context.log(response.body);
});
});
此代码片段仅用于获取授权代码,然后将有另一种方法获取令牌,然后调用实际的 SQL DW pause/resume 方法。
当我从 VS2015 运行 相同时(删除模块导出并将上下文更改为控制台)我得到与下面相同的错误
<html><head><title>Continue</title></head><body><form method="POST" name="hiddenform" action="https://login.microsoftonline.com/9b8d9cda-ddb4-43bb-8725-bc0e9af83b43/oauth2/authorize"><noscript><p>Script is disabled. Click Submit to continue</p><input type="submit" value="Submit" /></noscript></form><script language="javascript">window.setTimeout('document.forms[0].submit()', 0);</script></body></html>
我不确定我在这里遗漏了什么。如果有人以前做过,请分享您的意见/解决方案。
更新:添加 Azure AD - 注册权限页面作为对其中一条评论的回复。让我知道这个是否符合要求。
我发现了与权限有关的问题。我必须向 AAD 中的应用程序提供 SQL 数据库服务器管理器 RBAC 角色。
Resume commandlet 运行良好,但 Suspend commandlet 不起作用。发生以下异常。
Suspend-AzureRmSqlDatabase : 40640: The server encountered an unexpected exception.
At line:9 char:35
+ $resultDatabase = $database | Suspend-AzureRmSqlDatabase;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Suspend-AzureRmSqlDatabase], CloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Sql.DatabaseActivation.Cmdlet.SuspendAzureSqlDatabase
您愿意在函数中使用 PowerShell 来获得相同的结果吗? Azure SQL 数据仓库 (DW) 具有 PowerShell 命令,可让您暂停和恢复 Azure SQL DW。与制作 HTTP 请求和处理 HTTP 响应相比,使用 PowerShell 似乎更容易。
以下是有关如何创建 HTTP 触发的 PowerShell 函数以 暂停 和 恢复 Azure SQL DW 的步骤.您可以使用相同的 run.ps1
文件重新创建一个定时器触发的 PowerShell 函数。
设置服务主体以获取用户名、密码和租户ID。这是一项一次性任务,我觉得在函数中利用 运行 Azure PowerShell 是值得的。网上有很多文档,但这里有一些关于如何设置服务主体的文档链接:
我。 http://blog.davidebbo.com/2014/12/azure-service-principal.html(我用的就是这个)
登录 Functions 门户以访问您的 Functions 应用程序。
点击Function app settings->Configure app settings并为设置SP_USERNAME
、[=12=添加键值对],和 TENANTID
(您可以使用其他所需的键名)。
创建一个 HTTP 触发的 PowerShell 函数,命名为,例如SuspendSqlDataWarehouse 在其 run.ps1
文件中包含以下内容。
$requestBody = Get-Content $req -Raw | ConvertFrom-Json
# Set Service Principal credentials
# SP_PASSWORD, SP_USERNAME, TENANTID are app settings
$secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force;
$mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd)
Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds;
$context = Get-AzureRmContext;
Set-AzureRmContext -Context $context;
# Suspend SQL Data Warehouse
$database = Get-AzureRmSqlDatabase –ResourceGroupName $requestBody.resourcegroup –ServerName $requestBody.server –DatabaseName $requestBody.databasename
if($database.Status -ne "Paused") # IF-condition added on 2/3/2017
{
$resultDatabase = $database | Suspend-AzureRmSqlDatabase;
$resultDatabase | Out-String;
}
单击 保存 按钮。
接下来,点击日志按钮打开日志查看器。
点击测试按钮打开简单的HTTP客户端。在请求正文中,为 SQL DW 提供资源组、服务器和数据库名称值,例如
{
"resourcegroup": "testresourcegroup",
"server": "testserver",
"databasename" : "testsqldw"
}
- 单击 运行 按钮并等待几秒钟。
Get-AzureRmSqlDatabase
和 Suspend-AzureRmSqlDatabase
cmdlet 需要一些时间(~3-4 分钟)才能完成 运行。当出现时,您应该会在日志查看器中看到类似的条目。
2016-12-09T18:02:07.990 Function started (Id=3c270254-f935-4a32-8b27-13131b6257d4)
2016-12-09T18:02:09.224 Microsoft.Azure.Commands.Profile.Models.PSAzureContext
2016-12-09T18:02:09.224 Microsoft.Azure.Commands.Profile.Models.PSAzureContext
2016-12-09T18:03:25 No new trace in the past 1 min(s).
2016-12-09T18:04:25 No new trace in the past 2 min(s).
2016-12-09T18:05:11.787 ResourceGroupName : testresourcegroup
ServerName : testserver
DatabaseName : testsqldw
Location : West US
DatabaseId : [some guid]
Edition : DataWarehouse
CollationName : SQL_Latin1_General_CP1_CI_AS
CatalogCollation :
MaxSizeBytes : 10995116277760
Status : Paused
CreationDate : 12/9/2016 5:14:35 PM
CurrentServiceObjectiveId : [some guid]
CurrentServiceObjectiveName : DW400
RequestedServiceObjectiveId : [some guid]
RequestedServiceObjectiveName :
ElasticPoolName :
EarliestRestoreDate : 1/1/0001 12:00:00 AM
Tags :
ResourceId : /subscriptions/[some guid]
/resourceGroups/testresourcegroup/providers
/Microsoft.Sql/servers/testserver/databases/tests
qldw
CreateMode :
2016-12-09T18:05:11.787 Function completed (Success, Id=3c270254-f935-4a32-8b27-13131b6257d4)
- 重复步骤 4-8 以在其
run.ps1
文件中创建具有以下内容的 ResumeSqlDataWarehouse 函数。
$requestBody = Get-Content $req -Raw | ConvertFrom-Json
# Set Service Principal credentials
# SP_PASSWORD, SP_USERNAME, TENANTID are app settings
$secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force;
$mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd)
Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds;
$context = Get-AzureRmContext;
Set-AzureRmContext -Context $context;
# Resume SQL Data Warehouse
$database = Get-AzureRmSqlDatabase –ResourceGroupName $requestBody.resourcegroup –ServerName $requestBody.server –DatabaseName $requestBody.databasename
$resultDatabase = $database | Resume-AzureRmSqlDatabase;
$resultDatabase | Out-String;
日志条目将类似于以下内容:
2016-12-09T18:17:34.625 Function started (Id=55f6d69e-a32e-4153-89c8-e821c4429421)
2016-12-09T18:17:36.504 Microsoft.Azure.Commands.Profile.Models.PSAzureContext
2016-12-09T18:17:36.504 Microsoft.Azure.Commands.Profile.Models.PSAzureContext
2016-12-09T18:18:07.836 ResourceGroupName : testresourcegroup
ServerName : testserver
DatabaseName : testsqldw
Location : West US
DatabaseId : [some guid]
Edition : DataWarehouse
CollationName : SQL_Latin1_General_CP1_CI_AS
CatalogCollation :
MaxSizeBytes : 10995116277760
Status : Online
CreationDate : 12/9/2016 5:14:35 PM
CurrentServiceObjectiveId : [some guid]
CurrentServiceObjectiveName : DW400
RequestedServiceObjectiveId : [some guid]
RequestedServiceObjectiveName :
ElasticPoolName :
EarliestRestoreDate : 1/1/0001 12:00:00 AM
Tags :
ResourceId : /subscriptions/[some guid]
/resourceGroups/testresourcegroup/providers/
Microsoft.Sql/servers/testserver/databases/tests
qldw
CreateMode :
2016-12-09T18:18:07.836 Function completed (Success, Id=55f6d69e-a32e-4153-89c8-e821c4429421)
注意: 我注意到暂停 SQL 数据仓库需要几分钟时间。在当前版本的 Azure Functions 中,所有函数的最长执行时间均为 5 分钟。如果您的函数在 5 分钟之前执行 Pause/Resume 命令是没有问题的,因为任务本身将被启动。您可以编写另一个函数来轮询 SQL 数据仓库的状态,直到获得预期的 Paused/Online
值。
我正在使用 azure 函数来调用 Azure SQL 数据仓库的其余 API 以在一天中的特定时间暂停和恢复服务器(2 个函数)。在我之前创建的 azure 函数中,我不必调用 REST API,因为我只使用了可用的输出选项。而 SQL DW 只有 REST API 选项。
我使用 nodejs 创建了一个函数应用程序,并从那里调用这些 REST APIs。我浏览了 azure REST API documentation 并尝试了那里解释的过程。 首先,我将函数应用程序作为租户添加到 azure 活动目录中,并获取了租户 ID(它是端点 url 的一部分)和应用程序 ID/客户端 ID,然后尝试调用登录名 URL,如此处所述https://docs.microsoft.com/en-us/azure/active-directory/active-directory-protocols-oauth-code#request-an-authorization-code 通过传递所需的 parameters.Though 它被称为 GET 我尝试了 GET 和 POST 但它们没有用。
module.exports = function(context) {
var unirest = require('unirest');
var subscriptionId='subscriptionId';
context.log("starting the function");
unirest.post('https://login.windows.net/tenantID/oauth2/authorize')
.headers({'Accept': 'application/json', 'Content-Type': 'application/json'})
.send({ "client_id": "clientID ", "response_type": "code","grant_type":"authorization_code" })
.end(function (response) {
context.log(response.body);
});
});
此代码片段仅用于获取授权代码,然后将有另一种方法获取令牌,然后调用实际的 SQL DW pause/resume 方法。 当我从 VS2015 运行 相同时(删除模块导出并将上下文更改为控制台)我得到与下面相同的错误
<html><head><title>Continue</title></head><body><form method="POST" name="hiddenform" action="https://login.microsoftonline.com/9b8d9cda-ddb4-43bb-8725-bc0e9af83b43/oauth2/authorize"><noscript><p>Script is disabled. Click Submit to continue</p><input type="submit" value="Submit" /></noscript></form><script language="javascript">window.setTimeout('document.forms[0].submit()', 0);</script></body></html>
我不确定我在这里遗漏了什么。如果有人以前做过,请分享您的意见/解决方案。
更新:添加 Azure AD - 注册权限页面作为对其中一条评论的回复。让我知道这个是否符合要求。
我发现了与权限有关的问题。我必须向 AAD 中的应用程序提供 SQL 数据库服务器管理器 RBAC 角色。 Resume commandlet 运行良好,但 Suspend commandlet 不起作用。发生以下异常。
Suspend-AzureRmSqlDatabase : 40640: The server encountered an unexpected exception. At line:9 char:35 + $resultDatabase = $database | Suspend-AzureRmSqlDatabase; + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Suspend-AzureRmSqlDatabase], CloudException + FullyQualifiedErrorId : Microsoft.Azure.Commands.Sql.DatabaseActivation.Cmdlet.SuspendAzureSqlDatabase
您愿意在函数中使用 PowerShell 来获得相同的结果吗? Azure SQL 数据仓库 (DW) 具有 PowerShell 命令,可让您暂停和恢复 Azure SQL DW。与制作 HTTP 请求和处理 HTTP 响应相比,使用 PowerShell 似乎更容易。
以下是有关如何创建 HTTP 触发的 PowerShell 函数以 暂停 和 恢复 Azure SQL DW 的步骤.您可以使用相同的 run.ps1
文件重新创建一个定时器触发的 PowerShell 函数。
设置服务主体以获取用户名、密码和租户ID。这是一项一次性任务,我觉得在函数中利用 运行 Azure PowerShell 是值得的。网上有很多文档,但这里有一些关于如何设置服务主体的文档链接:
我。 http://blog.davidebbo.com/2014/12/azure-service-principal.html(我用的就是这个)
登录 Functions 门户以访问您的 Functions 应用程序。
点击Function app settings->Configure app settings并为设置
SP_USERNAME
、[=12=添加键值对],和TENANTID
(您可以使用其他所需的键名)。创建一个 HTTP 触发的 PowerShell 函数,命名为,例如SuspendSqlDataWarehouse 在其
run.ps1
文件中包含以下内容。
$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Suspend SQL Data Warehouse $database = Get-AzureRmSqlDatabase –ResourceGroupName $requestBody.resourcegroup –ServerName $requestBody.server –DatabaseName $requestBody.databasename if($database.Status -ne "Paused") # IF-condition added on 2/3/2017 { $resultDatabase = $database | Suspend-AzureRmSqlDatabase; $resultDatabase | Out-String; }
单击 保存 按钮。
接下来,点击日志按钮打开日志查看器。
点击测试按钮打开简单的HTTP客户端。在请求正文中,为 SQL DW 提供资源组、服务器和数据库名称值,例如
{ "resourcegroup": "testresourcegroup", "server": "testserver", "databasename" : "testsqldw" }
- 单击 运行 按钮并等待几秒钟。
Get-AzureRmSqlDatabase
和Suspend-AzureRmSqlDatabase
cmdlet 需要一些时间(~3-4 分钟)才能完成 运行。当出现时,您应该会在日志查看器中看到类似的条目。
2016-12-09T18:02:07.990 Function started (Id=3c270254-f935-4a32-8b27-13131b6257d4) 2016-12-09T18:02:09.224 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-12-09T18:02:09.224 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-12-09T18:03:25 No new trace in the past 1 min(s). 2016-12-09T18:04:25 No new trace in the past 2 min(s). 2016-12-09T18:05:11.787 ResourceGroupName : testresourcegroup ServerName : testserver DatabaseName : testsqldw Location : West US DatabaseId : [some guid] Edition : DataWarehouse CollationName : SQL_Latin1_General_CP1_CI_AS CatalogCollation : MaxSizeBytes : 10995116277760 Status : Paused CreationDate : 12/9/2016 5:14:35 PM CurrentServiceObjectiveId : [some guid] CurrentServiceObjectiveName : DW400 RequestedServiceObjectiveId : [some guid] RequestedServiceObjectiveName : ElasticPoolName : EarliestRestoreDate : 1/1/0001 12:00:00 AM Tags : ResourceId : /subscriptions/[some guid] /resourceGroups/testresourcegroup/providers /Microsoft.Sql/servers/testserver/databases/tests qldw CreateMode : 2016-12-09T18:05:11.787 Function completed (Success, Id=3c270254-f935-4a32-8b27-13131b6257d4)
- 重复步骤 4-8 以在其
run.ps1
文件中创建具有以下内容的 ResumeSqlDataWarehouse 函数。
$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Resume SQL Data Warehouse $database = Get-AzureRmSqlDatabase –ResourceGroupName $requestBody.resourcegroup –ServerName $requestBody.server –DatabaseName $requestBody.databasename $resultDatabase = $database | Resume-AzureRmSqlDatabase; $resultDatabase | Out-String;
日志条目将类似于以下内容:
2016-12-09T18:17:34.625 Function started (Id=55f6d69e-a32e-4153-89c8-e821c4429421) 2016-12-09T18:17:36.504 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-12-09T18:17:36.504 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-12-09T18:18:07.836 ResourceGroupName : testresourcegroup ServerName : testserver DatabaseName : testsqldw Location : West US DatabaseId : [some guid] Edition : DataWarehouse CollationName : SQL_Latin1_General_CP1_CI_AS CatalogCollation : MaxSizeBytes : 10995116277760 Status : Online CreationDate : 12/9/2016 5:14:35 PM CurrentServiceObjectiveId : [some guid] CurrentServiceObjectiveName : DW400 RequestedServiceObjectiveId : [some guid] RequestedServiceObjectiveName : ElasticPoolName : EarliestRestoreDate : 1/1/0001 12:00:00 AM Tags : ResourceId : /subscriptions/[some guid] /resourceGroups/testresourcegroup/providers/ Microsoft.Sql/servers/testserver/databases/tests qldw CreateMode : 2016-12-09T18:18:07.836 Function completed (Success, Id=55f6d69e-a32e-4153-89c8-e821c4429421)
注意: 我注意到暂停 SQL 数据仓库需要几分钟时间。在当前版本的 Azure Functions 中,所有函数的最长执行时间均为 5 分钟。如果您的函数在 5 分钟之前执行 Pause/Resume 命令是没有问题的,因为任务本身将被启动。您可以编写另一个函数来轮询 SQL 数据仓库的状态,直到获得预期的 Paused/Online
值。