diff --git a/src/ConnectedKubernetes/custom/New-AzConnectedKubernetes.ps1 b/src/ConnectedKubernetes/custom/New-AzConnectedKubernetes.ps1 index 90edcc63c082..b9956b42bfe5 100644 --- a/src/ConnectedKubernetes/custom/New-AzConnectedKubernetes.ps1 +++ b/src/ConnectedKubernetes/custom/New-AzConnectedKubernetes.ps1 @@ -349,8 +349,19 @@ function New-AzConnectedKubernetes { #Endregion $RSA = [System.Security.Cryptography.RSA]::Create(4096) - $AgentPublicKey = [System.Convert]::ToBase64String($RSA.ExportRSAPublicKey()) - $AgentPrivateKey = "-----BEGIN RSA PRIVATE KEY-----`n" + [System.Convert]::ToBase64String($RSA.ExportRSAPrivateKey()) + "`n-----END RSA PRIVATE KEY-----" + if ($PSVersionTable.PSVersion.Major -eq 5) { + try { + . "$PSScriptRoot/../utils/RSAHelper.ps1" + $AgentPublicKey = ExportRSAPublicKeyBase64($RSA) + $AgentPrivateKey = ExportRSAPrivateKeyBase64($RSA) + } catch { + Write-Error "Unable to generate RSA keys" + throw + } + } else { + $AgentPublicKey = [System.Convert]::ToBase64String($RSA.ExportRSAPublicKey()) + $AgentPrivateKey = "-----BEGIN RSA PRIVATE KEY-----`n" + [System.Convert]::ToBase64String($RSA.ExportRSAPrivateKey()) + "`n-----END RSA PRIVATE KEY-----" + } $HelmChartPath = Join-Path -Path $ChartExportPath -ChildPath 'azure-arc-k8sagents' if (Test-Path Env:HELMCHART) { diff --git a/src/ConnectedKubernetes/utils/RSAHelper.ps1 b/src/ConnectedKubernetes/utils/RSAHelper.ps1 new file mode 100644 index 000000000000..73bdd98b06ec --- /dev/null +++ b/src/ConnectedKubernetes/utils/RSAHelper.ps1 @@ -0,0 +1,154 @@ +function ExportRSAPrivateKeyBase64{ + param( + [Parameter(Mandatory)] + [System.Security.Cryptography.RSA] + $RSA + ) + process{ + $RSAParams = $RSA.ExportParameters(1) + [byte]$Sequence = 0x30 + [byte[]]$Version =(0x00) + $stream = [System.IO.MemoryStream]::new() + $writer = [System.IO.BinaryWriter]::new($stream) + $writer.Write($Sequence); # SEQUENCE + $innerStream = [System.IO.MemoryStream]::new() + $innerWriter = [System.IO.BinaryWriter]::new($innerStream) + + EncodeIntegerBigEndian $innerWriter $Version + EncodeIntegerBigEndian $innerWriter $RSAParams.Modulus + EncodeIntegerBigEndian $innerWriter $RSAParams.Exponent + EncodeIntegerBigEndian $innerWriter $RSAParams.D + EncodeIntegerBigEndian $innerWriter $RSAParams.P + EncodeIntegerBigEndian $innerWriter $RSAParams.Q + EncodeIntegerBigEndian $innerWriter $RSAParams.DP + EncodeIntegerBigEndian $innerWriter $RSAParams.DQ + EncodeIntegerBigEndian $innerWriter $RSAParams.InverseQ + + $length = ([int]($innerStream.Length)) + EncodeLength $writer $length + $writer.Write($innerStream.GetBuffer(), 0, $length) + + $base64 = [Convert]::ToBase64String($stream.GetBuffer(), 0, ([int]($stream.Length))) + + $offset = 0 + $line_length = 64 + + $sb = [System.Text.StringBuilder]::new() + [void]$sb.AppendLine("-----BEGIN RSA PRIVATE KEY-----") + while ($offset -lt $base64.Length) { + $line_end = [Math]::Min($offset + $line_length, $base64.Length) + [void]$sb.AppendLine($base64.Substring($offset, $line_end - $offset)) + $offset = $line_end + } + + [void]$sb.AppendLine("-----END RSA PRIVATE KEY-----") + + return $sb.ToString() + } +} + +function ExportRSAPublicKeyBase64{ + param( + [Parameter(Mandatory)] + [System.Security.Cryptography.RSA] + $RSA + ) + process{ + $RSAParams = $RSA.ExportParameters(0) + [byte]$Sequence = 0x30 + $stream = [System.IO.MemoryStream]::new() + $writer = [System.IO.BinaryWriter]::new($stream) + $writer.Write($Sequence); # SEQUENCE + $innerStream = [System.IO.MemoryStream]::new() + $innerWriter = [System.IO.BinaryWriter]::new($innerStream) + EncodeIntegerBigEndian $innerWriter $RSAParams.Modulus + EncodeIntegerBigEndian $innerWriter $RSAParams.Exponent + + $length = ([int]($innerStream.Length)) + EncodeLength $writer $length + $writer.Write($innerStream.GetBuffer(), 0, $length) + + $base64 = [Convert]::ToBase64String($stream.GetBuffer(), 0, ([int]($stream.Length))) + + $offset = 0 + $line_length = 64 + + $sb = [System.Text.StringBuilder]::new() + + while ($offset -lt $base64.Length) { + $line_end = [Math]::Min($offset + $line_length, $base64.Length) + [void]$sb.AppendLine($base64.Substring($offset, $line_end - $offset)) + $offset = $line_end + } + + return $sb.ToString() + } +} + +function EncodeLength{ + param( + [System.IO.BinaryWriter]$stream, + [int]$length + ) + process{ + [byte]$bytex80 = 0x80 + if($length -lt 0){ + throw "Length must be non-negative" + } + if($length -lt $bytex80){ + $stream.Write(([byte]$length)) + } + else{ + $temp = $length + $bytesRequired = 0; + while ($temp -gt 0) { + $temp = $temp -shr 8 + $bytesRequired++ + } + + [byte]$byteToWrite = $bytesRequired -bor $bytex80 + $stream.Write($byteToWrite) + $iValue = ($bytesRequired - 1) + [byte]$0ffByte = 0xff + for ($i = $iValue; $i -ge 0; $i--) { + [byte]$byteToWrite = ($length -shr (8 * $i) -band $0ffByte) + $stream.Write($byteToWrite ) + } + } + } +} + +function EncodeIntegerBigEndian{ + param( + [System.IO.BinaryWriter]$stream, + [byte[]]$value, + [bool]$forceUnsigned = $true + ) + process{ + [byte]$Integer = 0x02 + + $stream.Write($Integer); # INTEGER + $prefixZeros = 0 + for ($i = 0; $i -lt $value.Length; $i++) { + if ($value[$i] -ne 0){break} + $prefixZeros++ + } + if(($value.Length - $prefixZeros) -eq 0){ + EncodeLength $stream 1 + $stream.Write(([byte]0)) + } + else{ + [byte]$newByte = 0x7f + if(($forceUnsigned) -AND ($value[$prefixZeros] -gt $newByte)){ + EncodeLength $stream ($value.Length - $prefixZeros +1) + $stream.Write(([byte]0)) + } + else{ + EncodeLength $stream ($value.Length - $prefixZeros) + } + for ($i = $prefixZeros; $i -lt $value.Length; $i++) { + $stream.Write($value[$i]) + } + } + } +}