【问题标题】:Authentication issue - Azure REST API called from azure functions身份验证问题 - 从 azure 函数调用的 Azure REST API
【发布时间】:2017-02-04 15:04:52
【问题描述】:

我正在开发 azure 函数来调用 Azure SQL 数据仓库的其余 API 以在一天中的特定时间暂停和恢复服务器(2 个函数)。在我之前创建的 azure 函数中,我不必调用 REST API,因为我只使用了可用的输出选项。而 SQL DW 只有 REST API 选项。

我使用 nodejs 创建了一个函数应用程序,并从那里调用这些 REST API。我浏览了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 通过传递所需的参数。虽然它被提到为 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 暂停/恢复方法。 当我从 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>

我不确定我在这里缺少什么。如果有人以前做过,请分享您的 cmets/ 解决方案。

更新:添加 Azure AD - 注册权限页面作为对其中一个 cmets 的回复。让我知道这是否符合要求。

我发现了与权限有关的问题。我必须向 AAD 中的应用程序提供 SQL 数据库服务器管理器 RBAC 角色。 Resume commandlet 工作正常,但 Suspend commandlet 不起作用。发生以下异常。

Suspend-AzureRmSqlDatabase:40640:服务器遇到意外异常。 在行:9 字符:35 + $结果数据库 = $数据库 |挂起-AzureRmSqlDatabase; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Suspend-AzureRmSqlDatabase], CloudException + FullyQualifiedErrorId : Microsoft.Azure.Commands.Sql.DatabaseActivation.Cmdlet.SuspendAzureSqlDatabase

【问题讨论】:

  • 如果帖子不是发给login.microsoftonline.com 而不是 login.windows.net 以获得第一个 access_token。我在文档中看到 login.windows.net 仅在您拥有访问身份验证资源的令牌时才建议使用
  • 是的..我的错..感谢您发现这一点。让我换一下试试看。

标签: node.js rest active-directory azure-functions azure-sqldw


【解决方案1】:

您愿意在 Functions 中使用 PowerShell 来获得相同的结果吗? Azure SQL 数据仓库 (DW) 具有 PowerShell 命令,可让您暂停和恢复 Azure SQL DW。与制作 HTTP 请求和处理 HTTP 响应相比,使用 PowerShell 似乎更容易。

以下是有关如何创建 HTTP 触发的 PowerShell 函数以暂停恢复 Azure SQL DW 的步骤。您可以使用相同的 run.ps1 文件重新创建计时器触发的 PowerShell 函数。

  1. 设置服务主体以获取用户名、密码和租户 ID。这是一项一次性任务,我认为在 Functions 中运行 Azure PowerShell 是值得的。网上有很多文档,但这里有一些关于如何设置服务主体的文档链接:

    我。 http://blog.davidebbo.com/2014/12/azure-service-principal.html(我用过这个)

    二。 https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal

  2. 登录到 Functions 门户以访问您的 Function 应用程序。

  3. 点击功能应用设置->配置应用设置,为设置SP_USERNAMESP_PASSWORDTENANTID添加键值对(您可以使用其他所需的键名)。

  4. 创建一个 HTTP 触发的 PowerShell 函数,命名为,例如SuspendSqlDataWarehouse 在其run.ps1 文件中包含以下内容。

$requestBody = 获取内容 $req -Raw | ConvertFrom-Json # 设置服务主体凭据 # SP_PASSWORD、SP_USERNAME、TENANTID 是应用设置 $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = 新对象 System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) 添加-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = 获取 AzureRmContext; 设置-AzureRmContext -Context $context; # 暂停 SQL 数据仓库 $database = Get-AzureRmSqlDatabase –ResourceGroupName $requestBody.resourcegroup –ServerName $requestBody.server –DatabaseName $requestBody.databasename if($database.Status -ne "Paused") # 2017 年 2 月 3 日添加的 IF 条件 { $结果数据库 = $数据库 |挂起-AzureRmSqlDatabase; $结果数据库 |外串; }
  1. 点击保存按钮。

  2. 接下来,单击日志按钮打开日志查看器。

  3. 点击Test按钮打开简单的HTTP客户端。在请求正文中,提供 SQL DW 的资源组、服务器和数据库名称值,例如

{ “资源组”:“测试资源组”, “服务器”:“测试服务器”, “数据库名称”:“testsqldw” }
  1. 单击运行按钮并等待几秒钟。 Get-AzureRmSqlDatabaseSuspend-AzureRmSqlDatabase cmdlet 需要一些时间(约 3-4 分钟)才能运行完成。当它出现时,您应该会在日志查看器中看到类似的条目。
