Ocelot + consul + 我的 web api (.Net 5) 通过 Docker 中的 HTTPS 我的 docker-compose:我的配置文件“ocelot.json”没有Consul的版本docker-compose ps案例 1:案例 2:案例 3我有问题,也许有人可以帮助我,请:

问题描述

我正在尝试通过 Docker 中的 HTTPS 使用 Ocelot(Api 网关)+ consul + 我的 web api(.Net 5);

信任来自适用于 Linux 的 Windows 子系统的 HTTPS 证书

来源:https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-5.0&tabs=visual-studio#trust-https-certificate-from-windows-subsystem-for-linux

MY_SECRET_PROJECT_PATH\LicenseServiceWebApi> dotnet dev-certs https --clean
Cleaning HTTPS development certificates from the machine. A prompt might get displayed to confirm the removal of some of the certificates.
HTTPS development certificates successfully removed from the machine.

MY_SECRET_PROJECT_PATH\LicenseServiceWebApi> dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\aspnetdev.pfx -p <водкабалалайка>
The HTTPS developer certificate was generated successfully.

MY_SECRET_PROJECT_PATH\LicenseServiceWebApi> dotnet dev-certs https --trust
Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed if the certificate was not prevIoUsly trusted. Click yes on the prompt to trust the certificate.
A valid HTTPS certificate is already present.

我的 docker-compose:

version: '3'

services:
  license-service-web-api-01:
    image: license-service-web-api
    container_name: license-service-01
    build: 
      context: .
      dockerfile: Services/LicenseServiceWebApi/Dockerfile
    environment:                      
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:9001;http://+:9000    
      - ASPNETCORE_Kestrel__Certificates__Default__Password=${Kestrel_Certificate_Password}
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/root/.aspnet/https/aspnetdev.pfx
    volumes:
      - ${USERPROFILE}\.aspnet\https:/root/.aspnet/https/:ro
    ports:
      - 9000:9000
      - 9001:9001
    depends_on:
      - consul
                     
  gateway:
    image: gateway
    container_name: gateway
    build: 
      context: .
      dockerfile: ApiGateway/gateway/Dockerfile                  
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:5001;http://+:5000
      - ASPNETCORE_Kestrel__Certificates__Default__Password=${Kestrel_Certificate_Password}
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/root/.aspnet/https/aspnetdev.pfx
    volumes:
      - ${USERPROFILE}\.aspnet\https:/root/.aspnet/https/:ro 
    ports:
      - 5001:5001
      - 5000:5000
    depends_on:
      - consul

  consul:
    image: consul
    container_name: consul
    command: agent -server -ui -node=server-1 -bootstrap-expect=1 -client=0.0.0.0
    environment: 
      - 'CONSUL_LOCAL_CONfig= {"connect": {"enabled": true}}'
    ports: 
      - 8500:8500

我的配置文件“ocelot.json”(没有Consul的版本)

{
  "Routes": [
    {
      "SwaggerKey": "License Service","DownstreamPathTemplate": "/api/{everything}","DownstreamScheme": "http","DownstreamHostAndPorts": [
        {
          "Host": "license-service-web-api-01","Port": 9000
        }
      ],"UpstreamHttpMethod": [ "Put","Post","GET" ],"UpstreamPathTemplate": "/{everything}","LoadBalancerOptions": {
        "Type": "LeastConnection"
      },"FileCacheOption": {
        "TtlSeconds": 30
      }
    },{
      "DownstreamPathTemplate": "/swagger/{everything}","UpstreamPathTemplate": "/swagger/{everything}","FileCacheOption": {
        "TtlSeconds": 666
      }
    }
  ],"SwaggerEndPoints": [
    {
      "Key": "License Service","Config": [
        {
          "Name": "License Service API","Version": "v1","Service": {
            "Name": "License Service","Path": "/swagger/v1/swagger.json"
          }
        }
      ]
    }
  ]
}

docker-compose ps

       Name                     Command               State                                              Ports
