如何将SSL添加到Azure容器示例应用程序?

yrwegjxp  于 2022-11-14  发布在  其他
关注(0)|答案(4)|浏览(332)

正如标题所说,我需要为Azure容器示例中托管的应用程序设置SSL,但是,我不太确定我需要从哪里开始。
我在地址http://myApp.northamerica.azurecontainer.io处通过Azure容器示例托管了一个容器化应用。此地址被“官方”地址http://api.myApp.com屏蔽。
为什么我不能只将SSL添加到表面域@http://api.myApp.com,而将其重定向到真实的域@http://myApp.northamerica.azurecontainer.io?或者我需要将SSL添加到这两个域吗?
此外,如果我需要使用SSL保护两个域,是否需要为每个域获取单独的证书?
Azure提供SSL证书服务,但我只需要知道最佳路径。谢谢。

k10s72fa

k10s72fa1#

在经历了围绕这个问题的痛苦研究之后,我们终于找到了如何使用Caddy Docker映像作为边车来向容器示例添加SSL。Caddy使自动续订和验证所有权以发布SSL变得容易。
我们写了一篇博客文章来帮助其他有同样问题的人。希望这能有所帮助。
https://www.antstack.io/blog/how-to-enable-tls-for-hasura-graphql-engine-in-azure-caddy/

sirbozc5

sirbozc52#

据我所知,目前,仍然没有内置的支持启用SSL的Azure容器示例参考this
但是,您可以有多种选择来为ACI应用程序启用SSL连接。

如果在Azure virtual network中部署容器组,则可以考虑使用其他选项为后端容器示例启用SSL端点,包括:

标准SSL证书Map到一个唯一的域名,因此每个域都需要单独的证书。
你可以开始在一个sidecar容器中设置Nginx作为SSL提供者,你需要一个api.myApp.com域的SSL证书。如果你想单独安全访问myApp.northamerica.azurecontainer.io域,你可以在Nginx配置文件中配置额外的服务器块。请参考configuring HTTPS server in Nginx

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}
vltsax25

vltsax253#

这里写了一段话:https://dev.to/kedzior_io/net-core-api-in-azure-container-instances-secured-with-https-using-caddy2-32jm
下面是复制/粘贴:
1.创建您的Web API项目,我们将其命名为MyApp.Image.Api,并假设它依赖于另一个项目MyApp.Core
1.将Dockerfile添加到MyApp.Image.Api项目

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
ARG ENVIRONMENT

ENV ASPNETCORE_URLS http://*:5000
ENV ENVIRONMENT_NAME "${ENVIRONMENT}"

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src

# copy project dependencies 
COPY ["src/MyApp.Core/MyApp.Core.csproj", "src/MyApp.Core/"]
COPY ["src/MyApp.Image.Api/MyApp.Image.Api.csproj", "src/MyApp.Image.Api/"]

RUN dotnet restore "src/MyApp.Image.Api/MyApp.Image.Api.csproj"
COPY . .

RUN dotnet build "src/MyApp.Image.Api/MyApp.Image.Api.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "src/MyApp.Image.Api/MyApp.Image.Api.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.Image.Api.dll"]

1.接下来,在同一个项目中创建名为Proxy的目录,您将需要4个文件:

  1. Caddyfile.development-使用自签名证书在本地运行时,将创建代理
{
    email artur@isready.io
}

https://localhost {
    reverse_proxy localhost:5000
}
  1. Caddyfile.staging
{
    email artur@isready.io
}

https://myapp-image-api-staging.eastus.azurecontainer.io {
    reverse_proxy localhost:5000
}
  1. Caddyfile.production
{
    email artur@isready.io
}

https://myapp-image-api.eastus.azurecontainer.io {
    reverse_proxy localhost:5000
}
  1. Dockerfile-我们将在执行此操作之前设置环境
FROM caddy:latest
ARG ENVIRONMENT

COPY "src/MyApp.Image.Api/Proxy/Caddyfile.${ENVIRONMENT}" /etc/caddy/Caddyfile
  • 如果您没有多个环境,您知道要跳过哪些:-)

1.现在需要将docker-compose.yml添加到项目中

version: '3.4'

services:

  proxy:
    image: myapp-image-api-proxy:${CONTAINER_VERSION}-${ENVIRONMENT}
    build:
      context: ../../
      args:
        ENVIRONMENT: ${ENVIRONMENT}
      dockerfile:  src/MyApp.Image.Api/Proxy/Dockerfile
  api:
    image:  myapp-image-api:${CONTAINER_VERSION}-${ENVIRONMENT}
    depends_on:
      - proxy
    build:
        context: ../../
        args:
          ENVIRONMENT: ${ENVIRONMENT}
        dockerfile: src/MyApp.Image.Api/Dockerfile

最后应该使用以下结构:

1.现在你可以开始了!我使用这个powershell脚本来构建我的映像。如果你是在本地构建的话,就运行这个脚本:

# set azure environment
$env:ENVIRONMENT = 'development'
$env:CONTAINER_VERSION = 'latest'

# builds images
docker-compose build

如果要构建映像并将其推送到Azure Container Registry,请在确保已创建注册表之前执行以下命令:

az provider register --namespace Microsoft.ContainerInstance`
az acr create --resource-group EastUS--name myapp --sku Basic // *enable admin user in azure portal once Azure Container Registry is created
# logs to azure
az login

# set azure environment
$env:ENVIRONMENT = 'staging'
$env:CONTAINER_VERSION = 'latest'

# builds images
docker-compose build

# logs to Azure Container Registry
az acr login --name myapp

# tag images
docker tag myapp-image-api-proxy:latest-staging myapp.azurecr.io/myapp-image-api-proxy:latest-staging
docker tag myapp-image-api:latest-staging myapp.azurecr.io/myapp-image-api:latest-staging

# push images
docker push myapp.azurecr.io/myapp-image-api-proxy:latest-staging
docker push myapp.azurecr.io/myapp-image-api:latest-staging

# clean up
docker rmi myapp-image-api-proxy:latest-staging
docker rmi myapp-image-api:latest-staging
docker rmi myapp.azurecr.io/myapp-image-api-proxy:latest-staging
docker rmi myapp.azurecr.io/myapp-image-api:latest-staging

酷!你已经准备好了!##

1.您将需要两个软件包:
一月十日一月一日一月一日
1.让我们从使用C# Fluent API连接到Azure开始

private IAzure GetAzureContext()
{
    Log.Information("[Container] Getting Service Principal");
    var creds = new AzureCredentialsFactory().FromServicePrincipal(
        _config["AppSettings:ImageApi:ServicePrincipalClientId"],
        _config["AppSettings:ImageApi:ServicePrincipalSecretId"],
        _config["AppSettings:ImageApi:ServicePrincipalTenat"],
        AzureEnvironment.AzureGlobalCloud);

    Log.Information("[Container] Getting subscribtion");
    var azure = Microsoft.Azure.Management.Fluent.Azure.Authenticate(creds).WithSubscription(_config["AppSettings:ImageApi:SubscribtionId"]);

    return azure;
}

从哪里获得这些服务主体ID?
在Azure CLI中执行以下操作:
az ad sp create-for-rbac --name myapp-containers --sdk-auth > my.azureauth
该文件将包含所需的所有服务主体数据。
1.现在主要部分:

private string CreateContainer()
{
    Log.Information("[Container] Authenticating with Azure");

    var azureContext = GetAzureContext();`
    
    // Get azure container registry for my resource group named 'EastUS' and registry 'myapp'
    var azureRegistry = azureContext.ContainerRegistries.GetByResourceGroup(
        _config["AppSettings:ImageApi:ResourceGroupName"],
        _config["AppSettings:ImageApi:ContainerRegistryName"]);

    var acrCredentials = azureRegistry.GetCredentials();

    // Get container group for my resource group named 'EastUS' and container group i.e 'myapp-image-api-staging'
    var containerGroup = azureContext.ContainerGroups.GetByResourceGroup(
        _config["AppSettings:ImageApi:ResourceGroupName"],
        _config["AppSettings:ImageApi:ContainerGroupName"]
        );

    if (containerGroup is null)
    {
        Log.Information("[Container] Creating with fluent API");

        // ContainerGroupName = 'myapp-image-api-staging'
        // ResourceGroupName = 'EastUS'
        // VolumeName = 'image-api-volume'
        // FileShare = 'containers' 
        //      # yes you need to have storage account with file share, we need it so that proxy (caddy2) can store Let's Encrypt certs in there
        //      az storage share create --name myapp-staging-containers-share --account-name myappstaging
        // 
        // StorageAccountName = 'myappstaging'
        // StorageAccountKey = 'well-that-key-here'
        // ProxyContainerName = 'image-api-proxy'
        // ProxyImageName = 'myapp.azurecr.io/myapp-image-api-proxy:latest-staging'
        // VolumeMountPath = '/data/'
        // ApiContainerName 'image-api'
        // ApiImageName 'myapp.azurecr.io/myapp-image-api:latest-staging'

        containerGroup = azureContext.ContainerGroups.Define(_config["AppSettings:ImageApi:ContainerGroupName"])
                .WithRegion(Region.USEast)
                .WithExistingResourceGroup(_config["AppSettings:ImageApi:ResourceGroupName"])
                .WithLinux()
                .WithPrivateImageRegistry(azureRegistry.LoginServerUrl, acrCredentials.Username, acrCredentials.AccessKeys[AccessKeyType.Primary])
                .DefineVolume(_config["AppSettings:ImageApi:VolumeName"])
                    .WithExistingReadWriteAzureFileShare(_config["AppSettings:ImageApi:FileShare"])
                    .WithStorageAccountName(_config["AppSettings:ImageApi:StorageAccountName"])
                    .WithStorageAccountKey(_config["AppSettings:ImageApi:StorageAccountKey"])
                    .Attach()
                .DefineContainerInstance(_config["AppSettings:ImageApi:ProxyContainerName"])
                    .WithImage(_config["AppSettings:ImageApi:ProxyImageName"])
                    .WithExternalTcpPort(443)
                    .WithExternalTcpPort(80)
                    .WithCpuCoreCount(1.0)
                    .WithMemorySizeInGB(0.5)
                    .WithVolumeMountSetting(
                        _config["AppSettings:ImageApi:VolumeName"],
                        _config["AppSettings:ImageApi:VolumeMountPath"])
                    .Attach()
                .DefineContainerInstance(_config["AppSettings:ImageApi:ApiContainerName"])
                    .WithImage(_config["AppSettings:ImageApi:ApiImageName"])
                    .WithExternalTcpPort(5000)
                    .WithCpuCoreCount(1.0)
                    .WithMemorySizeInGB(3.5)
                    .Attach()
                .WithDnsPrefix(_config["AppSettings:ImageApi:ContainerGroupName"])
                .WithRestartPolicy(ContainerGroupRestartPolicy.Always)
                .Create();
    }

    Log.Information("[Container] created {fqdn}", containerGroup.Fqdn);
    return containerGroup.Fqdn;
}

