0

如果在我们的 Azure 容器注册表中发生了新操作,我会努力将通知推送到我们的团队频道。

  1. Webhook 在另一个事件处理程序上工作
  2. 如果我将其推送到 MS Teams,我会收到回复:文本丢失

问题是:

如何在 Webhook 的有效负载中添加更多信息?我找不到任何文档

4

1 回答 1

2

@Matthias,谢谢您的提问。

如架构图所示,两个服务之间使用 Azure Functions 应用程序来转换从 ACR Webhook 接收到的负载。它也是自定义函数,它将调用 Microsoft Teams 来创建自定义消息。

在此处输入图像描述

在 Microsoft Teams 中配置传入 Webhook

要将消息发送到 Microsoft Teams,需要传入 Webhook。要创建和配置新的传入 Webhook,请导航到所需的团队并从选项菜单中选择连接器。

在此处输入图像描述

查找传入的 Webhook,然后添加它。添加后,必须配置传入 Webhook。使用官方 ACR 徽标进行演示,并将名称设置为“Azure Container Registry”。

在此处输入图像描述

将 Webhook URL 添加到 Azure Functions 应用

在 Microsoft Teams 中配置传入 Webhook 连接器后,您必须将 Webhook URL 存储在 Azure Functions 应用程序中。同样,使用 Azure CLI 完成此操作:

# Variables
FUNCTION_APP_NAME=fnapp-acr-teams
RESOURCE_GROUP_NAME=rg-acr-teams
WEBHOOK_URL=<your webhook url provided by Microsoft Teams>

# Set appSettings on Azure Functions App
az functionapp config appsettings set \
  -n $FUNCTION_APP_NAME \
  -g $RESOURCE_GROUP_NAME \
  --settings "ContainerRegistryTeams__TeamsWebhookUrl=$WEBHOOK_URL"
实施 Azure 函数

当涉及到 Azure Functions 时,我们使用了Azure Functions Core Tools ( ) 来完成所有工作。func如果您更关注 UI 方面,请使用首选 IDE 或编辑器创建新的 Azure Functions 项目。

# Create a project dir
mkdir -p ~/projects/acr-teams-integration
cd ~/projects/acr-teams-integration

# Create an Azure Functions project
func init --worker-runtime dotnet

# Create a new function
func new -l csharp --template "Http Trigger" \
  -n FnNotifyTeams -a function

若要在 Azure Functions 项目中使用 .NET 的依赖项注入 (DI) 和配置功能,必须安装以下 NuGet 包:

dotnet add package Microsoft.NET.Sdk.Functions
dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.Extensions.DependencyInjection
添加自定义 FunctionsStartup 类

如果您想IOptions<T>使用强类型 C# 类访问配置数据,请考虑添加FunctionsStartup如下所示的自定义实现:

[assembly: FunctionsStartup(typeof(Thns.Functions.Startup))]
namespace Thns.Functions
{
    public class Startup: FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddOptions<TeamsConfig>()
              .Configure<IConfiguration>((settings, configuration) =>
              {
                  configuration.GetSection("ContainerRegistryTeams")
                    .Bind(settings);
              });
        }
    }
}

我们函数的配置非常简单。这只是 webhook URL。也就是说,这个TeamsConfig类很简单:

public class TeamsConfig
{
    public string TeamsWebhookUrl { get; set; }
}

您现在可以使用常规 DI 模式在请求期间获取配置数据:

public class FnNotifyTeams
{
    public FnNotifyTeams(IOptions<TeamsConfig> options)
    {
        Config = options.Value; 
    }

    protected TeamsConfig Config { get; }
    
    // omitted
}
FnNotifyTeams 函数