----------------------------------------------------------------------------------------------------------------------------------------------------------
consul               docker-entrypoint.sh agent ...   Up      8300/tcp,8301/tcp,8301/udp,8302/tcp,8302/udp,0.0.0.0:8500->8500/tcp,8600/tcp,8600/udp
gateway              dotnet gateway.dll               Up      443/tcp,0.0.0.0:5000->5000/tcp,0.0.0.0:5001->5001/tcp
license-service-01   dotnet LicenseServiceWebAp ...   Up      443/tcp,0.0.0.0:9000->9000/tcp,0.0.0.0:9001->9001/tcp

案例 1:

PS C:\Users\tim> curl http://localhost:9000/api/HealthCheck/GetMachineName
StatusCode        : 200
StatusDescription : OK
Content           : MachineName=2a429d520129
RawContent        : HTTP/1.1 200 OK

PS C:\Users\tim> curl https://localhost:9001/api/HealthCheck/GetMachineName
StatusCode        : 200
StatusDescription : OK
Content           : MachineName=2a429d520129
RawContent        : HTTP/1.1 200 OK

PS C:\Users\tim> curl http://localhost:5000/HealthCheck/GetMachineName
StatusCode        : 200
StatusDescription : OK
Content           : MachineName=2a429d520129
RawContent        : HTTP/1.1 200 OK

PS C:\Users\tim> curl https://localhost:5001/HealthCheck/GetMachineName
StatusCode        : 200
StatusDescription : OK
Content           : MachineName=2a429d520129
RawContent        : HTTP/1.1 200 OK

案例 2:

我在我的服务中添加了 https 重定向

app.UseHttpsRedirection();
PS C:\Users\tim> curl http://localhost:9000/api/HealthCheck/GetMachineName
StatusCode        : 200
StatusDescription : OK
Content           : MachineName=345437c4c182
RawContent        : HTTP/1.1 200 OK

PS C:\Users\tim> curl https://localhost:9001/api/HealthCheck/GetMachineName                                                                                                                                                                     
StatusCode        : 200
StatusDescription : OK
Content           : MachineName=345437c4c182
RawContent        : HTTP/1.1 200 OK

PS C:\Users\tim> curl http://localhost:5000/HealthCheck/GetMachineName
curl : Unable to resolve the remote name: 'license-service-web-api-01'

docker-compose logs ..
 
gateway                       | info: Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware[0]
gateway                       |       requestId: 0HM6VQAI1UTJU:00000002,prevIoUsRequestId: no prevIoUs request id,message: EndpointRateLimiting is not enabled for /api/{everything}
gateway                       | info: Ocelot.Authentication.Middleware.AuthenticationMiddleware[0]
gateway                       |       requestId: 0HM6VQAI1UTJU:00000002,message: No authentication needed for /HealthCheck/GetMachineName
gateway                       | info: Ocelot.Authorization.Middleware.AuthorizationMiddleware[0]
gateway                       |       requestId: 0HM6VQAI1UTJU:00000002,message: /api/{everything} route does not require user to be authorized
gateway                       | info: Ocelot.Requester.Middleware.HttpRequesterMiddleware[0]
gateway                       |       requestId: 0HM6VQAI1UTJU:00000002,message: 307 (Temporary Redirect) status code,request uri: http://license-service-web-api-01:9000/api/HealthCheck/GetMachineName


PS C:\Users\tim> curl https://localhost:5001/HealthCheck/GetMachineName
curl : Unable to resolve the remote name: 'license-service-web-api-01'

..The logs are the same

案例 3

我更改了 https 和端口 9001 上的配置文件 ocelot.json

"DownstreamScheme": "https","DownstreamHostAndPorts": [
    {
        "Host": "license-service-web-api-01","Port": 9001
    }
],

在我的服务中删除了第 app.UseHttpsRedirection();

GET https://localhost:5001/WeatherForecast
502
225 ms
Warning: Unable to verify the first certificate
GET /WeatherForecast HTTP/1.1
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Postman-Token: 6cafa9e0-e195-4082-a7d4-daac4f58dff7
Host: localhost:5001
Accept-Encoding: gzip,deflate,br
Connection: keep-alive
HTTP/1.1 502 Bad Gateway
Date: Fri,05 Mar 2021 14:50:01 GMT
Server: Kestrel
Content-Length: 0

gateway                       | info: Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware[0]
gateway                       |       requestId: 0HM6VSNQ8J5GI:00000002,message: EndpointRateLimiting is not enabled for /api/{everything}
gateway                       | info: Ocelot.Authentication.Middleware.AuthenticationMiddleware[0]
gateway                       |       requestId: 0HM6VSNQ8J5GI:00000002,message: No authentication needed for /WeatherForecast
gateway                       | info: Ocelot.Authorization.Middleware.AuthorizationMiddleware[0]
gateway                       |       requestId: 0HM6VSNQ8J5GI:00000002,message: /api/{everything} route does not require user to be authorized
gateway                       | warn: Ocelot.Responder.Middleware.ResponderMiddleware[0]
gateway                       |       requestId: 0HM6VSNQ8J5GI:00000002,message: Error Code: ConnectionTodownstreamServiceError Message: Error connecting to downstream service,exception: System.Net.Http.HttpRequestException: The SSL connection Could not be established,see inner exception.
gateway                       |        ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch,RemoteCertificateChainErrors
gateway                       |          at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message,ExceptiondispatchInfo exception)
gateway                       |          at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter,Boolean receiveFirst,Byte[] reAuthenticationData,Boolean isApm)
gateway                       |          at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async,Stream stream,SslClientAuthenticationoptions sslOptions,CancellationToken cancellationToken)
gateway                       |          --- End of inner exception stack trace ---
gateway                       |          at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async,CancellationToken cancellationToken)
gateway                       |          at System.Net.Http.httpconnectionPool.ConnectAsync(HttpRequestMessage request,Boolean async,CancellationToken cancellationToken)
gateway                       |          at System.Net.Http.httpconnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request,CancellationToken cancellationToken)
gateway                       |          at System.Net.Http.httpconnectionPool.GethttpconnectionAsync(HttpRequestMessage request,CancellationToken cancellationToken)
gateway                       |          at System.Net.Http.httpconnectionPool.SendWithRetryAsync(HttpRequestMessage request,Boolean doRequestAuth,CancellationToken cancellationToken)
gateway                       |          at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request,CancellationToken cancellationToken)
gateway                       |          at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request,HttpCompletionoption completionoption,Boolean emitTelemetryStartStop,CancellationToken cancellationToken)
gateway                       |          at Ocelot.Requester.HttpClientHttpRequester.GetResponse(HttpContext httpContext) errors found in ResponderMiddleware. Setting error response for request path:/WeatherForecast,request method: GET

我有问题,也许有人可以帮助我,请:

  1. 为什么豹猫无法通过 https 呼叫我的服务器?
  2. 如何在 docker 中为 Consul 启用 https - 撰写?

解决方法

最后一种情况你有一个 ssl 错误。对于这个问题,您可以有 2 个选项

  1. best.option您创建自己的证书,然后让本地或远程机器信任它。

  2. 快速选项您可以将此行添加到您的 ocelot.json

    "DangerousAcceptAnyServerCertificateValidator": true

您应该在 docker-compose 文件中添加 networks 标签。 如下图:

version: '3'

networks:
  dockerapi:
    driver: bridge

services:
  license-service-web-api-01:
    image: license-service-web-api
    container_name: license-service-01
    build: 
      context: .
      dockerfile: Services/LicenseServiceWebApi/Dockerfile
    environment:                      
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:9001;http://+:9000    
      - ASPNETCORE_Kestrel__Certificates__Default__Password=${Kestrel_Certificate_Password}
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/root/.aspnet/https/aspnetdev.pfx
    volumes:
      - ${USERPROFILE}\.aspnet\https:/root/.aspnet/https/:ro
    ports:
      - 9000:9000
      - 9001:9001
    depends_on:
      - consul
    networks:
      - dockerapi   
                     
  gateway:
    image: gateway
    container_name: gateway
    build: 
      context: .
      dockerfile: ApiGateway/gateway/Dockerfile                  
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:5001;http://+:5000
      - ASPNETCORE_Kestrel__Certificates__Default__Password=${Kestrel_Certificate_Password}
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/root/.aspnet/https/aspnetdev.pfx
    volumes:
      - ${USERPROFILE}\.aspnet\https:/root/.aspnet/https/:ro 
    ports:
      - 5001:5001
      - 5000:5000
    depends_on:
      - consul
    networks:
      - dockerapi