Skip to content

Instantly share code, notes, and snippets.

@andersosthus
Created February 9, 2016 15:23
Show Gist options
  • Save andersosthus/c483eaf8630219c789de to your computer and use it in GitHub Desktop.
Save andersosthus/c483eaf8630219c789de to your computer and use it in GitHub Desktop.
Describes how to secure your OWIN/ASP.NET 5 endpoints in ServiceFabric without having to log on to each VM and do stuff.
<ApplicationManifest>
...
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="SERVICENAME" ServiceManifestVersion="1.0.0" />
<Policies>
<EndpointBindingPolicy CertificateRef="MyCertificateName" EndpointRef="ServiceEndpoint" />
</Policies>
</ServiceManifestImport>
...
<Certificates>
<EndpointCertificate Name="MyCertificateName" X509FindValue="CERT_THUMBPRINT"/>
</Certificates>
</ApplicationManifest>
# Upload certificate to VMs.
Param
(
[Parameter(Mandatory = $true)]
[string]
$SourceVault,
[Parameter(Mandatory = $true)]
[string]
$ResourceGroup,
[Parameter(Mandatory = $true)]
[string]
$CertificateUrl,
[Parameter(Mandatory = $true)]
[string]
$VMPrefix,
[Parameter(Mandatory = $true)]
[int]
$VMCount
)
$CertStore = "My"
for($i = 0; $i -lt $VMCount; $i++) {
$VMName = "$VMPrefix$i"
Write-Information "Getting VM info for VM $VMName"
$VM = Get-AzureRmVM -ResourceGroupName $ResourceGroup -Name $VMName
$VM = Add-AzureRmVMSecret -VM $VM -SourceVaultId $SourceVault -CertificateStore $CertStore -CertificateUrl $CertificateUrl
Write-Information "Updating VM $VMName"
try
{
Update-AzureRmVM -ResourceGroupName $ResourceGroup -VM $VM
}
Catch
{
$ExceptionMessage = $_.Exception.Message
Write-Warning $ExceptionMessage
}
}
<ServiceManifest>
...
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Type="Input" Protocol="https" Port="443" CertificateRef="MyCertificateName" />
</Endpoints>
</Resources>
</ServiceManifest>
# Before execution make sure to have logged in to Azure (Login-AzureRmAccount)
# and selected the correct subscription (Select-AzureRmSubscription)
Param
(
[Parameter(Mandatory = $true)]
[string]
$CertificateName,
[Parameter(Mandatory = $true)]
[string]
$PfxFile,
[Parameter(Mandatory = $true)]
[string]
$VaultName
)
$resourceId = $null
try
{
$existingKeyVault = Get-AzureRmKeyVault -VaultName $VaultName
$resourceId = $existingKeyVault.ResourceId
Write-Host "Using existing valut $VaultName in $($existingKeyVault.Location)"
}
catch
{
throw "Unable to find KeyVault named $VaultName"
}
$securePass = Read-Host 'Password: ' -AsSecureString
$password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePass))
$PfxPath = Resolve-Path $PfxFile
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $PfxPath, $password
$bytes = [System.IO.File]::ReadAllBytes($PfxPath)
$base64 = [System.Convert]::ToBase64String($bytes)
$jsonBlob = @{
data = $base64
dataType = 'pfx'
password = $password
} | ConvertTo-Json
$contentbytes = [System.Text.Encoding]::UTF8.GetBytes($jsonBlob)
$content = [System.Convert]::ToBase64String($contentbytes)
$secretValue = ConvertTo-SecureString -String $content -AsPlainText -Force
Write-Host "Writing secret to $CertificateName in vault $VaultName"
$secret = Set-AzureKeyVaultSecret -VaultName $VaultName -Name $CertificateName -SecretValue $secretValue
$output = @{};
$output.SourceVault = $resourceId;
$output.CertificateURL = $secret.Id;
$output.CertificateThumbprint = $cert.Thumbprint;
return $output;
@adamt06
Copy link

adamt06 commented May 27, 2016

@MegaMax93 Turns out the script needs modifications because service fabric VMs are in a scale set now.
I added it to my Azure RM template where it deploys the cluster key. I am using the same key vault so it only needed a new entry in vaultCertificates inside the osProfile of the virtual machine scale set.

@LarsKemmann
Copy link

LarsKemmann commented May 28, 2016

Here's an alternative to installCertOnVm.ps1 that works with VM Scale Sets. It assumes that you're adding a certificate to the first key vault referenced by the VMSS; change the commented line to suit your needs:

# Upload certificate to Virtual Machine Scale Set.

Param
(
    [Parameter(Mandatory = $true)]
    [string]
    $SourceVault,

    [Parameter(Mandatory = $true)]
    [string]
    $ResourceGroup,

    [Parameter(Mandatory = $true)]
    [string]
    $CertificateUrl,

    [Parameter(Mandatory = $true)]
    [string]
    $VmssName
)

$CertStore = "My"

Write-Information "Getting Key Vault info for vault $SourceVault"
$Vault = Get-AzureRmKeyVault -VaultName $SourceVault

Write-Information "Getting VMSS info for VMSS $VmssName"
$Vmss = Get-AzureRmVmss -ResourceGroupName $ResourceGroup -VMScaleSetName $VmssName

Write-Information "Updating VMSS $VmssName"

try
{
    $CertConfig = New-AzureRmVmssVaultCertificateConfig -CertificateUrl $CertificateUrl -CertificateStore $CertStore
    $Vmss.VirtualMachineProfile.OsProfile.Secrets[0].VaultCertificates.Add($CertConfig) # NOTE: Change this as needed
    Update-AzureRmVmss -ResourceGroupName $ResourceGroup -Name $VmssName -VirtualMachineScaleSet $Vmss
}
Catch
{
    $ExceptionMessage = $_.Exception.Message
    Write-Warning $ExceptionMessage
}

@shlatchz
Copy link

shlatchz commented Jul 23, 2016

Can it also work on the local cluster?
I have the certificate installed in Current User -> Personal.
Should it be able to find it there? Do I need to change something in the code, because it doesn't work locally for me.

UPDATE
This helped https://matt.kotsenas.com/posts/https-in-service-fabric-web-api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment