Update scripts

This commit is contained in:
2025-04-01 12:54:02 -04:00
parent 50d617ec67
commit 9e8e53061e
6 changed files with 1 additions and 685 deletions

View File

@@ -7,7 +7,7 @@ on:
env:
AZURE_WEBAPP_NAME: hutopy-backend-api
DOTNET_VERSION: '8.0.x'
DOTNET_VERSION: '9.0.x'
jobs:
build_and_deploy:

View File

@@ -1,362 +0,0 @@
@description('The location into which your Azure resources should be deployed.')
param location string = resourceGroup().location
@description('Select the type of environment you want to provision. Allowed values are Production, Staging, and Development.')
@allowed([
'Production'
'Staging'
'Development'
])
param environmentName string
@description('A unique suffix to add to resource names that need to be globally unique.')
@maxLength(13)
param resourceNameSuffix string = uniqueString(resourceGroup().id)
@description('The administrator login username for the SQL server.')
param sqlAdministratorUsername string
@secure()
@description('The administrator login password for the SQL server.')
param sqlAdministratorPassword string
@description('The name of the project.')
param projectName string
// Define the environment configuration map.
var environmentConfigurationMap = {
Production: {
environmentAbbreviation: 'prd'
appServicePlan: {
sku: {
name: 'S1'
capacity: 1
}
}
sqlDatabase: {
sku: {
name: 'Standard'
tier: 'Standard'
}
}
}
Staging: {
environmentAbbreviation: 'stg'
appServicePlan: {
sku: {
name: 'B1'
}
}
sqlDatabase: {
sku: {
name: 'Standard'
tier: 'Standard'
}
}
}
Development: {
environmentAbbreviation: 'dev'
appServicePlan: {
sku: {
name: 'B1'
}
}
sqlDatabase: {
sku: {
name: 'Standard'
tier: 'Standard'
}
}
}
}
// Define the names for resources.
var environmentAbbreviation = environmentConfigurationMap[environmentName].environmentAbbreviation
var keyVaultName = 'kv-${projectName}-${environmentAbbreviation}'
var appServiceAppName = 'as-${projectName}-${resourceNameSuffix}-${environmentAbbreviation}'
var appServicePlanName = 'plan-${projectName}-${environmentAbbreviation}'
var logAnalyticsWorkspaceName = 'log-${projectName}-${environmentAbbreviation}'
var applicationInsightsName = 'appi-${projectName}-${environmentAbbreviation}'
var sqlServerName = 'sql-${projectName}-${resourceNameSuffix}-${environmentAbbreviation}'
var sqlDatabaseName = '${projectName}-${environmentAbbreviation}'
// Define the SKUs for each component based on the environment type.
var appServicePlanSku = environmentConfigurationMap[environmentName].appServicePlan.sku
var sqlDatabaseSku = environmentConfigurationMap[environmentName].sqlDatabase.sku
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-10-01' = {
name: logAnalyticsWorkspaceName
location: location
properties: {
sku: {
name: 'PerGB2018'
}
}
}
resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = {
name: keyVaultName
location: location
properties: {
enabledForTemplateDeployment: true
tenantId: subscription().tenantId
accessPolicies: []
sku: {
name: 'standard'
family: 'A'
}
}
}
resource keyVault_ConnectionStringSecret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = {
parent: keyVault
name: 'ConnectionStrings--DefaultConnection'
properties: {
value: 'Server=tcp:${sqlServer.properties.fullyQualifiedDomainName},1433;Initial Catalog=${sqlDatabaseName};Persist Security Info=False;User ID=${sqlAdministratorUsername};Password=${sqlAdministratorPassword};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;'
}
dependsOn: [
sqlDatabase
]
}
resource keyVault_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
scope: keyVault
name: 'keyVaultDiagnosticSettings'
properties: {
workspaceId: logAnalyticsWorkspace.id
logs: [
{
category: 'AuditEvent'
enabled: true
}
]
metrics: [
{
category: 'AllMetrics'
enabled: true
}
]
}
}
resource appServicePlan 'Microsoft.Web/serverfarms@2021-01-15' = {
name: appServicePlanName
location: location
sku: appServicePlanSku
}
resource appServicePlan_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
scope: appServicePlan
name: 'appServicePlanDiagnosticSettings'
properties: {
workspaceId: logAnalyticsWorkspace.id
metrics: [
{
category: 'AllMetrics'
enabled: true
}
]
}
}
resource appServiceApp 'Microsoft.Web/sites@2021-01-15' = {
name: appServiceAppName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
siteConfig: {
healthCheckPath: '/health'
netFrameworkVersion: 'v7.0'
appSettings: [
{
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
value: applicationInsights.properties.ConnectionString
}
{
name: 'KeyVaultUri'
value: keyVault.properties.vaultUri
}
]
}
}
}
resource appServiceApp_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
scope: appServiceApp
name: 'appServiceAppDiagnosticSettings'
properties: {
workspaceId: logAnalyticsWorkspace.id
logs: [
{
category: 'AppServiceHTTPLogs'
enabled: true
}
{
category: 'AppServiceConsoleLogs'
enabled: true
}
{
category: 'AppServiceAppLogs'
enabled: true
}
{
category: 'AppServiceAuditLogs'
enabled: true
}
{
category: 'AppServiceIPSecAuditLogs'
enabled: true
}
{
category: 'AppServicePlatformLogs'
enabled: true
}
]
metrics: [
{
category: 'AllMetrics'
enabled: true
}
]
}
}
resource keyVault_AccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
parent: keyVault
name: 'add'
properties: {
accessPolicies: [
{
tenantId: appServiceApp.identity.tenantId
objectId: appServiceApp.identity.principalId
permissions: {
keys: [
'Get'
]
secrets: [
'Get'
'List'
]
certificates: [
'Get'
'List'
]
}
}
]
}
}
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
name: applicationInsightsName
location: location
kind: 'web'
properties: {
Application_Type: 'web'
WorkspaceResourceId: logAnalyticsWorkspace.id
}
}
resource sqlServer 'Microsoft.Sql/servers@2021-02-01-preview' = {
name: sqlServerName
location: location
properties: {
administratorLogin: sqlAdministratorUsername
administratorLoginPassword: sqlAdministratorPassword
}
}
resource sqlDatabase 'Microsoft.Sql/servers/databases@2021-02-01-preview' = {
parent: sqlServer
name: sqlDatabaseName
location: location
sku: sqlDatabaseSku
}
resource sqlServer_AuditingSettings 'Microsoft.Sql/servers/auditingSettings@2021-11-01-preview' = {
parent: sqlServer
name: 'default'
properties: {
state: 'Enabled'
isAzureMonitorTargetEnabled: true
}
}
resource sqlServer_FirewallRule 'Microsoft.Sql/servers/firewallRules@2021-02-01-preview' = {
parent: sqlServer
name: 'AllowAllWindowsAzureIps'
properties: {
endIpAddress: '0.0.0.0'
startIpAddress: '0.0.0.0'
}
}
resource sqlDatabase_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
scope: sqlDatabase
name: 'sqlDatabaseDiagnosticSettings'
properties: {
workspaceId: logAnalyticsWorkspace.id
logs: [
{
category: 'SQLInsights'
enabled: true
}
{
category: 'AutomaticTuning'
enabled: true
}
{
category: 'QueryStoreRuntimeStatistics'
enabled: true
}
{
category: 'QueryStoreWaitStatistics'
enabled: true
}
{
category: 'Errors'
enabled: true
}
{
category: 'DatabaseWaitStatistics'
enabled: true
}
{
category: 'Timeouts'
enabled: true
}
{
category: 'Blocks'
enabled: true
}
{
category: 'Deadlocks'
enabled: true
}
]
metrics: [
{
category: 'Basic'
enabled: true
}
{
category: 'InstanceAndAppAdvanced'
enabled: true
}
{
category: 'WorkloadManagement'
enabled: true
}
]
}
}
output appServiceAppName string = appServiceApp.name
output appServiceAppHostName string = appServiceApp.properties.defaultHostName
output sqlServerFullyQualifiedDomainName string = sqlServer.properties.fullyQualifiedDomainName
output sqlDatabaseName string = sqlDatabase.name

