问题
I want to host identity server 4 on azurewebsites.net https but I am not sure how to find ssl certificate of my someapp.azurewebsites.net sub domain so I can use it as thumbprint? Is that even possible to obtain ssl certificate that is running on your webapp on azurewebsites.net subdomain?
回答1:
One way to use a self-signed certificate to use for token signing with IdentityServer4 is to store the certificate with the application under the 'wwwroot' folder.
You can use OpenSSL to generate a self-signed certificate.
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout example.key -out example.crt -subj "/CN=example.com" -days 3650
Then load the certificate in the 'Startup.cs' class/file.
public void ConfigureServices(IServiceCollection services)
{
.....other code .....
var fileName = Path.Combine(env.WebRootPath, "YOUR_FileName" );
if (!File.Exists(fileName))
{
throw new FileNotFoundException("Signing Certificate is missing!");
}
var cert = new X509Certificate2(fileName, "Your_PassPhrase" );
services.AddIdentityServer().AddSigningCredential(cert)
...other code.....
}
回答2:
Use self-signed certificates. Since Identity Server only uses the certs internally, it doesn't matter that they aren't signed by a trusted CA, you aren't presenting them to others. I store my signing certificates in Azure Key Vault as serialized Secrets. Key Vault is very inexpensive but you have to cache the results, it isn't meant for high traffic.
Remember to enable Managed Service Identity on the website, Function App, or whatever else is retrieving the values, and add those to the Key Vault SAS list with read-access to Secrets.
Powershell: Create Signing Certificate
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$password = "",
[Parameter(Mandatory=$true)][string]$rootDomain = ""
)
$cwd = Convert-Path .
$sCerFile = "$cwd\token_signing.cer"
$sPfxFile = "$cwd\token_signing.pfx"
$vCerFile = "$cwd\token_validation.cer"
$vPfxFile = "$cwd\token_validation.pfx"
# abort if files exist
if((Test-Path($sPfxFile)) -or (Test-Path($sCerFile)) -or (Test-Path($vPfxFile)) -or (Test-Path($vCerFile)))
{
Write-Warning "Failed, token_signing or token_validation files already exist in current directory."
Exit
}
function Get-NewCert ([string]$name)
{
New-SelfSignedCertificate `
-Subject $rootDomain `
-DnsName $rootDomain `
-FriendlyName $name `
-NotBefore (Get-Date) `
-NotAfter (Get-Date).AddYears(10) `
-CertStoreLocation "cert:CurrentUser\My" `
-KeyAlgorithm RSA `
-KeyLength 4096 `
-HashAlgorithm SHA256 `
-KeyUsage DigitalSignature, KeyEncipherment, DataEncipherment `
-Type Custom,DocumentEncryptionCert `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")
}
$securePass = ConvertTo-SecureString -String $password -Force -AsPlainText
# token signing certificate
$cert = Get-NewCert("IdentityServer Token Signing Credentials")
$store = 'Cert:\CurrentUser\My\' + ($cert.ThumbPrint)
Export-PfxCertificate -Cert $store -FilePath $sPfxFile -Password $securePass
Export-Certificate -Cert $store -FilePath $sCerFile
Write-Host "Token-signing thumbprint: " $cert.Thumbprint
# token validation certificate
$cert = Get-NewCert("IdentityServer Token Validation Credentials")
$store = 'Cert:\CurrentUser\My\' + ($cert.ThumbPrint)
Export-PfxCertificate -Cert $store -FilePath $vPfxFile -Password $securePass
Export-Certificate -Cert $store -FilePath $vCerFile
Write-Host "Token-validation thumbprint: " $cert.Thumbprint
Powershell: Upload Certificate to Azure Key Vault
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$password = "",
[Parameter(Mandatory=$true)][string]$pfxFilename = "",
[Parameter(Mandatory=$true)][string]$keyVaultName = "",
[Parameter(Mandatory=$true)][string]$secretName = ""
)
$cwd = Convert-Path .
$pfxFile = "$cwd\$pfxFilename.pfx"
# abort when file not found
if(!(Test-Path($pfxFile)))
{
Write-Warning "Failed, $pfxFilename.pfx not found $cwd"
Exit
}
# force Azure login, if needed
function CheckLogin
{
$needLogin = $true
Try
{
$content = Get-AzureRmContext
if ($content)
{
$needLogin = ([string]::IsNullOrEmpty($content.Account))
}
}
Catch
{
if ($_ -like "*Login-AzureRmAccount to login*")
{
$needLogin = $true
}
else
{
throw
}
}
if ($needLogin)
{
Login-AzureRmAccount
}
}
CheckLogin
# load the PFX
$flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$coll = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$coll.Import($pfxFile, $password, $flag)
# export to byte array
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12
$bytes = $coll.Export($type)
# base64 encode
$base64 = [System.Convert]::ToBase64String($bytes)
$value = ConvertTo-SecureString -String $base64 -AsPlainText –Force
# send it to Azure KeyVault
$type = 'application/x-pkcs12'
Set-AzureKeyVaultSecret -VaultName $keyVaultName -Name $secretName -SecretValue $value -ContentType $type
Thread-Safe Key Vault Cache
public class KeyVaultCache
{
private KeyVaultClient _KeyVaultClient = null;
public KeyVaultClient KeyVaultClient
{
get
{
if(_KeyVaultClient is null)
{
var provider = new AzureServiceTokenProvider();
_KeyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(provider.KeyVaultTokenCallback));
}
return _KeyVaultClient;
}
}
private ConcurrentDictionary<string, string> SecretsCache = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public async Task<string> GetCachedSecret(string secretName)
{
if(!SecretsCache.ContainsKey(secretName))
{
var secretBundle = await KeyVaultClient.GetSecretAsync($"{AzureUris.KeyVaultSecrets}{secretName}").ConfigureAwait(false);
SecretsCache.TryAdd(secretName, secretBundle.Value);
}
return SecretsCache.ContainsKey(secretName) ? SecretsCache[secretName] : string.Empty;
}
}
Retreival of Deserialized Certificates
public async Task<X509Certificate2> TokenValidationCertificate() => PfxStringToCert(await cache.GetCachedSecret("x509-token-validation"));
public async Task<X509Certificate2> TokenSigningCertificate() => PfxStringToCert(await cache.GetCachedSecret("x509-token-signing"));
private X509Certificate2 PfxStringToCert(string pfx)
{
var bytes = Convert.FromBase64String(pfx);
var coll = new X509Certificate2Collection();
coll.Import(bytes, null, X509KeyStorageFlags.Exportable);
return coll[0];
}
来源:https://stackoverflow.com/questions/49075143/identityserver4-with-azurewebsites-net-domain-how-to-get-ssl-thumbprint