diff --git a/README.md b/README.md index d94534f..ee430a8 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,14 @@ Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers. ## Table of Contents +- [Upgrade broken in v2.43](#upgrade-broken-in-v243) - [Features](#features) - [Installation](#installation) - [Overview](#overview) - [Getting started](#getting-started) - [Detailed guide to getting started with more examples](#detailed-guide-to-getting-started-with-more-examples) - [Wildcard certificates](#wildcard-certificates) +- [ISPConfig](#ispconfig) - [Automating updates](#automating-updates) - [Structure](#structure) - [Server-Types](#server-types) @@ -19,6 +21,7 @@ for automating the process on remote servers. - [Elliptic curve keys](#elliptic-curve-keys) - [Preferred Chain](#preferred-chain) - [Include Root certificate in full chain](#include-root-certificate-in-full-chain) +- [Windows Server and IIS Support](#windows-server-and-iis-support) - [Issues / problems / help](#issues--problems--help) ## Upgrade broken in v2.43 @@ -194,7 +197,7 @@ DNS_DEL_COMMAND=/home/root/getssl/dns_scripts/dns_del_cpanel ``` -### ISPConfig +## ISPConfig There is a need to create a remote user in `ISPConfig` to enable the remote API access. @@ -441,6 +444,89 @@ adding the following line to `getssl.cfg` FULL_CHAIN_INCLUDE_ROOT="true" ``` +## Windows Server and IIS Support + +**System and software requirements**: + +- Windows Server with DNS and IIS services + +- One of + + - WSL Windows Sub for Linux + + - Ubuntu or any other distro + + - gettssl can be installed inside WSL or using `/mnt/` path to windows + + - Bash - gettssl should be installed in Windows + + - Git Bash - + + - Rtools4.0 - + +**WSL** + +- Installing and configuring WSL 2 + + - Add remove Windows features and choose "Windows for sub Linux" + + - Install a distro like Ubuntu or any other Linux platform + + - If newly added to the system a reboot is required to continue + + - wsl --install -d ubuntu + + - Any user will work + + - Copying files to WSL + + - From Windows open `Windows Explorer` and browse to `\\wsl$\Ubuntu\home\user\` and then place the getssl files and folders `.getssl` and `getssl` into users home directory `\\wsl$\Ubuntu\home\user\.getssl .` or in Windows + + - Open `cmd` in Widnows and type\ + `wsl -d Ubuntu /bin/bash /home/UserName/getssl/getssl domain.eu && exit` + + - Using a specific distro if not set as default in WSL then use the `wsl -d distro` command + + **Notes:** + + - While configuring WSL please do check the `/etc/hosts` file if the IP of the domain is correct since it overrides the DNS server. + + - Make sure running version 2. + +**GIT Bash** - MINGW64_NT + +- Install git GIT Bash + +- `"C:\Program Files\Git\bin\bash.exe" --login -i -- path_to/getssl/getssl domain.eu` + +**Rtools Bash** - MSYS_NT + +- Make sure that the path of `\rtools42\usr\bin` in Windows system environment variables is right before `c:\windows\system32\` so that getssl will use the `Rtools` applications instead of Windows applications such as `sort.exe` that crashes or speify full path to sort. + +- `\rtools42\usr\bin\bash.exe \Users\Administrator\getssl\getssl domain.eu 2>&1 1>out.txt` + +**Updating DNS TXT records** + +- Using `PowerShell` to add and delete `_acme-challenge` records + + - dns_add_windows_dnsserver + + - dns_del_windows_dnsserver + + **Notes:** The script supports optional second level `TLDs`. `sub.domain.co.uk` You can update the reqexp `.(co|com).uk` to fit your needs. + +**IIS internet information service** + +- Under folder `other_scripts` you can find a `PowerSheell` script `iis_install_certeficate.ps1` which generates `PFX` certificate to be installed in `IIS` and binds the domains to the `PFX` certificate. + +- WSL + + - `RELOAD_CMD=("powershell.exe -ExecutionPolicy Bypass -File "\\\\wsl$\\Ubuntu\\home\\user\\getssl\\other_scripts\\iis_install_certeficate.ps1" "domain.eu" "IIS SiteName" "\\\\wsl$\\Ubuntu\\home\\user\\ssl\\" "path_to_ssl_dir" )` + +- GIT and Rtools4 Bash + + - `RELOAD_CMD=("powershell.exe /c/Users/Administrator/getssl/other_scripts/iis_install_certeficate.ps1 domain.eu domain path_to_ssl_dir")` + ## Issues / problems / help If you have any issues, please log them at diff --git a/dns_scripts/dns_add_windows_dns_server b/dns_scripts/dns_add_windows_dns_server new file mode 100644 index 0000000..36c29ed --- /dev/null +++ b/dns_scripts/dns_add_windows_dns_server @@ -0,0 +1,39 @@ +#!/bin/bash + +# Windows DNS server using powershell - dnscmd is going to be deprecated +# Using Windows Sublinux for executing windows commands +# dnscmd command will be depricated use powershell instead + +regexp='[A-z0-9]+(\.(co|com))?\.\w+$' + +fulldomain=${1} +# Get root domain api.[domain|.co|.uk] +rootdomain=$(echo "${fulldomain}" | grep -Eo "${regexp}") +# Exlude root domain [api].domain.com +subdomain=$(result=$(echo "${fulldomain}" | grep -Po '(.*)(?=\.[A-z0-9]+(\.(co|com))?\.\w+$)') && if [[ ${#result} -gt 0 ]]; then echo ".${result}"; else echo ""; fi) +token=${2} + +nloop=1 +retries=15 # Sometimes it fails +while [[ ${nloop} -le ${retries} ]]; do + + # Add TXT record + echo "Tries ${nloop} out of ${retries}" + + echo "Adding acme challenge record for ${fulldomain} with token ${token}" + cmd=(powershell.exe Add-DnsServerResourceRecord -DescriptiveText \'"${token}"\' -Name \'"_acme-challenge${subdomain}"\' -Txt -ZoneName \'"${rootdomain}"\' -TimeToLive 0:0:0:1) + echo "${cmd[@]}" + + result_stderr=$({ "${cmd[@]}" ;} 2>&1) + + if [[ ${#result_stderr} -eq 0 ]]; then + break + else + echo "${result_stderr}" + fi + + nloop=$((nloop+1)) + + echo "Sleeping 5 seconds" + sleep 5 +done diff --git a/dns_scripts/dns_del_windows_dns_server b/dns_scripts/dns_del_windows_dns_server new file mode 100644 index 0000000..047be2e --- /dev/null +++ b/dns_scripts/dns_del_windows_dns_server @@ -0,0 +1,39 @@ +#!/bin/bash + +# Windows DNS server using powershell - dnscmd is going to be deprecated +# Using Windows Sublinux for executing windows commands +# dnscmd command will be depricated use powershell instead + +regexp='[A-z0-9]+(\.(co|com))?\.\w+$' + +fulldomain=${1} +# Get root domain api.[domain|.co|.uk] +rootdomain=$(echo "${fulldomain}" | grep -Eo "${regexp}") +# Exlude root domain [api].domain.com +subdomain=$(result=$(echo "${fulldomain}" | grep -Po '(.*)(?=\.[A-z0-9]+(\.(co|com))?\.\w+$)') && if [[ ${#result} -gt 0 ]]; then echo ".${result}"; else echo ""; fi) +token=${2} + +nloop=1 +retries=15 # Sometimes it fails +while [[ ${nloop} -le ${retries} ]]; do + + # Delete TXT record + echo "Tries ${nloop} out of ${retries}" + + echo "Deleting acme challenge record for ${fulldomain} with token ${token}" + cmd=(powershell.exe Remove-DnsServerResourceRecord -RRType TXT -Name \'"_acme-challenge${subdomain}"\' -ZoneName \'"${rootdomain}"\' -RecordData \'"${token}"\' -Force) + echo "${cmd[@]}" + + result_stderr=$({ "${cmd[@]}" ;} 2>&1) + + if [[ ${#result_stderr} -eq 0 ]]; then + break + else + echo "${result_stderr}" + fi + + nloop=$((nloop+1)) + + echo "Sleeping 5 seconds" + sleep 5 +done \ No newline at end of file diff --git a/getssl b/getssl index 7592cc4..20582a9 100755 --- a/getssl +++ b/getssl @@ -284,6 +284,7 @@ # 2021-12-23 Don't use +idnout if dig shows a warning (#688) # 2022-01-06 Support --account-id (#716)(2.46) # 2022-03-09 Support for ISPConfig API +# 2022-05-03 Windows Server and IIS support (2.47) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -292,7 +293,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.46" +VERSION="2.47" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -570,8 +571,8 @@ check_challenge_completion_dns() { # perform validation via DNS challenge ntries=0 check_dns="fail" while [[ "$check_dns" == "fail" ]]; do - if [[ "$os" == "cygwin" ]]; then - check_result=$(nslookup -type=txt "${rr}" "${ns}" \ + if [[ "$os" == "cygwin" || "$os" == "mingw64_nt" || "$os" == "msys_nt" ]]; then + check_result=$(nslookup -type=txt "${rr}." "${ns}" \ | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then @@ -1873,6 +1874,10 @@ get_os() { # function to get the current Operating System os="mac" elif [[ ${uname_res:0:6} == "CYGWIN" ]]; then os="cygwin" + elif [[ ${uname_res:0:10} == "MSYS_NT" ]]; then + os="msys_nt" + elif [[ ${uname_res:0:10} == "MINGW64_NT" ]]; then + os="mingw64_nt" elif [[ ${uname_res:0:5} == "MINGW" ]]; then os="mingw" elif [[ ${uname_res} == "SunOS" ]]; then @@ -2988,7 +2993,7 @@ CERT_FILE="$DOMAIN_DIR/${DOMAIN}.crt" FULL_CHAIN="$DOMAIN_DIR/fullchain.crt" CA_CERT="$DOMAIN_DIR/chain.crt" TEMP_DIR="$DOMAIN_DIR/tmp" -if [[ "$os" == "mingw" ]]; then +if [[ "$os" == "mingw" || "$os" == "mingw64_nt" ]]; then CSR_SUBJECT="//" fi diff --git a/other_scripts/iis_install_certeficate.ps1 b/other_scripts/iis_install_certeficate.ps1 new file mode 100644 index 0000000..74beb25 --- /dev/null +++ b/other_scripts/iis_install_certeficate.ps1 @@ -0,0 +1,95 @@ +# Generate PFX for IIS (Internet Information Service) + +# Load libraries +#Add-Type -AssemblyName 'C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll' +using assembly C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll + +$FullDomain = $args[0] +$DebugPreference = "Continue" +# $DebugPreference="SilentlyContinue" +$IIS_SiteName = $args[1] +$Path = $args[2] +# Files + +$PfxFile = "$Path$FullDomain.pfx" +$CrtFile = "$Path$FullDomain.crt" +$KeyFile = "$Path$FullDomain.key" + +Write-Debug "Generating pfx certificate" +openssl pkcs12 -inkey "$KeyFile" -in "$CrtFile" -password pass:$FullDomain -export -out "$PfxFile" + +# Delete old certificate and install the new PFX Certificate + +# Get all certificates +$Store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine") +$Store.Open("MaxAllowed") + +# Loop over all and delete matching certificate for the current domain + +$Ssc = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + +for ($i = 0; $i -lt $Store.Certificates.Count; $i++) { + + $Item = $Store.Certificates.Item($i) + + if ($Item.subject.Contains($FullDomain)) { + + Write-Debug "Adding $FullDomain certificate for deletion!" + $result=$Ssc.Add($Item) + } +} + +for ($i = 0; $i -lt $Ssc.Count; $i++) { + + Write-Debug "Deleting $FullDomain certificate!" + + $Store.RemoveRange($Ssc.Item($i)) +} + + +# $X509KeyStorageFlags Enums +$X509KeyStorageFlagsExportable = 4 +$X509KeyStorageFlagsPersistKeySet = 16 +$X509KeyStorageFlagsMachineKeySet = 2 + +<# +$X509KeyStorageFlagsDefaultKeySet=0 +$X509KeyStorageFlagsUserKeySet=1 +$X509KeyStorageFlagsUserProtected=8 +$X509KeyStorageFlagsEphemeralKeySet=32 +#> + +# Prepare for loading new certificated +$PFXCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($PfxFile, $FullDomain, + ( + $X509KeyStorageFlagsExportable + + $X509KeyStorageFlagsPersistKeySet + + $X509KeyStorageFlagsMachineKeySet + ) +) + +#Save New Cert +$Store.Add($PFXCert); +$Store.Close(); + +# IIS Binding - Need to rebind the domain to the new certificate +$Manager = New-Object Microsoft.Web.Administration.ServerManager +$Site = $Manager.Sites[$IIS_SiteName] + + +for ($i = 0; $i -lt $Site.Bindings.Count; $i++) { + + $Bind = $Site.Bindings.Item($i); + + $Protocol = $Bind.Protocol + $hostname = $Bind.Host + + if ($Protocol -eq "https") { + Write-Debug "Binding ${protocol}://${hostname}" + $Bind.CertificateHash = $PFXCert.GetCertHash() + } +} + +$Manager.CommitChanges() + +Write-Debug "PFX complete!" \ No newline at end of file