View File

@@ -1,29 +0,0 @@
# Check if Azure CLI is installed
$azPath = (Get-Command az -ErrorAction SilentlyContinue).Source
if (-not $azPath) {
throw "Azure CLI (az) is not installed. Please install it and try again."
}
# Check if Azure CLI is authenticated
az account show --output none
if ($LASTEXITCODE -ne 0) {
throw "Azure CLI (az) is not authenticated. Please authenticate with Azure CLI and try again."
}
# Check if GitHub CLI is installed
$ghPath = (Get-Command gh -ErrorAction SilentlyContinue).Source
if (-not $ghPath) {
throw "GitHub CLI (gh) is not installed. Please install it and try again."
}
# Check if GitHub CLI is authenticated
gh auth status | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "GitHub CLI (gh) is not authenticated. Please authenticate with GitHub CLI and try again."
}
# Check if Git repo is initialised
git status | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "The Git repository has not been initialised. Please create a new GitHub repository and try again."
}

View File

@@ -1,78 +0,0 @@
Param(
[String]$ProjectName
)
$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$checksScript = Join-Path $scriptRoot "checks.ps1"
try {
. $checksScript
} catch {
Write-Host $_.Exception.Message -ForegroundColor Red
Write-Host "Setup script terminated due to the checks failure." -ForegroundColor Red
exit 1
}
$MissingParameterValues = $false
if (-not $ProjectName) {
$ProjectName = $(gh repo view --json name -q '.name' 2> $null)
if (-not $ProjectName) { $MissingParameterValues = $true }
}
$ScriptParameters = @{
"ProjectName" = $ProjectName
}
Write-Host
Write-Host "This script performs cleanup operations to delete resource groups, Azure AD applications, and purge deleted key vaults associated with a specific project hosted on GitHub. It searches for resources based on the project name and performs the necessary deletion and purging actions. The script leverages the Azure CLI to interact with Azure resources. It aims to facilitate the cleanup process and remove unnecessary resources from your Azure environment."
Write-Host
Write-Host "Parameters:" -ForegroundColor Green
$ScriptParameters | Format-Table -AutoSize
Write-Host
if ($MissingParameterValues) {
Write-Host "Script execution cancelled. Missing parameter values." -ForegroundColor Red
return
}
Write-Host "Warning: This script will perform cleanup operations, including deleting resource groups, Azure AD applications, and purging deleted key vaults starting with the project name '$ProjectName'. Make sure you understand the consequences and have verified the project name before proceeding." -ForegroundColor Red
Write-Host
Write-Host "Disclaimer: Use this script at your own risk. The author and contributors are not responsible for any loss of data or unintended consequences resulting from running this script." -ForegroundColor Yellow
Write-Host
$confirmation = Read-Host "Do you want to continue? (y/N)"
if ($confirmation -ne "y") {
Write-Host "Script execution cancelled." -ForegroundColor Red
return
}
Write-Host "🔍 Searching for Resource Groups..."
$resourceGroups = az group list --query "[?starts_with(name, '$ProjectName')].name" --output tsv
foreach ($rg in $resourceGroups) {
Write-Host "🔥 Deleting: $rg"
az group delete --name $rg --yes > $null 2>&1
}
Write-Host "🔍 Searching for Azure AD Applications..."
$appRegistrations = az ad app list --display-name $ProjectName --query "[].{Name:displayName, AppId:appId}" --output json | ConvertFrom-Json
foreach ($appRegistration in $appRegistrations) {
$appName = $appRegistration.Name
$appId = $appRegistration.AppId
Write-Host "🔥 Deleting: $appName"
az ad app delete --id $appId > $null 2>&1
}
Write-Host "🔍 Searching for Deleted Key Vaults..."
$deletedKeyVaults = az keyvault list-deleted --query "[?starts_with(name, 'kv-$ProjectName')].name" --output tsv
foreach ($vaultName in $deletedKeyVaults) {
Write-Host "🔥 Purging: $vaultName"
az keyvault purge --name $vaultName > $null 2>&1
}
Write-Host "✅ Done"

