forked from microsoft/AL-Go-Actions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathReadSecretsHelper.psm1
209 lines (191 loc) · 7.36 KB
/
ReadSecretsHelper.psm1
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'GitHub Secrets come in as plain text')]
Param(
[string] $_gitHubSecrets
)
$script:gitHubSecrets = $_gitHubSecrets | ConvertFrom-Json
$script:escchars = @(' ','!','\"','#','$','%','\u0026','\u0027','(',')','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':',';','\u003c','=','\u003e','?','@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',[char]96,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','{','|','}','~')
. (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve)
function GetAzureCredentialsSecretName {
$settings = $env:Settings | ConvertFrom-Json
if ($settings.PSObject.Properties.Name -eq "AZURE_CREDENTIALSSecretName") {
return $settings.AZURE_CREDENTIALSSecretName
}
else {
return "AZURE_CREDENTIALS"
}
}
function GetAzureCredentials {
$secretName = GetAzureCredentialsSecretName
if ($script:gitHubSecrets.PSObject.Properties.Name -eq $secretName) {
return $script:gitHubSecrets."$secretName"
}
return $null
}
function MaskValue {
Param(
[string] $key,
[string] $value
)
Write-Host "Masking value for $key"
Write-Host "::add-mask::$value"
$val2 = ""
$value.ToCharArray() | ForEach-Object {
$chint = [int]$_
if ($chint -lt 32 -or $chint -gt 126 ) {
$val2 += $_
}
else {
$val2 += $script:escchars[$chint-32]
}
}
if ($val2 -ne $value) {
Write-Host "::add-mask::$val2"
}
Write-Host "::add-mask::$([Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($value)))"
}
function GetGithubSecret {
param (
[string] $secretName,
[switch] $encrypted
)
$secretSplit = $secretName.Split('=')
$envVar = $secretSplit[0]
$secret = $envVar
if ($secretSplit.Count -gt 1) {
$secret = $secretSplit[1]
}
if ($script:gitHubSecrets.PSObject.Properties.Name -eq $secret) {
$value = $script:githubSecrets."$secret"
if ($value) {
MaskValue -key $envVar -value $value
if ($encrypted) {
# Return encrypted string
return (ConvertTo-SecureString -String $value -AsPlainText -Force | ConvertFrom-SecureString)
}
else {
# Return decrypted string
return $value
}
}
}
return $null
}
function GetKeyVaultCredentials {
$creds = $null
$jsonStr = GetAzureCredentials
if ($jsonStr) {
if ($jsonStr -contains "`n" -or $jsonStr -contains "`r") {
throw "Secret for Azure KeyVault Connection ($(GetAzureCredentialsSecretName)) cannot contain line breaks, needs to be formatted as compressed JSON (no line breaks)"
}
try {
$creds = $jsonStr | ConvertFrom-Json
if ($creds.PSObject.Properties.Name -eq 'ClientSecret' -and $creds.ClientSecret) {
# Mask ClientSecret
MaskValue -key 'ClientSecret' -value $creds.ClientSecret
}
# Check thet $creds contains the needed properties
$creds.ClientId | Out-Null
$creds.TenantId | Out-Null
}
catch {
throw "Secret for Azure KeyVault Connection ($(GetAzureCredentialsSecretName)) is wrongly formatted. Needs to be formatted as compressed JSON (no line breaks) and contain at least the properties: clientId, clientSecret, tenantId and subscriptionId."
}
$keyVaultNameExists = $creds.PSObject.Properties.Name -eq 'keyVaultName'
$settings = $env:Settings | ConvertFrom-Json
# If KeyVaultName is defined in settings, use that value
if ($settings.keyVaultName) {
if ($keyVaultNameExists) {
$creds.keyVaultName = $settings.keyVaultName
}
else {
$creds | Add-Member -MemberType NoteProperty -Name 'keyVaultName' -Value $settings.keyVaultName
}
}
elseif (!($keyVaultNameExists)) {
# If KeyVaultName is not defined - return null (i.e. do not use a KeyVault)
$creds = $null
}
}
if ($creds) {
try {
# check that we have access to get secrets from the keyvault by trying to get a dummy secret
GetKeyVaultSecret -secretName 'algodummysecret' -keyVaultCredentials $creds -encrypted | Out-Null
}
catch {
Write-Host "Unable to get secrets from Azure Key Vault. Error was $($_.Exception.Message). Using Github secrets instead."
$creds = $null
}
}
return $creds
}
function GetKeyVaultSecret {
param (
[string] $secretName,
[PsCustomObject] $keyVaultCredentials,
[switch] $encrypted
)
if ($null -eq $keyVaultCredentials) {
return $null
}
ConnectAz -azureCredentials $keyVaultCredentials
$secretSplit = $secretName.Split('=')
$envVar = $secretSplit[0]
$secret = $envVar
if ($secretSplit.Count -gt 1) {
$secret = $secretSplit[1]
}
if ($secret.Contains('_')) {
# Secret name contains a '_', which is not allowed in Key Vault secret names
return $null
}
$value = $null
try {
$keyVaultSecret = Get-AzKeyVaultSecret -VaultName $keyVaultCredentials.keyVaultName -Name $secret
}
catch {
if ($keyVaultCredentials.PSObject.Properties.Name -eq 'ClientSecret') {
throw "Error trying to get secrets from Azure Key Vault. Error was $($_.Exception.Message)"
}
else {
throw "Error trying to get secrets from Azure Key Vault, maybe your Key Vault isn't setup for role based access control?. Error was $($_.Exception.Message)"
}
}
if ($keyVaultSecret) {
if ($encrypted) {
# Return encrypted string
$value = $keyVaultSecret.SecretValue | ConvertFrom-SecureString
}
else {
# Return decrypted string
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($keyVaultSecret.SecretValue)
$value = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[Runtime.InteropServices.Marshal]::FreeBSTR($bstr)
MaskValue -key $envVar -value $value
}
}
return $value
}
function GetSecret {
param (
[string] $secret,
[PSCustomObject] $keyVaultCredentials,
[switch] $encrypted
)
Write-Host "Trying to get the secret ($secret) from the github environment."
$value = GetGithubSecret -secretName $secret -encrypted:$encrypted
if ($value) {
Write-Host "Secret ($secret) was retrieved from the github environment."
}
elseif ($keyVaultCredentials) {
Write-Host "Trying to get the secret ($secret) from Key Vault ($($keyVaultCredentials.keyVaultName))."
$value = GetKeyVaultSecret -secretName $secret -keyVaultCredentials $keyVaultCredentials -encrypted:$encrypted
if ($value) {
Write-Host "Secret ($secret) was retrieved from the Key Vault."
}
}
else {
Write-Host "Could not find secret $secret in Github secrets or Azure Key Vault."
$value = $null
}
return $value
}