Skip to content

Instantly share code, notes, and snippets.

@iarovyi
Created April 24, 2018 07:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iarovyi/c31b34959c1cadaea462327dcdc0df1a to your computer and use it in GitHub Desktop.
Save iarovyi/c31b34959c1cadaea462327dcdc0df1a to your computer and use it in GitHub Desktop.
<#
I) Sign executable:
.\Signing-Utilities.ps1 -CommaSeparatedFilesToSign "D:\FilesToSign\one.exe,D:\FilesToSign\two.exe"
II) Upload or update signing key:
Initialize-AWSDefaults -ProfileName !!!!!!!!!!!!!!!!! -Region eu-west-1 #Different profile for production
. .\Signing-Utilities.ps1
UploadSigningKey -SigningKeyPath "C:\Users\s.larovyi\Desktop\KMS\testKey.pfx" -Password "secret"
List of saved values: https://eu-west-1.console.aws.amazon.com/ec2/v2/home?region=eu-west-1#Parameters:sort=Name
#>
param(
[string]$CommaSeparatedFilesToSign = ""
)
function CreateSecret([string]$Name, [string]$Value, [string]$Description = " "){
function NewKmsKey($Name, $Value, $Description, $Alias, [bool]$SandboxOnly = $false){
#policy that allows the root deployments access to the key
$iamUsers = @{ 'dev' = '!!!!!!!!!!!!!!!!!'; 'sandbox' = '!!!!!!!!!!!!!!!!!'; 'production' = '!!!!!!!!!!!!!!!!!' };
$roles = @{
'sandbox' = '!!!!!!!!!!!!!!!!!';
'xx' = '!!!!!!!!!!!!!!!!!';
'teamcity' = 'teamcity-build-agent';
'teamcityServiceAccount' = 'serviceAccount-TeamCity';
};
$decryptRole = if($SandboxOnly){ $roles.sandbox }else{ $roles.xx }
$iamUser = if($SandboxOnly){ $iamUsers.sandbox }else{ $iamUsers.production }
Write-Host "Using $($iamUser) user and $($decryptRole) role"
$policy = '
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::'+ $iamUser +':root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow Decryption",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::'+ $iamUser +':role/' + $decryptRole + '"
},
"Action": "kms:Decrypt",
"Resource": "*"
}
]
}';
#"AWS": "arn:aws:iam::'+ $iamUsers.production +':role/' + $roles.teamcity + '",
#"AWS": "arn:aws:iam::'+ $iamUsers.production +':role/' + $roles.teamcityServiceAccount + '"
Write-Host "Policy for new KMS Key: $($policy)"
#create kms key, assign an alias and add the value to ssm
$newKey = New-KMSKey -Description $Description -Policy $policy | %{
#http://docs.aws.amazon.com/powershell/latest/reference/items/New-KMSAlias.html
New-KMSAlias -AliasName "alias/$($Alias.Trim().ToLower())" -TargetKeyId $_.KeyId
Write-SSMParameter -KeyId $_.KeyId -Description $Description -Name $Name.Trim().ToLower() -Type SecureString -Value $Value.Trim()
}
}
#Initialize-AWSDefaults -ProfileName !!!!!!!!!!!!!!!!! -Region eu-west-1
$isSandboxProfile = (Get-AWSCredentials -ListProfiles).IndexOf("!!!!!!!!!!!!!!!!!") -ne -1;
NewKmsKey -Name $Name -Value $Value -Description $Description -Alias $Name -SandboxOnly $isSandboxProfile
}
function GetSecret ([string]$Name) {
return (Get-SSMParameterValue -Name $Name.Trim().ToLower() -Region eu-west-1 -WithDecryption $true).Parameters[0].Value;
}
function HasSecret([string]$Name){
function GetKmsKey($Name) { Get-KMSKey -KeyId "alias/$($Name.Trim().ToLower())" }
return (GetKmsKey $Name) -ne $null;
}
function DeleteSecret([string]$Name){
$realName = $Name.Trim().ToLower();
$alias = "alias/$($realName)";
Remove-SSMParameter -Name $realName -Force
Write-Host $alias
Remove-KMSAlias -AliasName $alias -Force
}
function UploadSecretFile([string]$Name, [string]$Path, [string]$Description = " "){
$bytes = Get-Content $Path -Encoding Byte
$value = [System.Convert]::ToBase64String($bytes);
CreateSecret -Name $Name -Value $value -Description $Description
}
function DownloadSecretFile([string]$Name, [string] $PathToSave){
$stringValue = GetSecret -Name $Name;
$bytes = [System.Convert]::FromBase64String($stringValue);
[System.IO.File]::WriteAllBytes($PathToSave,$bytes)
}
function ConvertBinaryFileToTextFile([string]$BinaryFile, [string] $TextFile){
$bytes = Get-Content $BinaryFile -Encoding Byte
$value = [System.Convert]::ToBase64String($bytes);
$value | Out-File -Filepath $TextFile
}
function ConvertTextFileToBinaryFile([string] $TextFile, [string]$BinaryFile){
$stringValue = Get-Content $TextFile
$bytes = [System.Convert]::FromBase64String($stringValue);
[System.IO.File]::WriteAllBytes($BinaryFile,$bytes)
}
function Sign([string]$ExecutablePath, [string]$SigningKeyPath, [string]$Password){
if ([string]::IsNullOrEmpty($Password)) { throw [System.IO.InvalidDataException] "Empty certificate password" }
if (!(Test-Path $ExecutablePath)) { throw [System.ArgumentException] "Executable path is incorrect: '${$ExecutablePath}'" }
if (!(Test-Path $SigningKeyPath)) { throw [System.ArgumentException] "Signing key path is incorrect: '${$SigningKeyPath}'" }
if ([IO.Path]::GetExtension($SigningKeyPath) -ne ".pfx"){ throw [System.ArgumentException] "Signing key file should be 'pfx' file: '${$SigningKeyPath}'" }
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($SigningKeyPath, $Password)
if($Cert -eq $null)
{
throw [System.IO.InvalidDataException] "Incorrect certificate"
}
Set-AuthenticodeSignature -FilePath $ExecutablePath -Certificate $Cert -ErrorAction Stop
Write-Host "File '$($ExecutablePath)' has been signed with '$($SigningKeyPath)'. You may see some not important error in console if you use test certificate.";
}
function SignFiles([string] $CommaSeparatedFilesToSign){
$files = $CommaSeparatedFilesToSign -split ','
$signingKeyPath = join-path (Resolve-Path .\).Path "key.pfx";
$password = GetSecret -Name "SigningKeyPassword";
DownloadSecretFile -Name "SigningKey" -PathToSave $signingKeyPath
try {
foreach($fileToSign in $files){
Sign -ExecutablePath $fileToSign -SigningKeyPath $signingKeyPath -Password $password
}
}
finally {
Remove-Item $signingKeyPath
}
}
function UploadSigningKey ([string]$SigningKeyPath, [string]$Password) {
$fileKey = "SigningKey";
$passwordKey = "SigningKeyPassword";
if (HasSecret -Name $fileKey) {
DeleteSecret -Name $fileKey
DeleteSecret -Name $passwordKey
}
UploadSecretFile -Name $fileKey -Path $SigningKeyPath -Description "signing key"
CreateSecret -Name $passwordKey -Value $Password -Description "signing key password"
}
Write-Host "Signing files: '$($CommaSeparatedFilesToSign)' with Version $(3) of 'Signing-Utilities.ps1'"
Write-Host "Roles assigned to machine:"
(Get-AWSCredentials -ListProfiles) | Write-Host
#Initialize-AWSDefaults -ProfileName !!!!!!!!!!!!!!!!! -Region eu-west-1
#Write-Host "Log in as !!!!!!!!!!!!!!!!!"
if (![string]::IsNullOrEmpty($CommaSeparatedFilesToSign)) {
SignFiles -CommaSeparatedFilesToSign $CommaSeparatedFilesToSign
} else {
Write-Host "No files specified for signing"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment