.NET Core 2.2 ve Docker Linux kapsayıcılarında kendinden imzalı sertifikalar ve istemci sertifika kimlik doğrulaması ile çalışırken aynı sorunla karşılaştım. Dev Windows makinemde her şey yolunda gitti, ancak Docker'da böyle bir hata aldım:
System.Security.Authentication.AuthenticationException: Doğrulama prosedürüne göre uzak sertifika geçersiz
Neyse ki, sertifika bir zincir kullanılarak oluşturuldu. Tabii ki, bu çözümü her zaman görmezden gelebilir ve yukarıdaki çözümleri kullanabilirsiniz.
İşte benim çözümüm:
Sertifikayı Chrome kullanarak bilgisayarımda P7B formatında kaydettim.
Bu komutu kullanarak sertifikayı PEM formatına dönüştürün:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Ca_bundle.crt dosyasını açın ve tüm Konu kayıtlarını silin ve temiz bir dosya bırakın. Aşağıdaki örnek:
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
- Bu satırları Dockerfile'a koyun (son adımlarda):
# Update system and install curl and ca-certificates
RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates
# Copy your bundle file to the system trusted storage
COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt
# During docker build, after this line you will get such output: 1 added, 0 removed; done.
RUN update-ca-certificates
- Uygulamada:
var address = new EndpointAddress("https://serviceUrl");
var binding = new BasicHttpsBinding
{
CloseTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
ReceiveTimeout = new TimeSpan(0, 1, 0),
SendTimeout = new TimeSpan(0, 1, 0),
MaxBufferPoolSize = 524288,
MaxBufferSize = 65536,
MaxReceivedMessageSize = 65536,
TextEncoding = Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
AllowCookies = false,
BypassProxyOnLocal = false,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
Security =
{
Mode = BasicHttpsSecurityMode.Transport,
Transport = new HttpTransportSecurity
{
ClientCredentialType = HttpClientCredentialType.Certificate,
ProxyCredentialType = HttpProxyCredentialType.None
}
}
};
var client = new MyWSClient(binding, address);
client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert");
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication
{
CertificateValidationMode = X509CertificateValidationMode.ChainTrust,
TrustedStoreLocation = StoreLocation.LocalMachine,
RevocationMode = X509RevocationMode.NoCheck
};
GetClientCertificate yöntemi:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password)
{
byte[] rawData = null;
using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read))
{
var size = (int)f.Length;
var rawData = new byte[size];
f.Read(rawData, 0, size);
f.Close();
}
return new X509Certificate2(rawData, password);
}