如何使用 Pulumi 向 Web App 添加身份验证

Posted

技术标签:

【中文标题】如何使用 Pulumi 向 Web App 添加身份验证【英文标题】:How to add Authentiction to WebApp with Pulumi 【发布时间】:2022-01-19 18:13:14 【问题描述】:

我正在尝试向 Pulumi WebApp 添加身份验证提供程序,但我完全不清楚如何实现这一点。来自包@pulumi/azure-native/web 的类WebApp 仅提供属性identity,但没有分配属性,例如微软广告。任何人都可以提供有关如何设置的提示吗?

【问题讨论】:

【参考方案1】:

有一些Pulumi Azure pre-requisites 并且在你的租户和 Azure 订阅中具有适当的权限。

按照以下步骤使用 pulumi 将身份验证添加到应用服务 webapp 并部署:

创建项目

首先创建应用程序,然后添加创建 Azure AD application registration 所需的 AzureAD 包。

pulumi new azure-csharp `
  --name easyauth-webapp `
  --description "azure ad secured app" `
  --stack dev `
  --config azure-native:location=eastus

dotnet add package Pulumi.AzureAD

接下来我们需要更新pulumi.dev.yaml 文件的内容以包含一些额外的配置项。将以下内容粘贴到文件中:

config:
  azure-native:location: eastus
  azure-native:subscriptionId: UPDATE_ME
  azure-native:tenantId: UPDATE_ME
  easyauth-webapp:tenantId: UPDATE_ME
  easyauth-webapp:ownerId: UPDATE_ME
  easyauth-webapp:siteName: UPDATE_ME
  easyauth-webapp:appRegistrationName: UPDATE_ME

您可以将siteNameappRegistrationName 设置为您想要的任何值。

subscriptionIdtenantId 应分别设置为 Azure 应用服务和 Azure AD 应用注册的相应目标。

以下命令可能有助于检索这些值:

# Get your user's id
az ad signed-in-user show --query objectId

# List all subscriptions (and their tenant) that you have access to
az account list

部署网站(没有安全措施)

接下来我们将创建要部署的网站。我们将使用run from ZIP package 功能来部署wwwroot 文件夹的内容。 创建该文件夹并向index.htm 文件添加一些内容:

例如:

<!-- wwwroot/index.htm -->
<html>
  <head>
    <title>A very secure app</title>
  </head>
  <body>
    Hello EasyAuth with Pulumi!
  </body>
</html>

现在我们可以使用 Pulumi 将此文件部署到 Azure。 修改MyStack.cs文件以包含以下代码,该代码已改编自Pulumi Function Stack example:

// MyStack.cs
using System;
using Pulumi;
using Pulumi.AzureAD;
using Pulumi.AzureAD.Inputs;
using Pulumi.AzureNative.Resources;
using Pulumi.AzureNative.Storage;
using Pulumi.AzureNative.Storage.Inputs;
using Pulumi.AzureNative.Web;
using Pulumi.AzureNative.Web.Inputs;

class MyStack : Stack

  public MyStack()
  
    var config = new Pulumi.Config();
    var tenantId = config.Require("tenantId");
    var ownerId = config.Require("ownerId");
    var siteName = config.Require("siteName");
    var appRegistrationName = config.Require("appRegistrationName");

    var rg = new ResourceGroup($"RG-siteName");

    var storageAccount = new StorageAccount("storageaccount", new StorageAccountArgs
    
      ResourceGroupName = rg.Name,
      Kind = "StorageV2",
      Sku = new SkuArgs
      
        Name = SkuName.Standard_LRS,
      ,
    );

    var appServicePlan = new AppServicePlan("appserviceplan", new AppServicePlanArgs
    
      ResourceGroupName = rg.Name,
      Kind = "App",
      Sku = new SkuDescriptionArgs
      
        Tier = "Basic",
        Name = "B1",
      ,
    );

    var container = new BlobContainer("zips", new BlobContainerArgs
    
      AccountName = storageAccount.Name,
      PublicAccess = PublicAccess.None,
      ResourceGroupName = rg.Name,
    );

    var blob = new Blob("appservice-blob", new BlobArgs
    
      ResourceGroupName = rg.Name,
      AccountName = storageAccount.Name,
      ContainerName = container.Name,
      Type = BlobType.Block,
      Source = new FileArchive("wwwroot"),
    );

    var codeBlobUrl = SignedBlobReadUrl(blob, container, storageAccount, rg);

    var app = new WebApp("app", new WebAppArgs
    
      Name = siteName,
      ResourceGroupName = rg.Name,
      ServerFarmId = appServicePlan.Id,
      SiteConfig = new SiteConfigArgs
      
        AppSettings = 
          new NameValuePairArgs
              Name = "WEBSITE_RUN_FROM_PACKAGE",
              Value = codeBlobUrl,
          
        ,
      
    );

    this.Endpoint = app.DefaultHostName;
  

  // From https://github.com/pulumi/examples/blob/master/azure-cs-functions/FunctionsStack.cs
  private static Output<string> SignedBlobReadUrl(Blob blob, BlobContainer container, StorageAccount account, ResourceGroup resourceGroup)
  
    return Output.Tuple<string, string, string, string>(
        blob.Name, container.Name, account.Name, resourceGroup.Name).Apply(t =>
    
      (string blobName, string containerName, string accountName, string resourceGroupName) = t;

      var blobSAS = ListStorageAccountServiceSAS.InvokeAsync(new ListStorageAccountServiceSASArgs
      
        AccountName = accountName,
        Protocols = HttpProtocol.Https,
        SharedAccessStartTime = "2021-01-01",
        SharedAccessExpiryTime = "2030-01-01",
        Resource = SignedResource.C,
        ResourceGroupName = resourceGroupName,
        Permissions = Permissions.R,
        CanonicalizedResource = "/blob/" + accountName + "/" + containerName,
        ContentType = "application/json",
        CacheControl = "max-age=5",
        ContentDisposition = "inline",
        ContentEncoding = "deflate",
      );
      return Output.Format($"https://accountName.blob.core.windows.net/containerName/blobName?blobSAS.Result.ServiceSasToken");
    );
  

  [Output] public Output<string> Endpoint  get; set; 

