GetSSL-LetsEncrypt.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
#requires -Modules AcmeSharp, Azure, AzureRM.Websites <#PSScriptInfo .VERSION 1.2 .AUTHOR Lee Holmes & Dani Alonso .GUID 21904884-3b46-4b37-b388-6a9958592401 .DESCRIPTION Script capaz de generar y renovar automaticamente los certificados SSL en sitios alojados en Microsoft Azure. Basado en el script original de Register-LetsEncryptCertificate (by Lee Holmes), realizando una serie de correcciones y mejoras que automatiza el correcto proceso (by Dani Alonso). .MANUAL (proximamente) #> param( [Parameter(Mandatory)] [String] $Domain, [Parameter(Mandatory)] [String] $RegistrationEmail, [Parameter(Mandatory)] [String] $ResourceGroup, [Parameter(Mandatory)] [String] $WebApp, [Switch] $UseUnixFileVerification ) Set-StrictMode -Version Latest function GetSafeFilename { param( $BasePath = ".", $Text, $Extension = ".txt" ) $invalidChars = [IO.Path]::GetInvalidFileNameChars() $invalidCharsRegex = "[" + (-join ($invalidChars | % { [Regex]::Escape($_) })) + "]" $baseFilename = $Text -replace $invalidCharsRegex,'_' $reservedDeviceNames = -split "CON PRN AUX NUL COM1 COM2 COM3 COM4 COM5 COM6 COM7 COM8 COM9 LPT1 LPT2 LPT3 LPT4 LPT5 LPT6 LPT7 LPT8 LPT9" if($baseFilename -in $reservedDeviceNames) { $baseFilename = "_" + $baseFilename } $baseFilename = $baseFilename.Substring(0, [Math]::Min(50, $baseFilename.Length)) $counter = 1 $fileName = $baseFilename + $Extension while(Test-Path (Join-Path $BasePath $fileName)) { $filename = $baseFilename + "_${counter}${Extension}" $counter++ } $fileName.Trim() } function PublishWebsiteFile { param( [Parameter(Mandatory)] $ResourceGroup, [Parameter(Mandatory)] $WebApp, [Parameter(Mandatory)] $PublishSettingsFile, [Parameter(Mandatory)] $RemotePath, [Parameter(Mandatory)] $FileContent ) $RemotePath = $RemotePath.Trim("/\") $publishSettings = [xml] (Get-Content $PublishSettingsFile -Raw) $ftpPublishSettings = $publishSettings.publishData.publishProfile | ? publishMethod -eq MSDeploy $username = $ftpPublishSettings.userName $password = $ftpPublishSettings.userPWD $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password))) $apiBaseUrl = "https://$WebApp.scm.azurewebsites.net/api" Invoke-RestMethod -Uri "$apiBaseUrl/vfs/site/wwwroot/$RemotePath" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo); 'If-Match' = '*'} -Method PUT -Body $FileContent } $outputDirectory = GetSafeFilename -Text $Domain -Extension "" if(-not (Test-Path $outputDirectory)) { $null = New-Item -Type Directory $outputDirectory } Write-Progress "Creating Let's Encrypt registration" if(-not (Get-AcmeVault)) { $null = Initialize-ACMEVault -BaseURI https://acme-v01.api.letsencrypt.org/ } $identifier = -join (([int][char]'a'..[int][char]'z') | Get-Random -Count 10 | % { [char] $_ }) $null = New-ACMERegistration -Contacts mailto:$RegistrationEmail -AcceptTos $null = New-ACMEIdentifier -Dns $domain -Alias $identifier Write-Progress "Receiving challenge" $completedChallenge = Complete-ACMEChallenge -Ref $identifier -Challenge http-01 -Handler manual -Regenerate $challengeAnswer = ($completedChallenge.Challenges | Where-Object { $_.HandlerName -eq "manual" }).Challenge $key = $challengeAnswer.FilePath $target = "$key/index.html" if($UseUnixFileVerification) { $target = $key } Write-Progress "Uploading key and challenge to $domain/$target" ####################################################################### ## ACCION REQUERIDA! Incluir tu credencial de Automation, TenantID y SubscriptionID: $mycredential = <Credential> $mysubscription = <SubscriptionId> $mytenant = <TenantID> ## Fin de area configurable. ####################################################################### $Cred = Get-AutomationPSCredential -Name $mycredential Add-AzureRmAccount -TenantId $mytenant -SubscriptionId $mysubscription -Credential $Cred $tempFile = New-TemporaryFile try { $null = Get-AzureRmWebAppPublishingProfile -ResourceGroupName $ResourceGroup -Name $WebApp -OutputFile $tempFile PublishWebsiteFile -ResourceGroup $ResourceGroup -WebApp $WebApp -PublishSettingsFile $tempFile -RemotePath $target -FileContent $challengeAnswer.FileContent } finally { Remove-Item $tempFile } $counter = 0 Write-Progress "Waiting for challenge verification" -PercentComplete ($counter++) $challenge = Submit-ACMEChallenge -Ref $identifier -ChallengeType http-01 while ($challenge.Status -eq "pending") { Start-Sleep -m 500 Write-Progress "Waiting for challenge verification" -PercentComplete ($counter++) $challenge = Update-ACMEIdentifier -Ref $identifier } if($challenge.Status -eq "valid") { $rawPassword = -join (([int][char]'a'..[int][char]'z') | Get-Random -Count 20 | % { [char] $_ }) $certIdentifier = -join (([int][char]'a'..[int][char]'z') | Get-Random -Count 10 | % { [char] $_ }) New-ACMECertificate -Identifier $identifier -Alias $certIdentifier -Generate $certificateInfo = Submit-ACMECertificate -Ref $certIdentifier Write-Progress "Waiting for IssuerSerialNumber to be issued" while(-not ((Test-Path variable:\certificate) -or $certificateInfo.IssuerSerialNumber)) { Start-Sleep -m 500 $certificateInfo = Update-ACMECertificate -Ref $certIdentifier } $outputFile = Join-Path $pwd cert1-all.pfx $null = Get-ACMECertificate -Ref $certIdentifier -ExportPkcs12 $outputFile -CertificatePassword $rawPassword Get-Item $outputFile New-AzureRmWebAppSSLBinding -ResourceGroupName $ResourceGroup -WebAppName $WebApp -CertificateFilePath $outputFile -CertificatePassword $rawPassword -Name $Domain } else { Write-Error (("Certificate generation failed. Status is '{0}', can't continue as it is not 'valid'. " + "Let's Encrypt could not retrieve the expected content from '$domain/$target'") -f $challenge.Status) $challenge } |