modules/HomeLab.Security/Public/Add-VpnGatewayCertificate.ps1
<#
.SYNOPSIS Uploads a certificate to an Azure VPN Gateway. .DESCRIPTION Uploads a public certificate to an Azure VPN Gateway for P2S VPN authentication. .PARAMETER ResourceGroupName The resource group containing the VPN gateway. .PARAMETER GatewayName The name of the VPN gateway. .PARAMETER CertificateName The name to give the certificate in Azure. .PARAMETER CertificateData The Base64-encoded certificate data. .EXAMPLE Add-VpnGatewayCertificate -ResourceGroupName "MyRG" -GatewayName "MyVPN" -CertificateName "RootCert" -CertificateData $certData .OUTPUTS Hashtable containing success status and message. .NOTES Author: Jurie Smit Date: March 6, 2025 #> function Add-VpnGatewayCertificate { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ResourceGroupName, [Parameter(Mandatory = $true)] [string]$GatewayName, [Parameter(Mandatory = $true)] [string]$CertificateName, [Parameter(Mandatory = $true)] [string]$CertificateData ) # Sanitize certificate name $safeCertName = Get-SanitizedCertName -Name $CertificateName # Log any name changes if ($safeCertName -ne $CertificateName) { Write-LogSafely -Message "Certificate name sanitized from '$CertificateName' to '$safeCertName'" -Level WARNING } Write-LogSafely -Message "Uploading certificate '$safeCertName' to VPN Gateway '$GatewayName' in resource group '$ResourceGroupName'" -Level INFO # Validate certificate data is Base64 encoded try { # Try to decode the Base64 string to ensure it's valid $null = [System.Convert]::FromBase64String($CertificateData) } catch { Write-LogSafely -Message "Certificate data is not valid Base64. Error: $_" -Level ERROR return @{ Success = $false Message = "Invalid certificate data format. Must be Base64 encoded." Error = $_ } } try { # First check if Azure CLI is installed $azCheck = $null try { $azCheck = & az --version 2>&1 } catch { throw "Azure CLI is not installed or not in the PATH. Please install Azure CLI and try again." } if (-not $azCheck) { throw "Azure CLI is not installed or not in the PATH. Please install Azure CLI and try again." } # Check if user is logged in $loginCheck = $null try { $loginCheck = & az account show 2>&1 } catch { Write-LogSafely -Message "Not logged in to Azure. Prompting for login." -Level WARNING } if (-not $loginCheck) { Write-LogSafely -Message "Not logged in to Azure. Prompting for login." -Level WARNING & az login | Out-Null } # Create a temporary file for the certificate data to avoid command injection $tempCertFile = Join-Path -Path $env:TEMP -ChildPath "vpn_cert_$([Guid]::NewGuid().ToString()).txt" [System.IO.File]::WriteAllText($tempCertFile, $CertificateData) try { # Use the Azure CLI to upload the certificate from the file $result = & az network vnet-gateway root-cert create ` --resource-group $ResourceGroupName ` --gateway-name $GatewayName ` --name $safeCertName ` --public-cert-data "@$tempCertFile" if ($LASTEXITCODE -eq 0) { Write-LogSafely -Message "VPN gateway certificate uploaded successfully" -Level INFO return @{ Success = $true Message = "VPN gateway certificate uploaded." CertificateName = $safeCertName } } else { throw "Azure CLI command failed with exit code $LASTEXITCODE" } } finally { # Clean up the temporary file if (Test-Path $tempCertFile) { Remove-Item -Path $tempCertFile -Force } } } catch { Write-LogSafely -Message "Error uploading VPN gateway certificate: $_" -Level ERROR return @{ Success = $false Message = "Failed to upload VPN gateway certificate: $_" Error = $_ } } } |