<commit_before>﻿<#
    script to add certificate to azure arm AAD key vault
    to enable script execution, you may need to Set-ExecutionPolicy Bypass -Force

    Copyright 2017 Microsoft Corporation

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    # Note: Certificates stored in Key Vault as secrets with content type 'application/x-pkcs12', this is why Set-AzureRmKeyVaultAccessPolivy cmdlet grants -PremissionsToSecrets (rather than -PermissionsToCertificates).
    # You will need 1) application id ($app.ApplicationId), and 2) the password from above step supplied as input parameters to the Template.
    # https://www.sslforfree.com/
    # 170914
    https://blogs.msdn.microsoft.com/tsmatsuz/2017/03/03/azure-rest-api-with-certificate-and-service-principal-by-silent-backend-daemon-service/
    .\azure-rm-aad-add-key-vault.ps1 -certPassword "<PASSWORD>!" -certNameInVault "sfjagilber1cert" -vaultName "sfjagilber1vault" -resourceGroup "certsjagilber" -adApplicationName "sfjagilber1"
#>

[cmdletbinding()]
param(
    [string]$pfxPath = "$($env:temp)\$($adApplicationName).pfx",
    [string]$certPassword, # password that was used to secure the pfx file at the time of export 
    [string]$certNameInVault, # cert name in vault, has to be '^[0-9a-zA-Z-]+$' pattern (digits, letters or dashes only, no spaces)
    [string]$vaultName, # has to be unique?
    [string]$resourceGroup,
    [string]$uri, #  a valid formatted URL, not validated for single-tenant deployments used for identification
    [string]$adApplicationName,
    [switch]$noprompt,
    [string]$location = "eastus",
    [string]$certSubject = $adApplicationName,
    [switch]$adApplicationOnly,
    [switch]$certOnly
)

# authenticate
try
{
    Get-AzureRmResourceGroup | Out-Null
}
catch
{
    try
    {
        Add-AzureRmAccount
    }
    catch [management.automation.commandNotFoundException]
    {
        write-host "installing azurerm sdk. this will take a while..."
        install-module azurerm
        import-module azurerm
        Add-AzureRmAccount
    }
}

if (!(Get-AzureRmResourceGroup -Name $resourceGroup -ErrorAction SilentlyContinue))
{
    New-AzureRmResourceGroup -Name $resourceGroup -location $location
}

if (Get-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -ErrorAction SilentlyContinue)
{
    if ($noprompt -or (read-host "remove existing cert in vault?[y|n]") -imatch "y")
    {
        write-host "removing old cert from existing vault."
        remove-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -Force
    }
}
    
if ((Get-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -ErrorAction SilentlyContinue))
{
    if ($noprompt -or (read-host "remove existing vault?[y|n]") -imatch "y")
    {
        write-host "removing old existing vault."
        remove-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -Force
    }
}

if (!(Get-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -ErrorAction SilentlyContinue))
{
    write-host "creating new azure rm key vault"
    New-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -Location $location -EnabledForDeployment -EnabledForTemplateDeployment
}

if (!$certPassword)
{
    $certPassword = (get-credential).Password
}

$pwd = ConvertTo-SecureString -String $certPassword -Force -AsPlainText

if (!$uri)
{
    $uri = "https://$($env:Computername)/$($adApplicationName)"
}

$cert = $null

if (![IO.File]::Exists($pfxPath))
{
    if(!$certSubject)
    {
        write-host "please provide argument certSubject. exiting"
        exit 1
    }

    if($certs = (Get-ChildItem Cert:\CurrentUser\My | Where-Object Subject -imatch "CN=$($certSubject)"))
    {
        foreach ($cert in $certs)
        {
            if ($noprompt -or (read-host "remove existing cert from local My store?[y|n]") -imatch "y")
            {
                remove-item -Path "Cert:\CurrentUser\My\$($cert.thumbprint)" -Force
            }
        }
    }

    if($certs = (Get-ChildItem Cert:\CurrentUser\Root | Where-Object Subject -imatch "CN=$($certSubject)"))
    {
        foreach ($cert in $certs)
        {
            if ($noprompt -or (read-host "remove existing cert from local Root store?[y|n]") -imatch "y")
            {
                remove-item -Path "Cert:\CurrentUser\Root\$($cert.thumbprint)" -Force
            }
        }
    }

    #$cert = New-SelfSignedCertificate -CertStoreLocation "cert:\currentuser\My" -Subject "CN=$($adApplicationName)" -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider"
    write-host "installing new self signed cert to cert:\currentuser\my"
    $cert = New-SelfSignedCertificate -CertStoreLocation "cert:\currentuser\My" -Subject "CN=$($certSubject)" -KeyExportPolicy Exportable #-Provider "Microsoft Enhanced RSA and AES Cryptographic Provider"
    $cert
    
    Export-PfxCertificate -cert $cert -FilePath $pfxPath -Password $pwd
    write-host "installing new self signed cert to cert:\currentuser\root"
    Import-PfxCertificate -Exportable -Password $pwd -CertStoreLocation Cert:\CurrentUser\Root -FilePath $pfxPath
}

if(!$adApplicationOnly)
{
    ipconfig /flushdns
    start-sleep -Seconds 10
    $azurecert = Import-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -filepath $pfxpath -password $<PASSWORD>
    $azurecert
}

if($certOnly)
{
    return
}

if ($oldapp = Get-AzureRmADApplication -IdentifierUri $uri -ErrorAction SilentlyContinue)
{<commit_msg>fix timing issue for new vault and dns<commit_after>﻿<#
    script to add certificate to azure arm AAD key vault
    to enable script execution, you may need to Set-ExecutionPolicy Bypass -Force

    Copyright 2017 Microsoft Corporation

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    # Note: Certificates stored in Key Vault as secrets with content type 'application/x-pkcs12', this is why Set-AzureRmKeyVaultAccessPolivy cmdlet grants -PremissionsToSecrets (rather than -PermissionsToCertificates).
    # You will need 1) application id ($app.ApplicationId), and 2) the password from above step supplied as input parameters to the Template.
    # https://www.sslforfree.com/
    # 170914
    https://blogs.msdn.microsoft.com/tsmatsuz/2017/03/03/azure-rest-api-with-certificate-and-service-principal-by-silent-backend-daemon-service/
    .\azure-rm-aad-add-key-vault.ps1 -certPassword "<PASSWORD>!" -certNameInVault "sfjagilber1cert" -vaultName "sfjagilber1vault" -resourceGroup "certsjagilber" -adApplicationName "sfjagilber1"
#>

[cmdletbinding()]
param(
    [string]$pfxPath = "$($env:temp)\$($adApplicationName).pfx",
    [string]$certPassword, # password that was used to secure the pfx file at the time of export 
    [string]$certNameInVault, # cert name in vault, has to be '^[0-9a-zA-Z-]+$' pattern (digits, letters or dashes only, no spaces)
    [string]$vaultName, # has to be unique?
    [string]$resourceGroup,
    [string]$uri, #  a valid formatted URL, not validated for single-tenant deployments used for identification
    [string]$adApplicationName,
    [switch]$noprompt,
    [string]$location = "eastus",
    [string]$certSubject = $adApplicationName,
    [switch]$adApplicationOnly,
    [switch]$certOnly
)

$error.Clear()

# authenticate
try
{
    Get-AzureRmResourceGroup | Out-Null
}
catch
{
    try
    {
        Add-AzureRmAccount
    }
    catch [management.automation.commandNotFoundException]
    {
        write-host "installing azurerm sdk. this will take a while..."
        install-module azurerm
        import-module azurerm
        Add-AzureRmAccount
    }
}

if (!(Get-AzureRmResourceGroup -Name $resourceGroup -ErrorAction SilentlyContinue))
{
    New-AzureRmResourceGroup -Name $resourceGroup -location $location
}

if (Get-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -ErrorAction SilentlyContinue)
{
    if ($noprompt -or (read-host "remove existing cert in vault?[y|n]") -imatch "y")
    {
        write-host "removing old cert from existing vault."
        remove-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -Force
    }
}
    
if ((Get-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -ErrorAction SilentlyContinue))
{
    if ($noprompt -or (read-host "remove existing vault?[y|n]") -imatch "y")
    {
        write-host "removing old existing vault."
        remove-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -Force
    }
}

if (!(Get-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -ErrorAction SilentlyContinue))
{
    write-host "creating new azure rm key vault"
    New-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroup -Location $location -EnabledForDeployment -EnabledForTemplateDeployment
}

if (!$certPassword)
{
    $certPassword = (get-credential).Password
}

$pwd = ConvertTo-SecureString -String $certPassword -Force -AsPlainText

if (!$uri)
{
    $uri = "https://$($env:Computername)/$($adApplicationName)"
}

$cert = $null

if (![IO.File]::Exists($pfxPath))
{
    if(!$certSubject)
    {
        write-host "please provide argument certSubject. exiting"
        exit 1
    }

    if($certs = (Get-ChildItem Cert:\CurrentUser\My | Where-Object Subject -imatch "CN=$($certSubject)"))
    {
        foreach ($cert in $certs)
        {
            if ($noprompt -or (read-host "remove existing cert from local My store?[y|n]") -imatch "y")
            {
                remove-item -Path "Cert:\CurrentUser\My\$($cert.thumbprint)" -Force
            }
        }
    }

    if($certs = (Get-ChildItem Cert:\CurrentUser\Root | Where-Object Subject -imatch "CN=$($certSubject)"))
    {
        foreach ($cert in $certs)
        {
            if ($noprompt -or (read-host "remove existing cert from local Root store?[y|n]") -imatch "y")
            {
                remove-item -Path "Cert:\CurrentUser\Root\$($cert.thumbprint)" -Force
            }
        }
    }

    #$cert = New-SelfSignedCertificate -CertStoreLocation "cert:\currentuser\My" -Subject "CN=$($adApplicationName)" -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider"
    write-host "installing new self signed cert to cert:\currentuser\my"
    $cert = New-SelfSignedCertificate -CertStoreLocation "cert:\currentuser\My" -Subject "CN=$($certSubject)" -KeyExportPolicy Exportable #-Provider "Microsoft Enhanced RSA and AES Cryptographic Provider"
    $cert
    
    Export-PfxCertificate -cert $cert -FilePath $pfxPath -Password $pwd
    write-host "installing new self signed cert to cert:\currentuser\root"
    Import-PfxCertificate -Exportable -Password $<PASSWORD> -CertStoreLocation Cert:\CurrentUser\Root -FilePath $pfxPath
}

if(!$adApplicationOnly)
{
    $count = 0
    while($count -lt 5)
    {
        ipconfig /flushdns
        write-host "$($count) -- sleeping 30 seconds while vault is created and registered in dns"
        start-sleep -Seconds 30
        $azurecert = Import-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -filepath $pfxpath -password $<PASSWORD>
        
        if(!$error)
        {
            break
        }

        $count++
        $error.Clear()
    }

    $azurecert
}

if($certOnly)
{
    return
}

if ($oldapp = Get-AzureRmADApplication -IdentifierUri $uri -ErrorAction SilentlyContinue)
{
{'fraction_non_alphanumeric': 0.10812113422764881, 'fraction_numerical': 0.005944252550405655, 'mean_word_length': 3.382259767687434, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 10, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3196657', 'n_tokens_mistral': 3862, 'n_tokens_neox': 3720, 'n_words': 1060}