{"copy":"Zkop\u00edrovat","expand":"Rozbalit","collapse":"Sbalit","copy_success":"Zkop\u00edrov\u00e1no!","copy_error":"Kop\u00edrov\u00e1n\u00ed selhalo!"}

Jak na Windows Serveru s IIS použít certifikát z Azure Key Vault

Logo Azure Key Vault Tento návod vám pomůže nasadit certifikáty ze služby Azure Key Vault do vašeho IIS webserveru na Windows Serveru. Azure Key Vault může být propojen přímo s DigiCertem a automatizován. Návod je vytvořen pro dvě varianty - pro virtuální stroje v Azure a pro ty on-premise Windows Servery, které máte ve firmě.

Tento návod předpokládá, že budeme mít certifikát v Azure Key Vaultu. Jak ho tam dostat pomocí přímého napojení na CA DigiCert najdete v návodu Propojení Azure Key Vault s CA DigiCert.

Pak máte dvě možnosti nasazení TLS certifikátu na server:

Tento návod pokrývá oba scénáře, přičemž první je bezpečnější (certifikát se neexportuje z Azure Key Vaultu a neukládá lokálně).

Varianta nasazení na VM v Azure

Pokud máte virtuální Windows server (VM) přímo v Azure, využijte tuto možnost. Nainstalujte si Azure PowerShell a Az PowerShell module.

V návodu je použit Windows Server 2022 s IIS 10 (poslední verzi 2025 není možné pro tento účet použít) a použil jsem rozšíření KeyVaultForWindows ve verzi 3.3.

Automatická synchronizace certifikátu z Azure Key Vault do Azure VM

Povolte Managed Identity na Azure VM

V Azure Portal otevřete VM > Identity > System assigned a zapněte ji. Přejděte do Azure Key Vault > Access Policies a přidejte oprávnění pro VM.

Pro nejlepší praxi Microsoft doporučuje pro VM rozšíření využít Azure RBAC model. V tomto případě se pro Managed Identity očekává přiřazená role Key Vault Secrets User na úrovni vaultu prostřednictvím Azure RBAC.

Pokud se rozhodnete pro Access Policies, udělte v sekci `Secrets` oprávnění `Get` a `List`. Oprávnění v sekci `Certificates` nejsou obvykle potřeba, pokud používáte `secretsManagementSettings`, jelikož rozšíření stahuje PFX soubor z `/secrets/` endpointu, a proto využívá oprávnění pro Secrets. Oprávnění na `Certificate` by byla relevantní pouze při použití `certificateManagementSettings`.

Instalace Azure Key Vault VM Extension

Vytvořte v prvním kroku konfigurační soubor, který bude uložen lokálně na serveru. V něm uveďte cestu k "Secrets" ve Vaultu, nikoliv jen k certifikátu (taková cesta vede pouze na veřejný klíč).


{
"secretsManagementSettings": {
"pollingIntervalInS": "60",
"certificateStoreName": "MY",
"certificateStoreLocation": "LocalMachine",
"observedCertificates": [
{
"url": "https://xxxxx-test.vault.azure.net/secrets/zoner-test-azure",
"certificateStoreName": "MY",
"certificateStoreLocation": "LocalMachine"
}
]
}
} 

Pokud používáte user-assigned managed identity, musí v JSON bloku `authenticationSettings` být specifikován `msiEndpoint` a `msiClientId` vaší user-assigned identity. Příklad:


{
  "secretsManagementSettings": {
    "pollingIntervalInS": "3600",
    "certificateStoreName": "MY",
    "certificateStoreLocation": "LocalMachine",
    "observedCertificates": [
      { "url": "https://.vault.azure.net/secrets/",
        "certificateStoreName": "MY",
        "certificateStoreLocation": "LocalMachine"
      }
    ]
  },
  "authenticationSettings": {
    "msiEndpoint": "http://169.254.169.254/metadata/identity/oauth2/token",
    "msiClientId": ""
  }
}

Pak nainstalujte a spusťte VM extension (PowerShell). Nastavení načtěte z lokálně uloženého JSON souboru. Název VM a Resource Group si můžete uložit i jako proměnné a použít je, nebo konkrétní názvy.

az vm extension set --resource-group "RG-name" --vm-name "vmname" --name "KeyVaultForWindows" --publisher "Microsoft.Azure.KeyVault" --version 3.3 --settings ".\settings.json"

Po spuštění tohoto příkazu bude program v PS chvíli pracovat a při úspěchu dostanete dlouhý JSON report o stavu VM extension. Následně se certifikát objeví ve Windows certificate store v Local Computer -> Personal -> Certificates. Tím, že je v Local Computer, na něj vidí všechny aplikace včetně IIS. Synchronizace může trvat, záleží na intervalu "pollingIntervalInS" a kolik jste v něm uvedli sekund.

Ověření synchronizace certifikátu

Po instalaci zkontrolujte, zda se certifikát stáhl do Windows Certificate Store:

PowerShell
certlm.msc

Certifikát by měl být v sekci Personal > Certificates.

ACL Oprávnění pro privátní klíče: Po importu certifikátu v konzoli v MMC (Local Computer → Certificates → vaše certifikáty) klikněte na certifikát → All Tasks → Manage Private Keys. Zde přidejte účet IIS (`IIS_IUSRS` nebo `Network Service`) s právem `Read`. Absence těchto oprávnění může způsobit chybu "logon session does not exist" v IIS.

Automatické přiřazení certifikátu k IIS

Prvně si vypište certifikáty dostupné v Local Machine Storu:

Get-ChildItem -Path Cert:\LocalMachine\My

Pak vybereme správný certifikát podle otisku a uložíme ho do proměnné `$cert`:

$certThumbprint = "THUMBPRINT_VYBRANEHO_CERTIFIKATU"
$cert = Get-ChildItem -Path Cert:\LocalMachine\My |
Where-Object { $_.Thumbprint -eq $certThumbprint }

Pro zajištění, že se nedeploynul špatný certifikát, doporučujeme přidat validaci certifikátu k doméně. Můžete přidat kontrolu `Subject` certifikátu:

$expectedDomain = "zoner-test-azure.eu" # Nahraďte očekávanou doménou
if ($cert.Subject -notmatch "CN=$expectedDomain") {
    throw "Certificate subject mismatch. Expected CN to contain '$expectedDomain'."
}

Nyní přiřadíme vybraný certifikát k Bindingu. Verze 3.0 VM Extension obsahuje podporu "IIS Certificate Rebind", kterou lze využít pro automatickou změnu vazby v IIS při aktualizaci certifikátu.

Doporučený postup pro vazbu certifikátu:

Nejprve vytvořte vazbu (s `SslFlags 1` pro SNI, pokud je třeba):

New-WebBinding -Name "Default Web Site" -Protocol https -Port 443 -HostHeader "zoner-test-azure.eu" -SslFlags 1

Poté certifikát přiřaďte pomocí metody `.AddSslCertificate()`:

(Get-WebBinding -Name "Default Web Site" -Protocol https).AddSslCertificate($certThumbprint, 'My')

Alternativně, můžete použít `netsh` pro přímé přidání SSL certifikátu k HTTP.sys. Thumbprint certifikátu ve storu už známe, budete ještě potřebovat appid, které zjistíte pomocí

[guid]::NewGuid()


$certThumbprint = "THUMBPRINT_VYBRANEHO_CERTIFIKATU"
$port = 443
$appid = "{00112233-4455-6677-8899-AABBCCDDEEFF}"  # Nahraďte svým GUID aplikace
$certStoreName = "MY"  # 'MY' = 'Personal' ve Windows cert store


$cert = Get-ChildItem -Path Cert:\LocalMachine\My |
Where-Object { $_.Thumbprint -replace '\s','' -ieq $certThumbprint }