2016-12-09T18:02:07.990 功能已启动(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 在过去 1 分钟内没有新的跟踪。 2016-12-09T18:04:25 在过去 2 分钟内没有新的跟踪。 2016-12-09T18:05:11.787 资源组名称:测试资源组 服务器名称:测试服务器 数据库名称:testsqldw 地点:美国西部 DatabaseId : [一些指导] 版本:数据仓库 排序规则名称:SQL_Latin1_General_CP1_CI_AS 目录排序: 最大字节数:10995116277760 状态:暂停 创建日期:2016 年 12 月 9 日下午 5:14:35 CurrentServiceObjectiveId : [一些指导] 当前服务目标名称:DW400 RequestedServiceObjectiveId : [一些指导] 请求服务目标名称: 弹性池名称: 最早恢复日期:1/1/0001 12:00:00 AM 标签: ResourceId : /subscriptions/[一些 guid] /resourceGroups/testresourcegroup/providers /Microsoft.Sql/servers/testserver/databases/tests qldw 创建模式: 2016-12-09T18:05:11.787 功能完成(成功,Id=3c270254-f935-4a32-8b27-13131b6257d4)
  1. 重复步骤 4-8 以创建 ResumeSqlDataWarehouse 函数,在其 run.ps1 文件中包含以下内容。
$requestBody = 获取内容 $req -Raw | ConvertFrom-Json # 设置服务主体凭据 # SP_PASSWORD、SP_USERNAME、TENANTID 是应用设置 $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = 新对象 System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) 添加-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = 获取 AzureRmContext; 设置-AzureRmContext -Context $context; # 恢复 SQL 数据仓库 $database = Get-AzureRmSqlDatabase –ResourceGroupName $requestBody.resourcegroup –ServerName $requestBody.server –DatabaseName $requestBody.databasename $结果数据库 = $数据库 |简历-AzureRmSqlDatabase; $结果数据库 |外串;

日志条目将类似于以下内容:

2016-12-09T18:17:34.625 功能已启动(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 资源组名称:测试资源组 服务器名称:测试服务器 数据库名称:testsqldw 地点:美国西部 DatabaseId : [一些指导] 版本:数据仓库 排序规则名称:SQL_Latin1_General_CP1_CI_AS 目录排序: 最大字节数:10995116277760 状态:在线 创建日期:2016 年 12 月 9 日下午 5:14:35 CurrentServiceObjectiveId : [一些指导] 当前服务目标名称:DW400 RequestedServiceObjectiveId : [一些指导] 请求服务目标名称: 弹性池名称: 最早恢复日期:1/1/0001 12:00:00 AM 标签: ResourceId : /subscriptions/[一些 guid] /resourceGroups/testresourcegroup/providers/ Microsoft.Sql/servers/testserver/databases/tests qldw 创建模式: 2016-12-09T18:18:07.836 功能完成(成功,Id=55f6d69e-a32e-4153-89c8-e821c4429421)

注意:我注意到暂停 SQL 数据仓库需要几分钟时间。在当前版本的 Azure Functions 中,所有 Functions 的最长执行时间为 5 分钟。如果你的函数在 5 分钟之前执行 Pause/Resume 命令就可以了,因为任务本身将被启动。您可以编写另一个函数来轮询 SQL 数据仓库的状态,直到获得预期的 Paused/Online 值。

【讨论】:

  • 感谢分享 powershell 选项。我可以将其配置为时间触发器并将值放在脚本本身而不是这个 http 触发器中吗?
  • 是的,您可以将它们重新创建为计时器触发器。至于值,您可以将其硬编码到脚本本身中。否则,为了获得更好的安全模型,您还可以将其添加到应用程序设置中,就像示例对服务主体用户名、密码和租户 ID 所做的那样。
  • 在未获得使用 REST API 选项的授权后,我尝试了您共享的 powershell 选项。我收到以下错误。 Resume-AzureRmSqlDatabase : AuthorizationFailed: 对象 id 为 '2a4f65b9-1a93-4294-bd37-72a2df4a7843' 的客户端 '2a4f65b9-1a93-4294-bd37-72a2df4a7843' 没有执行操作的授权。我在任何地方都没有看到此客户端 ID .我在功能应用程序设置中提供了所有正确的客户端应用程序 ID。不确定。
  • @Aravind,您能否确保您的服务主体在订阅级别获得了全部权限?此外,从这个线程来看,似乎有些人说服务主体设置在通过 Portal UI 而不是通过 PowerShell 完成时有效。 github.com/Azure/azure-xplat-cli/issues/2051
  • 我添加了azure AD应用注册权限页面的截图。你能告诉我这里需要改变什么吗?或者它是否在其他地方......?
猜你喜欢
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-03
  • 2021-08-14
  • 1970-01-01
相关资源
最近更新 更多