现在让我们基于HTTPTrigger实现我们的 Azure 函数。该功能负责:

  • 验证来自 ACR 的传入请求

  • 构建 Microsoft Teams 消息的有效负载

  • 调用 Microsoft Teams webhook

     [FunctionName("FnNotifyTeams")]
     public async Task<IActionResult> Run(
         [HttpTrigger(AuthorizationLevel.Function, "POST", Route = "images")] HttpRequest req, ILogger log) 
     {
          string body = await new StreamReader(req.Body).ReadToEndAsync();
          dynamic d = JsonConvert.DeserializeObject(body);
          string action = d?.action;
    
         if (action != "push" && action != "chart_push")
         {
             log.LogWarning($"Action {action} is not supported.");
             return new BadRequestResult();
         }
         var metadata = ImageMetadata.FromPayload(d);
         if(metadata == null)
         {
             log.LogWarning($"Received invalid request. Got {body}");
             return new BadRequestResult();
         }
         var message = new {
             Title = $"New Container Image published in ACR",
             Text = $"`{metadata.Repository}:{metadata.Tag}` has been published at `{metadata.Registry}`. You can pull it now using: {Environment.NewLine}`docker pull {metadata.Registry}/{metadata.Repository}:{metadata.Tag}{Environment.NewLine}`"
         };
         var h = new HttpClient();
         var content = new StringContent(JsonConvert.SerializeObject(message), Encoding.UTF8, "application/json");
    
         var r = await h.PostAsync(Config.TeamsWebhookUrl, content);
         if (r.IsSuccessStatusCode){
             return new OkResult();
         }
         log.LogError($"Teams response -> {r.StatusCode}: {r.ReasonPhrase}");
         return new StatusCodeResult(500);            
     }
    

前面的代码获取从 ACR 接收的原始有效负载,提取并验证基本元数据。假设所有必要的信息都可用,并且 ACR 由于 a pushorchart_push动作而发出调用。在这种情况下,调用 Microsoft Teams 的请求负载将使用该HttpClient::PostAsync方法构造和发送。

主要将入站消息验证封装到ImageMetadata类中,如下所示:

public class ImageMetadata
{
    public string Registry { get; private set; }
    public string Repository { get; private set; }
    public string Tag { get; private set; }

    public static ImageMetadata FromPayload(dynamic d)
    {
        string repository = d?.target?.repository;
        string tag = d?.target?.tag;
        string registry = d?.request?.host;
        if (string.IsNullOrWhiteSpace(repository) ||
            string.IsNullOrWhiteSpace(tag) ||
            string.IsNullOrWhiteSpace(registry))
        {
            return null;
        }
        return new ImageMetadata
        {
            Registry = registry,
            Repository = repository,
            Tag = tag,
        };
    }
}

立即将其发布到云端:

# Variables
FUNCTION_APP_NAME=fnapp-acr-teams

# go to the functions directory
cd projects/acr-teams-integration

# deploy the current code to Azure Functions app
func azure functionapp publish $FUNCTION_APP_NAME -b local
使用身份验证密钥获取 Azure 函数 URL

现在代码已部署到 Azure Functions 应用程序,您必须获取函数的 URL,包括用于身份验证的函数密钥。同样,您可以使用 func CLI 从命令行直接执行此操作:

# Variables
FUNCTION_APP_NAME=fnapp-acr-teams

# Grab function url with function key
func azure functionapp list-functions $FUNCTION_APP_NAME --show-keys

从输出中复制调用 URL。

将 Webhook 添加到 ACR

最后但同样重要的是,我们必须在 ACR 中创建一个新的传出 webhook。此时,我们对通过 webhookpush和从 ACR 公开的两个事件感兴趣chart_push

# Variables
FUNCTION_URL=<paste function app url including function-key>
ACR_NAME=acrteams2021

# create a webhook in ACR
az acr webhook create -n webhook-notify-teams \
    -r $ACR_NAME \
    --uri $FUNCTION_URL \
    --actions push chart_push
测试 Azure Container Registry 和 Microsoft Teams 的集成

您可以使用任何 Docker 映像或符合 OCI 的工件来测试集成。我们将在此处使用 alpine Linux 容器映像作为示例:

# Variables
ACR_NAME=acrteams2021

docker pull alpine:latest
docker tag alpine:latest $ACR_NAME.azurecr.io/alpine:0.0.1

# Login to ACR
az acr login -n $ACR_NAME

# Push the container image to ACR
docker push $ACR_NAME.azurecr.io/alpine:0.0.1

几秒钟后,您应该会在 Microsoft Teams 中看到一条消息。

在此处输入图像描述

参考:https ://www.thorsten-hans.com/send-microsoft-teams-message-oci-artifacts-azure-container-registry/

于 2021-08-30T08:51:20.297 回答