if (-not $cert) {
    Write-Host "❌ Certifikát s otiskem $certThumbprint nebyl nalezen v LocalMachine\My." `
    -ForegroundColor Red
    return
}

if (-not $cert.HasPrivateKey) {
    Write-Host "❌ Certifikát neobsahuje privátní klíč, nelze jej použít pro SSL." `
    -ForegroundColor Red
    return
}

# === Odebrání případného existujícího bindingu ===
Write-Host "? Odstraňuji starý SSL binding na 0.0.0.0:$port (pokud existuje)..."
netsh http delete sslcert ipport=0.0.0.0:$port | Out-Null

# === Přidání nového bindingu pomocí netsh ===
Write-Host "? Přidávám nový SSL certifikát pro 0.0.0.0:$port..."

netsh http add sslcert `
    ipport=0.0.0.0:$port `
    certhash=$($cert.Thumbprint) `
    appid=$appid `
    certstorename=$certStoreName | Out-Null

Write-Host "✅ Certifikát byl úspěšně přiřazen ke 0.0.0.0:$port pomocí netsh." `
-ForegroundColor Green

Nakonec proveďte reload IIS:

iisreset

Že se certifikát přiřadil ke správnému bindingu zkontrolovat manuálně v IIS, nebo pomocí tohoto skriptu:


$bindings = Get-WebBinding |
Where-Object {$_.protocol -eq "https"}

foreach ($binding in $bindings) {
    $bindingDetails = $binding |
Select-Object -Property protocol, bindingInformation
    $parts = $bindingDetails.bindingInformation.Split(":")
    $ip = $parts[0]
    $port = $parts[1]

    if ($ip -eq "*") {
        $ip = "0.0.0.0"
    }

    try {
        $sslCertOutput = netsh http show sslcert ipport=${ip}:${port}

        # Vytáhni potřebné řádky
        $certHash = ($sslCertOutput | Select-String "Certificate Hash").Line.Split(":")[1].Trim()
        $storeName = ($sslCertOutput | Select-String
"Certificate Store Name").Line.Split(":")[1].Trim()

        Write-Host "`n? SSL Binding: ${ip}:${port}" -ForegroundColor Cyan
        Write-Host "  Certificate Hash   : $certHash"
        Write-Host "  Store              : $storeName"

        # Vyhledání certifikátu v LocalMachine\
        $cert = Get-ChildItem -Path "Cert:\LocalMachine\$storeName" |
Where-Object {
            $_.Thumbprint -replace '\s','' -ieq $certHash
        }

        if ($cert) {
            Write-Host "  CN (Subject)       : $($cert.Subject)"
            Write-Host "  Platnost           : $($cert.NotBefore.ToShortDateString()) – $($cert.NotAfter.ToShortDateString())"
        } else {
  
           Write-Host "  ⚠️  Certifikát s tímto otiskem nebyl nalezen ve Windows certifikátovém úložišti."
 }

    } catch {
        Write-Host "❌ Nelze načíst certifikát pro ${ip}:${port} – $($_.Exception.Message)"
    }

    Write-Host "`n---`n"
}
    

Doporučuji zkonfigurovat a zkontrolovat, ať tam nemáte nějaké Bindings navíc.

Automatická obnova

Azure Key Vault VM Extension zajistí, že se certifikát při změně v Key Vaultu automaticky aktualizuje. IIS se při změně certifikátu restartuje a vždy použije nejnovější verzi.

Varianta nasazení na on-premise server

Pokud máte Windows server na vlastním virtuálu či vlastním železe, není možné využít Azure Key Vault VM Extension a je potřeba import udělat jinak.

Automatická synchronizace certifikátu z Azure Key Vault do on-premise IIS

Vytvoření Azure AD aplikace pro přístup k Key Vault

V Azure Portal přejděte do Azure Active Directory > App registrations a vytvořte novou aplikaci. Po registraci aplikace zkopírujte Application (client) ID a Directory (tenant) ID.