容器正在运行!

大约需要2:50分钟才能让它们完全可用。

点击上面代码中给出的fqdn,得到我的swagger索引页:

zy1mlcev

zy1mlcev4#

我在这篇文章中找到了答案:https://www.raeffs.dev/blog/2021/05-mai/25-autogenerate-ssl-certificates-for-aci/
我有一个可以通过other-service.francecentral.azurecontainer.io上的端口80访问的服务。
我添加了以下代理,它们响应URL caddy-example.francecentral.azurecontainer.io上的端口80和443。
下面是文件azure_container_caddy.yaml的内容:

# https://www.raeffs.dev/blog/2021/05-mai/25-autogenerate-ssl-certificates-for-aci/
name: acicaddynonprod
apiVersion: '2021-10-01'
location: francecentral
properties:
    containers:
        - name: caddy
          properties:
              image: docker.io/caddy:2
              command:
                [
                    'caddy',
                    'reverse-proxy',
                    '--from',
                    'caddy-example.francecentral.azurecontainer.io',
                    '--to',
                    'other-service.francecentral.azurecontainer.io',
                ]
              ports:
                  - port: 80
                    protocol: TCP
                  - port: 443
                    protocol: TCP
              resources:
                  requests:
                      cpu: 0.5
                      memoryInGB: 0.5
    ipAddress:
        ports:
            - port: 80
              protocol: TCP
            - port: 443
              protocol: TCP
        type: Public
        dnsNameLabel: caddy-example
    osType: Linux
tags: null
type: Microsoft.ContainerInstance/containerGroups

您必须更新caddy-example的2个示例和other-service的示例,并更改主机名中的location和区域。
然后我只需要部署它:

az container create --resource-group [something] --file azure_container_caddy.yaml

相关问题