View File

@@ -1,5 +0,0 @@
{
"Dev": "Development",
"Stg": "Staging",
"Prd": "Production"
}

View File

@@ -1,210 +0,0 @@
Param(
[String]$GitHubOrganisationName,
[String]$GitHubRepositoryName,
[String]$AzureLocation,
[String]$AzureSubscriptionId,
[String]$AzureTenantId,
[ValidateLength(4, 17)]
[String]$ProjectName,
[String]$AzureSqlLogin = "SqlAdmin"
)
$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$checksScript = Join-Path $scriptRoot "checks.ps1"
$environmentsFile = Join-Path $scriptRoot "environments.json"
try {
. $checksScript
} catch {
Write-Host $_.Exception.Message -ForegroundColor Red
Write-Host "Setup script terminated due to the checks failure." -ForegroundColor Red
exit 1
}
$MissingParameterValues = $false
if (-not $GitHubOrganisationName) {
$ownerJson = gh repo view --json owner 2>$null | ConvertFrom-Json
if ($ownerJson -and $ownerJson.owner -and $ownerJson.owner.login) {
$GitHubOrganisationName = $ownerJson.owner.login
}
else {
$MissingParameterValues = $true
}
}
if (-not $GitHubRepositoryName) {
$GitHubRepositoryName = $(gh repo view --json name -q '.name' 2> $null)
if (-not $GitHubRepositoryName) { $MissingParameterValues = $true }
}
if (-not $AzureLocation) {
$AzureLocation = "australiaeast"
}
if (-not $AzureSubscriptionId) {
$AzureSubscriptionId = $(az account show --query id --output tsv 2> $null)
if (-not $AzureSubscriptionId) { $MissingParameterValues = $true }
}
if (-not $AzureTenantId) {
$AzureTenantId = $(az account show --query tenantId --output tsv 2> $null)
if (-not $AzureTenantId) { $MissingParameterValues = $true }
}
if (-not $ProjectName) {
if ($GitHubRepositoryName) {
$ProjectName = $GitHubRepositoryName
}
if (-not $ProjectName) { $MissingParameterValues = $true }
}
$repoUrl = "https://github.com/$GitHubOrganisationName/$GitHubRepositoryName"
$environments = Get-Content -Raw -Path $environmentsFile | ConvertFrom-Json
$ParametersTableData = @{
"AzureLocation" = $AzureLocation
"AzureSubscriptionID" = $AzureSubscriptionId
"AzureTenantID" = $AzureTenantId
"GitHubOrganisationName" = $GitHubOrganisationName
"GitHubRepositoryName" = $GitHubRepositoryName
"ProjectName" = $ProjectName
"AzureSqlLogin" = $AzureSqlLogin
}
Write-Host
Write-Host "This script automates the setup of environments, resources, and credentials for a project hosted on GitHub and deployed to Azure. It creates workload identities in Azure AD, sets up resource groups, and configures environment-specific variables and secrets in the GitHub repository. The script leverages the Azure CLI, GitHub CLI, and GitHub APIs to perform these tasks. It aims to streamline the process of setting up and configuring development, staging, and production environments for the project."
Write-Host
Write-Host "Parameters:" -ForegroundColor Green
$ParametersTableData | Format-Table -AutoSize
if ($MissingParameterValues) {
Write-Host "Script execution cancelled. Missing parameter values." -ForegroundColor Red
exit 1
}
$EnvironmentTableData = foreach ($environment in $environments.PSObject.Properties) {
[PSCustomObject]@{
Abbreviation = $environment.Name
Name = $environment.Value
}
}
Write-Host "Environments:" -ForegroundColor Green
$EnvironmentTableData | Select-Object Name, Abbreviation | Format-Table -AutoSize
Write-Host
Write-Host "Warning: Running this script will perform various operations in your GitHub repository and Azure subscription. Ensure that you have the necessary permissions and understand the consequences. " -ForegroundColor Red
Write-Host
Write-Host "Disclaimer: Use this script at your own risk. The author and contributors are not responsible for any loss of data or unintended consequences resulting from running this script." -ForegroundColor Yellow
Write-Host
$confirmation = Read-Host "Do you want to continue? (y/N)"
if ($confirmation -ne "y") {
Write-Host "Script execution cancelled." -ForegroundColor Red
return
}
Write-Host
function CreateWorkloadIdentity {
param (
$environmentAbbr,
$environmentName
)
# Create Azure AD Application Registration
$applicationRegistrationDetails=$(az ad app create --display-name "$ProjectName$environmentAbbr") | ConvertFrom-Json
# Create federated credentials
$credential = @{
name="$ProjectName$environmentName";
issuer="https://token.actions.githubusercontent.com";
subject="repo:${GitHubOrganisationName}/${GitHubRepositoryName}:environment:$environmentName";
audiences=@("api://AzureADTokenExchange")
} | ConvertTo-Json
$credential | az ad app federated-credential create --id $applicationRegistrationDetails.id --parameters "@-" | Out-Null
$credential = @{
name="$ProjectName";
issuer="https://token.actions.githubusercontent.com";
subject="repo:${GitHubOrganisationName}/${GitHubRepositoryName}:ref:refs/heads/main";
audiences=@("api://AzureADTokenExchange")
} | ConvertTo-Json
$credential | az ad app federated-credential create --id $applicationRegistrationDetails.id --parameters "@-" | Out-Null
return $applicationRegistrationDetails.appId
}
function CreateResourceGroup {
param (
$environmentAbbr,
$appId
)
$resourceGroupId = $(az group create --name "$ProjectName$environmentAbbr" --location $AzureLocation --query id --output tsv)
az ad sp create --id $appId
az role assignment create --assignee $appId --role Contributor --scope $resourceGroupId
}
function CreateEnvironment {
param (
$environmentName
)
$token = gh auth token
$header = @{"Authorization" = "token $token" }
$contentType = "application/json"
$uri = "https://api.github.com/repos/$GitHubOrganisationName/$GitHubRepositoryName/environments/$environmentName"
Invoke-WebRequest -Method PUT -Header $header -ContentType $contentType -Uri $uri
}
function GenerateRandomPassword {
param (
[int]$Length = 16
)
$ValidChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#^_-+=?<>|~".ToCharArray()
$Password = -join ((Get-Random -Count $Length -InputObject $ValidChars) | Get-Random -Count $Length)
return $Password
}
function SetVariables() {
gh variable set AZURE_TENANT_ID --body $AzureTenantId --repo $repoUrl
gh variable set AZURE_SUBSCRIPTION_ID --body $AzureSubscriptionId --repo $repoUrl
gh variable set PROJECT_NAME --body $ProjectName --repo $repoUrl
}
function SetEnvironmentVariablesAndSecrets {
param(
$environmentAbbr,
$environmentName,
$appId
)
gh variable set AZURE_CLIENT_ID --body "$appId" --env $environmentName --repo $repoUrl
gh variable set AZURE_RESOURCE_GROUP_NAME --body "$ProjectName$environmentAbbr" --env $environmentName --repo $repoUrl
gh variable set AZURE_SQL_ADMINISTRATOR_USERNAME --body "$AzureSqlLogin" --env $environmentName --repo $repoUrl
gh secret set AZURE_SQL_ADMINISTRATOR_PASSWORD --body (GenerateRandomPassword) --env $environmentName --repo $repoUrl
}
SetVariables
foreach ($environment in $environments.PSObject.Properties) {
$environmentAbbr = $environment.Name
$environmentName = $environment.Value
CreateEnvironment $environmentName
$appId = CreateWorkloadIdentity $environmentAbbr $environmentName
CreateResourceGroup $environmentAbbr $appId
SetEnvironmentVariablesAndSecrets $environmentAbbr $environmentName $appId
}
Write-Host "✅ Done"