V sekci Certificates & secrets vygenerujte nový client secret a uložte ho.

Přiřazení oprávnění aplikaci v Azure Key Vault

  • Otevřete Azure Key Vault > Access Policies.
  • Přidejte oprávnění pro aplikaci:
    • Get, List pro Secret permissions
    • Get, List pro Certificate permissions

Aplikaci je následně potřeba vytvořit a přidělit Client Secret.

Stáhnutí certifikátu z Azure Key Vault na on-premise server

PowerShell
$tenantId = "TENANT_ID"
$clientId = "CLIENT_ID"
$clientSecret = "CLIENT_SECRET"
$vaultName = "MOJE-KEYVAULT-JMENO"
$certName = "MOJE-CERTIFIKAT-JMENO"
$outputPath = "C:\certscert.pfx"

# Přihlášení k Azure AD
$body = @{grant_type="client_credentials";
client_id=$clientId; client_secret=$clientSecret; resource="https://vault.azure.net" }
$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/token" -Body $body
$token = $tokenResponse.access_token

# Získání certifikátu
$headers = @{ Authorization = "Bearer $token" }
$apiVersion = "7.5"
$secret = Invoke-RestMethod -Uri "https://$vaultName.vault.azure.net/secrets/${certName}?api-version=$apiVersion" -Headers $headers
$pfxBytes = [Convert]::FromBase64String($secret.value)
[System.IO.File]::WriteAllBytes($outputPath, $pfxBytes)

Import certifikátu do Windows Certificate Store

PowerShell
$password = ConvertTo-SecureString -String "MOJE-HESLO" -Force -AsPlainText
Import-PfxCertificate -FilePath $outputPath -CertStoreLocation Cert:LocalMachineMy -Password $password

ACL Oprávnění pro privátní klíče: Po importu certifikátu v konzoli v MMC (Local Computer → Certificates → vaše certifikáty) klikněte na certifikát → All Tasks → Manage Private Keys. Zde přidejte účet IIS (`IIS_IUSRS` nebo `Network Service`) s právem `Read`. Absence těchto oprávnění může způsobit chybu "logon session does not exist" v IIS.

Přiřazení certifikátu k IIS

Nejprve zjistíme otisk certifikátu, který je v certificate storu.

PowerShell
$cert = Get-ChildItem -Path Cert:LocalMachineMy |
Sort-Object NotAfter -Descending | Select-Object -First 1
$thumbprint = $cert.Thumbprint

Pak vytvoříme Binding a přiřadíme ho. `New-WebBinding` vytvoří vazbu a certifikát k ní musíte přiřadit pomocí metody `.AddSslCertificate(Thumbprint, 'My')`.

Nejprve vytvořte vazbu (s `SslFlags` pro SNI, pokud je třeba):

New-WebBinding -Name "Default Web Site" -Protocol https -Port 443 -HostHeader "zoner-test-azure.eu" -SslFlags 1

Poté certifikát přiřaďte:

(Get-WebBinding -Name "Default Web Site" -Protocol https).AddSslCertificate($certThumbprint, 'My')

Alternativně můžete použít netsh pro přímé přidání SSL certifikátu k HTTP.sys:

netsh http add sslcert ipport=0.0.0.0:443 `
    certhash= `
    appid={} `
    certstorename=My

Pro načtení nové konfigurace použijte iisreset.

Doporučuje se přidat validaci certifikátu k doméně, aby se nedeploynul špatný certifikát. Můžete přidat kontrolu "Subject" certifikátu:

$expectedDomain = "zoner-test-azure.eu" # Nahraďte očekávanou doménou
if ($cert.Subject -notmatch "CN=$expectedDomain") {
    throw "Certificate subject mismatch. Expected CN to contain '$expectedDomain'."
}

Automatická obnova

Naplánujte tento skript jako Scheduled Task (například denně) v Task Scheduleru, aby se certifikát automaticky aktualizoval při změně v Azure Key Vault.

Povolení automatického přesměrování HTTP → HTTPS v IIS

Použijte následující PowerShell skript pro automatické přesměrování všech HTTP požadavků na HTTPS.

PowerShell
Import-Module WebAdministration

# Povolit přesměrování v IIS
Set-WebConfigurationProperty -Filter "/system.webServer/httpRedirect" -Name "enabled" -Value "True" -PSPath "IIS:SitesDefault Web Site"
Set-WebConfigurationProperty -Filter "/system.webServer/httpRedirect" 
-Name "destination" -Value "https://localhost" -PSPath "IIS:SitesDefault Web Site"
Set-WebConfigurationProperty -Filter "/system.webServer/httpRedirect" -Name "exactDestination" -Value "True" -PSPath "IIS:SitesDefault Web Site"
Set-WebConfigurationProperty -Filter "/system.webServer/httpRedirect" -Name "httpResponseStatus" -Value "Permanent" -PSPath "IIS:SitesDefault Web Site"

# Restart IIS
iisreset

Automatizace celého procesu

Pokud budete používat Azure Key Vault VM Extension a Key Vault bude napojen na DigiCert, bude se certifikát automaticky prodlužovat a synchronizovat do úložiště certifikátů systému Windows Certificate Store. Je však potřeba dořešit nabindování certifikátu v IIS, protože to se samo nestane. Je potřeba udělat několik dalších kroků, aby byl certifikát při změně automaticky přiřazen do IIS.

Níže je uveden skript, který automaticky detekuje změnu certifikátu a provádí potřebné úpravy v IIS. Zajistí automatickou aktualizaci certifikátu ve webovém serveru IIS. Certifikáty budou v úložišti Certificate Store automaticky aktualizované z Azure Key Vault. Skript bude pravidelně kontrolovat, zda byl nový certifikát importován do LocalMachine\My store a zda je třeba tento certifikát přiřadit k bindingu v IIS.

Jak nastavit automatizaci pomocí Scheduled Task a PowerShell skriptů

Nejprve si připravíme PowerShell skript, který provede potřebné akce, jako je získání certifikátu a aktualizace IIS bindingu. PowerShell skript pro automatické připojení certifikátu k IIS bindingu:

Import-Module WebAdministration

# Získání certifikátů, které byly vydány dnes
$certificates = Get-ChildItem -Path Cert:\LocalMachine\My
$today = (Get-Date).Date
$todayCerts = $certificates |
Where-Object { $_.NotBefore.Date -eq $today }
$appid = "{fbb8250d-a9d7-4d41-b7bc-e75b77578802}"

if ($todayCerts.Count -gt 0) {
    # Seřadíme certifikáty podle data vytvoření (nejnovější certifikát bude první)
    $latestCert = $todayCerts |
Sort-Object NotBefore -Descending | Select-Object -First 1

    # Získání thumbprintu z nejnovějšího certifikátu
    $certThumbprint = $latestCert.Thumbprint
    Write-Output "Nový certifikát (dnes vydaný): $certThumbprint"

    # Port pro HTTPS
    $bindingPort = 443
    $hostHeader = "zoner-test-azure.eu"

    # Validace certifikátu k doméně
    $expectedDomain = "zoner-test-azure.eu" # Nahraďte očekávanou doménou
    if ($latestCert.Subject -notmatch "CN=$expectedDomain") {
        Write-Output "❌ Certifikát s otiskem $certThumbprint má nesprávný Subject. Očekáváno: CN=$expectedDomain" -ForegroundColor Red
        return
    }

    # Získání certifikátu podle thumbprintu
    $cert = Get-ChildItem -Path Cert:\LocalMachine\My |
Where-Object { $_.Thumbprint -eq $certThumbprint }

    if ($cert -and $cert.HasPrivateKey) {
        # Získání bindingu z IIS pro daný port a host header
        $binding = Get-WebBinding |
Where-Object { $_.bindingInformation -like "*:$($bindingPort):$hostHeader" }

        # Pokud binding existuje, odstraníme starý binding
        if ($binding) {
            # Pro odstranění bindingu použijeme Remove-WebBinding
            Remove-WebBinding -Name "Default Web Site" -BindingInformation "*:$($bindingPort):$hostHeader" -Protocol "https"
            Write-Output "Starý binding pro $hostHeader byl odstraněn."
} else {
            Write-Output "Binding pro $hostHeader na portu $bindingPort neexistuje."
}

        # Přidání nového bindingu
        # Použijeme New-WebBinding k připojení certifikátu k portu s HostHeader a SslFlags 1 pro SNI
        New-WebBinding -Name "Default Web Site" -Protocol "https" -Port $bindingPort -HostHeader $hostHeader -SslFlags 1

        # Získání nového bindingu
        $binding = Get-WebBinding |
Where-Object { $_.bindingInformation -like "*:$($bindingPort):$hostHeader" }

        # Pokud binding ještě neexistuje, přidáme nový certifikát
        if ($binding) {
            # Použijeme metodu AddSslCertificate pro přiřazení certifikátu k bindingu
            $binding.AddSslCertificate($cert.Thumbprint, "My")
            Write-Output "IIS binding pro $hostHeader byl aktualizován s novým 
certifikátem."
        } else {
            Write-Host "❌ Nepodařilo se přidat nový binding pro $hostHeader."
-ForegroundColor Red
        }
    } else {
        Write-Host "❌ Certifikát s otiskem $certThumbprint neobsahuje privátní klíč, nelze jej použít pro SSL."
-ForegroundColor Red
    }
} else {
    Write-Output "Dnes nebyl vydán žádný nový certifikát."
}

Co tento skript dělá:

  • Kontrola nového certifikátu: Skript zjistí, jestli byl dnes vydán nový certifikát.
  • Získání thumbprintu: Pokud certifikát existuje, získá jeho thumbprint.
  • Validace certifikátu k doméně: Zkontroluje, zda `Subject` certifikátu odpovídá očekávané doméně.
  • Aktualizace IIS bindingu: Pokud certifikát obsahuje private key (což je nutné pro SSL), skript odstraní starý binding na portu 443 a přidá nový s aktualizovaným certifikátem pomocí metody `.AddSslCertificate()`.

Aby tento skript běžel pravidelně a kontroloval změny certifikátu, je třeba nastavit Scheduled Task na serveru, který bude tento skript spouštět například každou hodinu nebo denně. Nastavte tedy v Task Scheduler spouštění tohoto PS skriptu.

Kde najít logy

V případě potíží je užitečné podívat se do logu, co se vlastně děje. Ty najdete zde: Event Log: Microsoft-Windows-CertificateServicesClient-Lifecycle-System/Operational Podrobný log soubor: %windrive%\WindowsAzure\Logs\Plugins\Microsoft.Azure.KeyVault.KeyVaultForWindows\\akvvm_service_.log

Závěr

Tento návod by vám měl napovědět jak zautomatizovat vydávání a následné nasazování TLS certifikátů pro IIS na platformě Windows Server. Pro získání certifikátů jsme použili Azure Key Vault a přímou integraci s CA DigiCert.

Pak certifikát synchronizujeme buď na jiný Azure VM, nebo na on-premise Windows server a pomocí Powershellu přiřazujeme na vytvořený binding v IIS. Je samozřejmě možné použít i jiný postup, než zde uvedený.

Při nastavení opakovaných úloh bude jak získání certifikátu, tak i deploy fungovat plně automaticky a bezstarostně.

Oficiální dokumentace

  1. Azure Key Vault VM Extension for Windows
  2. IIS SSL Certificate Binding
  3. Default MachineKeys folders Windows Server
  4. Azure Key Vault PowerShell Reference
  5. Managed Identity for Azure Resources
  6. IIS PowerShell Cmdlets
Byl tento článek pro vás užitečný?