Last active
August 17, 2019 19:58
-
-
Save stypr/915af22b4348d57a59ac4cdd8ff39921 to your computer and use it in GitHub Desktop.
How to convert HTTPS Certificates for RDP auth (using Caddy)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# derived from http://stackoverflow.com/questions/40046916/how-to-grant-permission-to-user-on-certificate-private-key-using-powershell | |
param ( | |
[string]$certThumbprint = "NothingToDoHere" | |
) | |
$serviceAccount = 'NETWORK SERVICE' | |
$permissionType = 'Read' | |
try | |
{ | |
Write-Host "Thumbprint: $certThumbprint" | |
#Clear Existing Variables | |
$cert = '' | |
$keyFullPath = '' | |
Write-Host "--------------------------" | |
Write-Host "Server: $env:ComputerName" -ForegroundColor Cyan | |
Write-Host "Finding Certificate..." -ForegroundColor Green | |
#Get Certificate | |
$cert = Get-ChildItem -Path cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq ($certThumbprint -replace '\s','')} | |
If ($cert -ne $null -and $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName -ne $null) | |
{ | |
# Get Location of the machine related keys | |
$keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\"; | |
$keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName; | |
$keyFullPath = $keyPath + $keyName; | |
Write-Host "Found Certificate..." -ForegroundColor Green | |
Write-Host "Granting access to $serviceAccount..." -ForegroundColor Green | |
#Grant Full Control to account listed in $serviceAccount | |
$acl = (Get-Item $keyFullPath).GetAccessControl('Access') #Get Current Access | |
$buildAcl = New-Object System.Security.AccessControl.FileSystemAccessRule($serviceAccount,$permissionType,"Allow") #Build Access Rule | |
$acl.SetAccessRule($buildAcl) #Add Access Rule | |
Set-Acl $keyFullPath $acl #Save Access Rules | |
Write-Host "Access granted to $serviceAccount..." -ForegroundColor Green | |
Write-Host "--------------------------" | |
} | |
Else { | |
Write-Host "Unable to find Certificate that matches thumbprint $certThumbprint or the private key is missing..." -ForegroundColor Red | |
Write-Host "--------------------------" | |
} | |
} | |
catch | |
{ | |
Write-Host "Unable to grant access to $serviceAccount..." -ForegroundColor Yellow | |
Write-Host "--------------------------" | |
throw $_; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python -u | |
#-*- coding: utf-8 -*- | |
__author__ = "Harold Kim" | |
__email__ = "root@stypr.com" | |
import os | |
import sys | |
import time | |
import datetime | |
import hashlib | |
import _winreg | |
def list_installed_certs(): | |
""" List installed Certificates (return type list) """ | |
cert = [] | |
# get sha1sum of installed certficates | |
_cert_installed = [] | |
_cert_directory ='Software\\Microsoft\\SystemCertificates\\MY\\Certificates' | |
_cert_list = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, _cert_directory) | |
i = 0 | |
try: | |
while True: | |
_cert_installed.append([_winreg.EnumKey(_cert_list, i),]) | |
i += 1 | |
except WindowsError: | |
pass | |
# get blobs of installed certificates | |
for i in xrange(len(_cert_installed)): | |
_cert_info = _winreg.OpenKey( | |
_winreg.HKEY_LOCAL_MACHINE, | |
os.path.join(_cert_directory, _cert_installed[i][0]) | |
) | |
j = 0 | |
try: | |
while True: | |
_cert_blob = _winreg.EnumValue(_cert_info, j)[1] | |
_cert_installed[i].append(_cert_blob) | |
j += 1 | |
except WindowsError: | |
pass | |
# get info of installed certificates | |
for i in xrange(len(_cert_installed)): | |
_blob_temp = os.path.join( | |
os.environ['TEMP'], | |
hashlib.sha1(_cert_installed[i][1]).hexdigest() | |
) | |
_file_temp = open(_blob_temp, 'wb') | |
_file_temp.write(_cert_installed[i][1]) | |
_file_temp.close() | |
_cert_result = os.popen("certutil -dump " + _blob_temp).read() | |
# parse_cert_result | |
_cert_notbefore = _cert_result.split("NotBefore: ")[1].split(" ")[0] | |
_cert_notafter = _cert_result.split("NotAfter: ")[1].split(" ")[0] | |
# 2nd hierachy | |
_cert_cn = _cert_result.split("CN=")[2].split(",")[0].split("\n")[0] | |
_cert_sha1sum = _cert_result.split("(sha1):")[1] \ | |
.split("\n")[0].replace(" ", "") | |
if _cert_installed[i][0].lower() == _cert_sha1sum.lower(): | |
cert.append({ | |
'before': time.mktime( | |
datetime.datetime.strptime( | |
_cert_notbefore, "%Y-%m-%d" | |
).timetuple() | |
), | |
'after': time.mktime( | |
datetime.datetime.strptime( | |
_cert_notafter, "%Y-%m-%d" | |
).timetuple() | |
), | |
'CN': _cert_cn, | |
'sha1': _cert_sha1sum.lower(), | |
}) | |
os.remove(_blob_temp) | |
return cert | |
def get_caddy_cert_directory(domain): | |
""" get caddy certificate directory """ | |
for root, dirs, files in os.walk( | |
os.path.join(os.environ['HOMEPATH'], ".caddy")): | |
for _file in files: | |
if _file.endswith("crt") and _file.startswith(domain_name): | |
return root | |
return False | |
def sha1sum_from_openssl(filename): | |
""" parse sha1sum from openssl result """ | |
_cmd = "openssl x509 -in %s -noout -fingerprint" | |
_data = os.popen(_cmd % (filename,)).read() | |
try: | |
_data = _data.split("=")[1].split("\n")[0].replace(":", "").lower() | |
if not _data: | |
return False | |
except: | |
return False | |
return _data | |
def parse_certificate(result, domain_name): | |
for _cert in result: | |
if _cert['CN'] == domain_name: | |
return _cert | |
return False | |
if __name__ == "__main__": | |
domain_name = "your.caddy-domain.tld" | |
# get caddy cert directory | |
caddy_certificate = get_caddy_cert_directory(domain_name) | |
if not caddy_certificate: | |
print("Caddy does not have your certificate!") | |
sys.exit(-1) | |
_installed = parse_certificate(list_installed_certs(), domain_name) | |
_cert = os.path.join(caddy_certificate, domain_name + '.crt') | |
_priv = os.path.join(caddy_certificate, domain_name + '.key') | |
_pfx = os.path.join(caddy_certificate, domain_name + '.pfx') | |
_sha1 = sha1sum_from_openssl(_cert) | |
if _installed: | |
if _sha1 == _installed['sha1']: | |
print("Not required to trigger any events.") | |
sys.exit(-1) | |
# x509 -> pkcs12 | |
_cmd = "openssl pkcs12 -export -out %s -inkey %s -in %s -passout pass:" | |
_convert = os.popen(_cmd % (_pfx, _priv, _cert,)).read() | |
# remove pkcs12 | |
_cmd = "certutil -delstore my %s" | |
_remove = os.popen(_cmd % (domain_name,)).read() | |
# install pkcs12 | |
_cmd = "certutil -p \"\" -importPFX my %s NoProtect" | |
_install = os.popen(_cmd % (_pfx,)).read() | |
print(_install) | |
# apply RDP key | |
_cmd = "wmic /namespace:\\root\cimv2\TerminalServices PATH " | |
_cmd += "Win32_TSGeneralSetting Set SSLCertificateSHA1Hash=\"%s\"" | |
_apply = os.popen(_cmd % (_sha1,)).read() | |
# give ACL to RDP -- refer to rdp.ps1 (Powershell script) | |
_acl = os.popen("Powershell -File rdp.ps1 %s" % (_sha1,)).read() | |
print("Done as expected!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Someone sent me a bug request mail for this. Please update the code with the following: