ssl 通过https提供身份服务和微服务的Docker容器无法检索已知/openid配置

h5qlskok  于 2023-03-08  发布在  Docker
关注(0)|答案(1)|浏览(102)

我正在做一个使用IdentityServer来传递令牌给Ocelot网关和它的微服务的项目。它是在本地工作的,但是当我想在一个docker容器中配置相同的设置时,我不得不信任我的自签名证书。我的容器是linux容器,并且每个项目都是用一个docker文件生成的。这些不同的项目是用一个docker合成文件添加在一起的。
所有容器都在同一个域中运行,现在我想通过网关访问我的微服务,使用IdentityServer提供的令牌,所有这些都通过https进行。
这是我的Docker覆盖文件

version: '3.4'

services:
   abiidentity.web:
     environment:
       ASPNETCORE_ENVIRONMENT: docker
       ASPNETCORE_URLS: https://+;http://+
       Kestrel__Certificates__Default__Password: development
       Kestrel__Certificates__Default__Path: "/root/.aspnet/https/aspnetapp-identity-server.pfx"
     ports:
       - "45570:443"
       - "45571:80"
     volumes:
       - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https
       - type: bind
         source: "${APPDATA}\\ASP.NET\\Https\\aspnetapp-root-cert.cer"
         target: "/root/.aspnet/https/aspnetapp-root-cert.cer"
     depends_on:
       - idendity-db
       - abiweb.apigateway
  abiweb.HRM:
     environment:
       ASPNETCORE_ENVIRONMENT: docker
       ASPNETCORE_URLS: https://+;http://+
       Kestrel__Certificates__Default__Password: development
       Kestrel__Certificates__Default__Path: "/root/.aspnet/https/aspnetapp-web-api.pfx"
     ports:
       - "45591:443"
       - "45590:80"
     volumes:
       - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https
       - type: bind
         source: "${APPDATA}/ASP.NET/Https/aspnetapp-root-cert.cer"
         target: /root/.aspnet/https/aspnetapp-root-cert.cer
   abiweb.apigateway:
     environment:
       ASPNETCORE_ENVIRONMENT: docker
       ASPNETCORE_URLS: https://+;http://+
       Kestrel__Certificates__Default__Password: development
       Kestrel__Certificates__Default__Path: "/root/.aspnet/https/aspnetapp-gateway.pfx"
     ports:
       - "44351:443"
       - "44350:80"
     volumes:
       - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https
       - type: bind
         source: "${APPDATA}/ASP.NET/Https/aspnetapp-root-cert.cer"
         target: /root/.aspnet/https/aspnetapp-root-cert.cer

我已使用以下脚本生成证书:

# Source: https://stackoverflow.com/a/62060315
# Generate self-signed certificate to be used by IdentityServer.
# When using localhost - API cannot see the IdentityServer from within the docker-compose'd network.
# You have to run this script as Administrator (open Powershell by right click -> Run as Administrator).

$ErrorActionPreference = "Stop"

$rootCN = "IdentityServerDockerDemoRootCert"
$identityServerCNs = "abiidentity.web", "localhost"
$webApiCNs = "abiweb.hrm", "localhost"
$gatewayCns = "abiweb.apigateway", "localhost"

$alreadyExistingCertsRoot = Get-ChildItem -Path Cert:\LocalMachine\My -Recurse | Where-Object {$_.Subject -eq "CN=$rootCN"}
$alreadyExistingCertsIdentityServer = Get-ChildItem -Path Cert:\LocalMachine\My -Recurse | Where-Object {$_.Subject -eq ("CN={0}" -f $identityServerCNs[0])}
$alreadyExistingCertsApi = Get-ChildItem -Path Cert:\LocalMachine\My -Recurse | Where-Object {$_.Subject -eq ("CN={0}" -f $webApiCNs[0])}
$alreadyExistingCertsGateway = Get-ChildItem -Path Cert:\LocalMachine\My -Recurse | Where-Object {$_.Subject -eq ("CN={0}" -f $gatewayCns[0])}

if ($alreadyExistingCertsRoot.Count -eq 1) {
    Write-Output "Skipping creating Root CA certificate as it already exists."
    $testRootCA = [Microsoft.CertificateServices.Commands.Certificate] $alreadyExistingCertsRoot[0]
} else {
    $testRootCA = New-SelfSignedCertificate -Subject $rootCN -KeyUsageProperty Sign -KeyUsage CertSign -CertStoreLocation Cert:\LocalMachine\My
}

if ($alreadyExistingCertsIdentityServer.Count -eq 1) {
    Write-Output "Skipping creating Identity Server certificate as it already exists."
    $identityServerCert = [Microsoft.CertificateServices.Commands.Certificate] $alreadyExistingCertsIdentityServer[0]
} else {
    # Create a SAN cert for both identity-server and localhost.
    $identityServerCert = New-SelfSignedCertificate -DnsName $identityServerCNs -Signer $testRootCA -CertStoreLocation Cert:\LocalMachine\My
}

if ($alreadyExistingCertsApi.Count -eq 1) {
    Write-Output "Skipping creating API certificate as it already exists."
    $webApiCert = [Microsoft.CertificateServices.Commands.Certificate] $alreadyExistingCertsApi[0]
} else {
    # Create a SAN cert for both web-api and localhost.
    $webApiCert = New-SelfSignedCertificate -DnsName $webApiCNs -Signer $testRootCA -CertStoreLocation Cert:\LocalMachine\My
}

if ($alreadyExistingCertsGateway.Count -eq 1) {
    Write-Output "Skipping creating API certificate as it already exists."
    $webApiCert = [Microsoft.CertificateServices.Commands.Certificate] $alreadyExistingCertsGateway[0]
} else {
    # Create a SAN cert for both web-api and localhost.
    $webApiCert = New-SelfSignedCertificate -DnsName $gatewayCns -Signer $testRootCA -CertStoreLocation Cert:\LocalMachine\My
}

# Export it for docker container to pick up later.
$password = ConvertTo-SecureString -String "xxx" -Force -AsPlainText

$rootCertPathPfx = "C:/Users/jvdw/AppData/Roaming/ASP.NET/Https"
$identityServerCertPath = "C:/Users/jvdw/AppData/Roaming/ASP.NET/Https"
$webApiCertPath = "C:/Users/jvdw/AppData/Roaming/ASP.NET/Https"

[System.IO.Directory]::CreateDirectory($rootCertPathPfx) | Out-Null
[System.IO.Directory]::CreateDirectory($identityServerCertPath) | Out-Null
[System.IO.Directory]::CreateDirectory($webApiCertPath) | Out-Null

Export-PfxCertificate -Cert $testRootCA -FilePath "$rootCertPathPfx/aspnetapp-root-cert.pfx" -Password $password | Out-Null
Export-PfxCertificate -Cert $identityServerCert -FilePath "$identityServerCertPath/aspnetapp-identity-server.pfx" -Password $password | Out-Null
Export-PfxCertificate -Cert $webApiCert -FilePath "$webApiCertPath/aspnetapp-web-api.pfx" -Password $password | Out-Null
Export-PfxCertificate -Cert $webApiCert -FilePath "$rootCertPathPfx/aspnetapp-gateway.pfx" -Password $password | Out-Null

# Export .cer to be converted to .crt to be trusted within the Docker container.
$rootCertPathCer = "C:/Users/jvdw/AppData/Roaming/ASP.NET/Https/aspnetapp-root-cert.cer"
Export-Certificate -Cert $testRootCA -FilePath $rootCertPathCer -Type CERT | Out-Null

# Trust it on your host machine.
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store "Root","LocalMachine"
$store.Open("ReadWrite")

$rootCertAlreadyTrusted = ($store.Certificates | Where-Object {$_.Subject -eq "CN=$rootCN"} | Measure-Object).Count -eq 1

if ($rootCertAlreadyTrusted -eq $false) {
    Write-Output "Adding the root CA certificate to the trust store."
    $store.Add($testRootCA)
}

$store.Close()

在执行脚本之后,我的所有pfx文件都生成了,然后我检查了这些文件在我的docker容器示例中是否可用,情况确实如此。
但当我https://aibiidentity.web在容器示例的终端中执行“wget www.example.com”时,我得到以下响应:

root@1e3233925091:/app# wget https://abiidentity.web
--2023-03-06 19:30:39--  https://abiidentity.web/
Resolving abiidentity.web (abiidentity.web)... 172.21.0.11
Connecting to abiidentity.web (abiidentity.web)|172.21.0.11|:443... connected.
ERROR: The certificate of 'abiidentity.web' is not trusted.
ERROR: The certificate of 'abiidentity.web' doesn't have a known issuer.

当我检查我的根证书是否可信时,我得到一个ok:

echo | openssl verify /usr/local/share/ca-certificates/aspnetapp-root-cert.crt 
/usr/local/share/ca-certificates/aspnetapp-root-cert.crt: OK

有人能告诉我我做错了什么吗?我还关注了这篇博客文章:https://mjarosie.github.io/dev/2020/09/24/running-identityserver4-on-docker-with-https.html

gudnpqoy

gudnpqoy1#

要使linux容器信任您的证书,您需要在Dockerfile上添加一个新步骤,将证书复制到类似/usr/local/share/ca-certificates/的路径
COPY path/to/your/crt /usr/local/share/ca-certificates/
然后运行update-ca-certificates
RUN sudo update-ca-certificates

  • 基于Debian的发行版 *,如果您使用的是基于RHEL的发行版,您可以完成此操作,但使用不同的命令。

这样,生成的映像将在其CA存储上具有您的证书,因此信任您对使用该证书的https端点所做的任何连接。
换句话说,您需要在主机上安装证书,以连接到服务公开的TLS端点。但是,如果在容器上运行的服务还需要连接到容器公开的其他TLS端点,则该容器也需要安装证书,就像您的主机一样。
您还可以创建一个新的Dockerfile,并使用原始映像作为基础来创建一个带有证书的特定Docker映像,您可以在您的Docker-Compsoe上使用该映像,而不是原始服务映像。

相关问题