我们现在可以部署站点并验证它是否按预期工作:

pulumi up --stack dev

curl (pulumi stack --stack dev output Endpoint)

[

保护网站

要配置 Easy Auth,我们首先创建一个 Azure AD 应用程序注册。 在此示例中,我指定了 AzureADMyOrg,它限制了对部署应用程序注册的租户的访问。我还添加了一个 RedirectUri,它指向已部署站点的 Easy Auth 中间件。需要密码才能用作客户端机密(在这种情况下,Web 应用程序是客户端)。

创建应用程序注册后,我们可以将WebAppAuthSettings 添加到我们的网站。该示例指定无匿名访问(使用RedirectToLoginPage),并使用ClientIdClientSecret(密码)将站点连接到应用程序注册。

将下面的代码粘贴到上面MyStack.cs中的this.Endpoint...代码之后:

// MyStack.cs
// After this.Endpoint = app.DefaultHostName;

var adApp = new Application("ADAppRegistration", new ApplicationArgs

  DisplayName = appRegistrationName,
  SignInAudience = "AzureADMyOrg",
  Owners = new[]  ownerId ,
  Web = new ApplicationWebArgs
  
    ImplicitGrant = new ApplicationWebImplicitGrantArgs
    
      IdTokenIssuanceEnabled = true
    ,
    RedirectUris = new System.Collections.Generic.List<string>  $"https://siteName.azurewebsites.net/.auth/login/aad/callback" 
  

);

var applicationPassword = new ApplicationPassword("appPassword", new ApplicationPasswordArgs

  ApplicationObjectId = adApp.Id,
  DisplayName = "Client secret for web app"
);

var allowedAudience = adApp.ApplicationId.Apply(id => $"api://id");

var authSettings = new WebAppAuthSettings("authSettings", new WebAppAuthSettingsArgs

  ResourceGroupName = rg.Name,
  Name = app.Name,
  Enabled = true,
  UnauthenticatedClientAction = UnauthenticatedClientAction.RedirectToLoginPage,
  DefaultProvider = BuiltInAuthenticationProvider.AzureActiveDirectory,
  ClientId = adApp.ApplicationId,
  ClientSecret = applicationPassword.Value,
  Issuer = $"https://sts.windows.net/tenantId/v2.0",
  AllowedAudiences = new[]  allowedAudience ,
);

我们现在可以更新站点了,从命令行我们无法比这更进一步。 但在浏览器中,我们将被重定向以完成登录流程并访问该站点。

pulumi up --stack dev

# Redirect to HTTPS
curl (pulumi stack --stack dev output Endpoint)

# Access denied
curl "https://$(pulumi stack --stack dev output Endpoint)"

请参阅此Github 链接以获取 pulumi 样本。

【讨论】:

以上是关于如何使用 Pulumi 向 Web App 添加身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Pulumi 如何在 Windows 环境中设置

使用 Pulumi 创建 EKS 后如何修改 `aws-auth` Config Map?

Pulumi 输出 - 创建一个外部配置文件

如何将 Pulumi Azure 资源迁移到 Azure-Nextgen?

java web app-为servlet上下文侦听器向web.xml添加内容后无法看到jsp文件

Pulumi Stack 命令不能找到默认的 Stack