Skip to content

Commit 8b70a6a

Browse files
committed
Replace Azure SQL Server infrastructure with PostgreSQL Flexible Server using Entra ID authentication
1 parent 4e29c08 commit 8b70a6a

16 files changed

Lines changed: 254 additions & 275 deletions

.github/workflows/_deploy-infrastructure.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ on:
3030
domain_name:
3131
required: true
3232
type: string
33-
sql_admin_object_id:
33+
postgres_admin_object_id:
3434
required: true
3535
type: string
3636
production_service_principal_object_id:
@@ -84,7 +84,7 @@ jobs:
8484
STRIPE_PUBLISHABLE_KEY: ${{ vars.STRIPE_PUBLISHABLE_KEY }}
8585
STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
8686
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
87-
run: bash ./cloud-infrastructure/cluster/deploy-cluster.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location }} ${{ inputs.cluster_location_acronym }} ${{ inputs.sql_admin_object_id }} ${{ inputs.domain_name }} --plan
87+
run: bash ./cloud-infrastructure/cluster/deploy-cluster.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location }} ${{ inputs.cluster_location_acronym }} ${{ inputs.postgres_admin_object_id }} ${{ inputs.domain_name }} --plan
8888

8989
- name: Show DNS Configuration
9090
if: ${{ inputs.domain_name != '' && inputs.domain_name != '-' }}
@@ -149,7 +149,7 @@ jobs:
149149
STRIPE_PUBLISHABLE_KEY: ${{ vars.STRIPE_PUBLISHABLE_KEY }}
150150
STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
151151
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
152-
run: bash ./cloud-infrastructure/cluster/deploy-cluster.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location }} ${{ inputs.cluster_location_acronym }} ${{ inputs.sql_admin_object_id }} ${{ inputs.domain_name }} --apply
152+
run: bash ./cloud-infrastructure/cluster/deploy-cluster.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location }} ${{ inputs.cluster_location_acronym }} ${{ inputs.postgres_admin_object_id }} ${{ inputs.domain_name }} --apply
153153

154154
- name: Refresh Azure Tokens # The previous step may take a while, so we refresh the token to avoid timeouts
155155
uses: azure/login@v2
@@ -158,14 +158,14 @@ jobs:
158158
tenant-id: ${{ inputs.tenant_id }}
159159
subscription-id: ${{ inputs.subscription_id }}
160160

161-
- name: Install Microsoft sqlcmd Utility
162-
run: |
163-
curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc &&
164-
sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/22.04/prod.list)" &&
165-
sudo apt-get update &&
166-
sudo apt-get install -y sqlcmd
161+
- name: Install PostgreSQL Client
162+
run: sudo apt-get update && sudo apt-get install -y postgresql-client
163+
164+
- name: Add PostgreSQL Admin
165+
run: bash ./cloud-infrastructure/cluster/add-postgres-admin.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location_acronym }} ${{ inputs.postgres_admin_object_id }}
167166

168167
- name: Grant Database Permissions
169168
run: |
170169
bash ./cloud-infrastructure/cluster/grant-database-permissions.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location_acronym }} 'account' ${{ steps.deploy_cluster.outputs.ACCOUNT_IDENTITY_CLIENT_ID }}
171170
bash ./cloud-infrastructure/cluster/grant-database-permissions.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location_acronym }} 'back-office' ${{ steps.deploy_cluster.outputs.BACK_OFFICE_IDENTITY_CLIENT_ID }}
171+
bash ./cloud-infrastructure/cluster/grant-database-permissions.sh ${{ inputs.unique_prefix }} ${{ inputs.azure_environment }} ${{ inputs.cluster_location_acronym }} 'main' ${{ steps.deploy_cluster.outputs.MAIN_IDENTITY_CLIENT_ID }}

.github/workflows/_migrate-database.yml

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ jobs:
5252
UNIQUE_PREFIX: ${{ vars.UNIQUE_PREFIX }}
5353
TENANT_ID: ${{ vars.TENANT_ID }}
5454
CLUSTER_RESOURCE_GROUP_NAME: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
55-
SQL_SERVER_NAME: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
56-
SQL_SERVER_FQDN: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}.database.windows.net
55+
POSTGRES_SERVER_NAME: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
56+
POSTGRES_HOST: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}.postgres.database.azure.com
5757

5858
steps:
5959
- name: Checkout Code
@@ -83,15 +83,16 @@ jobs:
8383
working-directory: cloud-infrastructure/cluster
8484
env:
8585
CLUSTER_RESOURCE_GROUP_NAME: ${{ env.CLUSTER_RESOURCE_GROUP_NAME }}
86-
SQL_SERVER_NAME: ${{ env.SQL_SERVER_NAME }}
87-
SQL_DATABASE_NAME: ${{ inputs.database_name }}
86+
POSTGRES_SERVER_NAME: ${{ env.POSTGRES_SERVER_NAME }}
87+
DATABASE_NAME: ${{ inputs.database_name }}
8888
run: bash ./firewall.sh open
8989

9090
- name: Generate Script for Pending Migrations
9191
id: generate-migration-script
9292
working-directory: application
9393
run: |
94-
CONNECTION_STRING="Server=tcp:${{ env.SQL_SERVER_FQDN }},1433;Database=${{ inputs.database_name }};Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=Active Directory Default;"
94+
ENTRA_USER=$(az postgres flexible-server microsoft-entra-admin list --resource-group ${{ env.CLUSTER_RESOURCE_GROUP_NAME }} --server-name ${{ env.POSTGRES_SERVER_NAME }} --query "[0].principalName" --output tsv)
95+
CONNECTION_STRING="Host=${{ env.POSTGRES_HOST }};Database=${{ inputs.database_name }};Username=$ENTRA_USER;Password=$(az account get-access-token --resource-type oss-rdbms --query accessToken --output tsv);Ssl Mode=Require;"
9596
9697
echo "Checking for pending migrations..."
9798
MIGRATION_INFO=$(dotnet ef migrations list \
@@ -143,8 +144,8 @@ jobs:
143144
working-directory: cloud-infrastructure/cluster
144145
env:
145146
CLUSTER_RESOURCE_GROUP_NAME: ${{ env.CLUSTER_RESOURCE_GROUP_NAME }}
146-
SQL_SERVER_NAME: ${{ env.SQL_SERVER_NAME }}
147-
SQL_DATABASE_NAME: ${{ inputs.database_name }}
147+
POSTGRES_SERVER_NAME: ${{ env.POSTGRES_SERVER_NAME }}
148+
DATABASE_NAME: ${{ inputs.database_name }}
148149
run: bash ./firewall.sh close
149150

150151
- name: Upload Migration Script
@@ -239,8 +240,8 @@ jobs:
239240
UNIQUE_PREFIX: ${{ vars.UNIQUE_PREFIX }}
240241
TENANT_ID: ${{ vars.TENANT_ID }}
241242
CLUSTER_RESOURCE_GROUP_NAME: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
242-
SQL_SERVER_NAME: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
243-
SQL_SERVER_FQDN: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}.database.windows.net
243+
POSTGRES_SERVER_NAME: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
244+
POSTGRES_HOST: ${{ vars.UNIQUE_PREFIX }}-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}.postgres.database.azure.com
244245

245246
steps:
246247
- name: Checkout Code
@@ -259,25 +260,23 @@ jobs:
259260
name: migration-script-${{ inputs.azure_environment }}-${{ inputs.cluster_location_acronym }}
260261
path: .
261262

262-
- name: Install Microsoft sqlcmd Utility
263-
run: |
264-
curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc &&
265-
sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/22.04/prod.list)" &&
266-
sudo apt-get update &&
267-
sudo apt-get install -y sqlcmd
263+
- name: Install PostgreSQL Client
264+
run: sudo apt-get update && sudo apt-get install -y postgresql-client
268265

269266
- name: Open Firewall
270267
working-directory: cloud-infrastructure/cluster
271268
env:
272269
CLUSTER_RESOURCE_GROUP_NAME: ${{ env.CLUSTER_RESOURCE_GROUP_NAME }}
273-
SQL_SERVER_NAME: ${{ env.SQL_SERVER_NAME }}
274-
SQL_DATABASE_NAME: ${{ inputs.database_name }}
270+
POSTGRES_SERVER_NAME: ${{ env.POSTGRES_SERVER_NAME }}
271+
DATABASE_NAME: ${{ inputs.database_name }}
275272
run: bash ./firewall.sh open
276273

277274
- name: Apply Migrations
278275
run: |
279-
echo "Applying migrations to ${{ inputs.database_name }} database on ${{ env.SQL_SERVER_FQDN }}..."
280-
sqlcmd -S "tcp:${{ env.SQL_SERVER_FQDN }},1433" -d "${{ inputs.database_name }}" --authentication-method=ActiveDirectoryDefault --exit-on-error -i migration.sql
276+
echo "Applying migrations to ${{ inputs.database_name }} database on ${{ env.POSTGRES_HOST }}..."
277+
ACCESS_TOKEN=$(az account get-access-token --resource-type oss-rdbms --query accessToken --output tsv)
278+
ENTRA_USER=$(az postgres flexible-server microsoft-entra-admin list --resource-group ${{ env.CLUSTER_RESOURCE_GROUP_NAME }} --server-name ${{ env.POSTGRES_SERVER_NAME }} --query "[0].principalName" --output tsv)
279+
PGPASSWORD=$ACCESS_TOKEN psql "host=${{ env.POSTGRES_HOST }} dbname=${{ inputs.database_name }} user='$ENTRA_USER' sslmode=require" -f migration.sql
281280
echo "Migrations applied successfully!"
282281
283282
- name: Display Migration Summary
@@ -290,6 +289,6 @@ jobs:
290289
working-directory: cloud-infrastructure/cluster
291290
env:
292291
CLUSTER_RESOURCE_GROUP_NAME: ${{ env.CLUSTER_RESOURCE_GROUP_NAME }}
293-
SQL_SERVER_NAME: ${{ env.SQL_SERVER_NAME }}
294-
SQL_DATABASE_NAME: ${{ inputs.database_name }}
292+
POSTGRES_SERVER_NAME: ${{ env.POSTGRES_SERVER_NAME }}
293+
DATABASE_NAME: ${{ inputs.database_name }}
295294
run: bash ./firewall.sh close

.github/workflows/cloud-infrastructure.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
shared_location: ${{ vars.STAGING_SHARED_LOCATION }}
3838
cluster_location: ${{ vars.STAGING_CLUSTER_LOCATION }}
3939
domain_name: ${{ vars.STAGING_DOMAIN_NAME }}
40-
sql_admin_object_id: ${{ vars.STAGING_SQL_ADMIN_OBJECT_ID }}
40+
postgres_admin_object_id: ${{ vars.STAGING_POSTGRES_ADMIN_OBJECT_ID }}
4141
production_service_principal_object_id: ${{ vars.PRODUCTION_SERVICE_PRINCIPAL_OBJECT_ID }}
4242

4343
prod1:
@@ -55,5 +55,5 @@ jobs:
5555
shared_location: ${{ vars.PRODUCTION_SHARED_LOCATION }}
5656
cluster_location: ${{ vars.PRODUCTION_CLUSTER1_LOCATION }}
5757
domain_name: ${{ vars.PRODUCTION_DOMAIN_NAME }}
58-
sql_admin_object_id: ${{ vars.PRODUCTION_SQL_ADMIN_OBJECT_ID }}
58+
postgres_admin_object_id: ${{ vars.PRODUCTION_POSTGRES_ADMIN_OBJECT_ID }}
5959
tenant_id: ${{ vars.TENANT_ID }}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
UNIQUE_PREFIX=$1
2+
ENVIRONMENT=$2
3+
CLUSTER_LOCATION_ACRONYM=$3
4+
POSTGRES_ADMIN_OBJECT_ID=$4
5+
6+
CLUSTER_RESOURCE_GROUP_NAME=$UNIQUE_PREFIX-$ENVIRONMENT-$CLUSTER_LOCATION_ACRONYM
7+
POSTGRES_SERVER_NAME=$CLUSTER_RESOURCE_GROUP_NAME
8+
9+
echo "$(date +"%Y-%m-%dT%H:%M:%S") Adding Entra ID group $POSTGRES_ADMIN_OBJECT_ID as admin on PostgreSQL server $POSTGRES_SERVER_NAME"
10+
11+
az postgres flexible-server microsoft-entra-admin create \
12+
--resource-group $CLUSTER_RESOURCE_GROUP_NAME \
13+
--server-name $POSTGRES_SERVER_NAME \
14+
--display-name "PostgreSQL Admins" \
15+
--object-id $POSTGRES_ADMIN_OBJECT_ID \
16+
--type Group

cloud-infrastructure/cluster/deploy-cluster.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ UNIQUE_PREFIX=$1
44
ENVIRONMENT=$2
55
CLUSTER_LOCATION=$3
66
CLUSTER_LOCATION_ACRONYM=$4
7-
SQL_ADMIN_OBJECT_ID=$5
7+
POSTGRES_ADMIN_OBJECT_ID=$5
88
DOMAIN_NAME=$6
99

1010
get_active_version()
@@ -29,7 +29,6 @@ export UNIQUE_PREFIX
2929
export ENVIRONMENT
3030
export LOCATION=$CLUSTER_LOCATION
3131
export DOMAIN_NAME
32-
export SQL_ADMIN_OBJECT_ID
3332
export GOOGLE_OAUTH_CLIENT_ID
3433
export GOOGLE_OAUTH_CLIENT_SECRET
3534
export STRIPE_PUBLISHABLE_KEY
@@ -97,7 +96,7 @@ then
9796
exit 1
9897
fi
9998

100-
# Extract the ID of the Managed Identities, which can be used to grant access to SQL Database
99+
# Extract the ID of the Managed Identities, which can be used to grant access to PostgreSQL databases
101100
ACCOUNT_IDENTITY_CLIENT_ID=$(echo "$cleaned_output" | jq -r '.properties.outputs.accountIdentityClientId.value')
102101
BACK_OFFICE_IDENTITY_CLIENT_ID=$(echo "$cleaned_output" | jq -r '.properties.outputs.backOfficeIdentityClientId.value')
103102
MAIN_IDENTITY_CLIENT_ID=$(echo "$cleaned_output" | jq -r '.properties.outputs.mainIdentityClientId.value')
@@ -106,6 +105,7 @@ then
106105
echo "BACK_OFFICE_IDENTITY_CLIENT_ID=$BACK_OFFICE_IDENTITY_CLIENT_ID" >> $GITHUB_OUTPUT
107106
echo "MAIN_IDENTITY_CLIENT_ID=$MAIN_IDENTITY_CLIENT_ID" >> $GITHUB_OUTPUT
108107
else
108+
. ./add-postgres-admin.sh $UNIQUE_PREFIX $ENVIRONMENT $CLUSTER_LOCATION_ACRONYM $POSTGRES_ADMIN_OBJECT_ID
109109
. ./grant-database-permissions.sh $UNIQUE_PREFIX $ENVIRONMENT $CLUSTER_LOCATION_ACRONYM 'account' $ACCOUNT_IDENTITY_CLIENT_ID
110110
. ./grant-database-permissions.sh $UNIQUE_PREFIX $ENVIRONMENT $CLUSTER_LOCATION_ACRONYM 'back-office' $BACK_OFFICE_IDENTITY_CLIENT_ID
111111
. ./grant-database-permissions.sh $UNIQUE_PREFIX $ENVIRONMENT $CLUSTER_LOCATION_ACRONYM 'main' $MAIN_IDENTITY_CLIENT_ID
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
IP_ADDRESS=$(curl -s https://api.ipify.org)
2-
FIREWALL_RULE_NAME="GitHub Action Workflows - ${SQL_DATABASE_NAME} - Only active when deploying"
2+
FIREWALL_RULE_NAME="github-action-${DATABASE_NAME}"
33

44
if [[ "$1" == "open" ]]
55
then
6-
echo "$(date +"%Y-%m-%dT%H:%M:%S") Add the IP $IP_ADDRESS to the SQL Server firewall on server $SQL_SERVER_NAME for database $SQL_DATABASE_NAME"
7-
az sql server firewall-rule create --resource-group $CLUSTER_RESOURCE_GROUP_NAME --server $SQL_SERVER_NAME --name "$FIREWALL_RULE_NAME" --start-ip-address $IP_ADDRESS --end-ip-address $IP_ADDRESS
6+
echo "$(date +"%Y-%m-%dT%H:%M:%S") Add the IP $IP_ADDRESS to the PostgreSQL server firewall on server $POSTGRES_SERVER_NAME for database $DATABASE_NAME"
7+
az postgres flexible-server firewall-rule create --resource-group $CLUSTER_RESOURCE_GROUP_NAME --server-name $POSTGRES_SERVER_NAME --name "$FIREWALL_RULE_NAME" --start-ip-address $IP_ADDRESS --end-ip-address $IP_ADDRESS
88
else
9-
echo "$(date +"%Y-%m-%dT%H:%M:%S") Delete the IP $IP_ADDRESS from the SQL Server firewall on server $SQL_SERVER_NAME for database $SQL_DATABASE_NAME"
10-
az sql server firewall-rule delete --resource-group $CLUSTER_RESOURCE_GROUP_NAME --server $SQL_SERVER_NAME --name "$FIREWALL_RULE_NAME"
9+
echo "$(date +"%Y-%m-%dT%H:%M:%S") Delete the IP $IP_ADDRESS from the PostgreSQL server firewall on server $POSTGRES_SERVER_NAME for database $DATABASE_NAME"
10+
az postgres flexible-server firewall-rule delete --resource-group $CLUSTER_RESOURCE_GROUP_NAME --server-name $POSTGRES_SERVER_NAME --name "$FIREWALL_RULE_NAME" --yes
1111
fi
Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
UNIQUE_PREFIX=$1
22
ENVIRONMENT=$2
33
CLUSTER_LOCATION_ACRONYM=$3
4-
SQL_DATABASE_NAME=$4
4+
DATABASE_NAME=$4
55
MANAGED_IDENTITY_CLIENT_ID=$5
66

77
CLUSTER_RESOURCE_GROUP_NAME=$UNIQUE_PREFIX-$ENVIRONMENT-$CLUSTER_LOCATION_ACRONYM
88
MANAGED_IDENTITY_NAME=$CLUSTER_RESOURCE_GROUP_NAME-$4
9-
SQL_SERVER_NAME=$CLUSTER_RESOURCE_GROUP_NAME
10-
SQL_SERVER=$SQL_SERVER_NAME.database.windows.net
9+
POSTGRES_SERVER_NAME=$CLUSTER_RESOURCE_GROUP_NAME
10+
POSTGRES_HOST=$POSTGRES_SERVER_NAME.postgres.database.azure.com
1111

1212
cd "$(dirname "${BASH_SOURCE[0]}")"
13-
# Export SQL_DATABASE_NAME for firewall.sh to use
14-
export SQL_DATABASE_NAME=$SQL_DATABASE_NAME
15-
trap '. ./firewall.sh close' EXIT # Ensure that the firewall is closed no matter if other commands fail
13+
14+
export CLUSTER_RESOURCE_GROUP_NAME
15+
export POSTGRES_SERVER_NAME
16+
export DATABASE_NAME
17+
trap '. ./firewall.sh close' EXIT
1618
. ./firewall.sh open
1719

18-
# Convert the ClientId of the Managed Identity to the binary version. The following bash script is equivalent to this PowerShell:
19-
# $SID = "0x" + [System.BitConverter]::ToString(([guid]$SID).ToByteArray()).Replace("-", "")
20-
SID=$(echo $MANAGED_IDENTITY_CLIENT_ID | tr 'a-f' 'A-F' | tr -d '-') # Convert to uppercase and remove hyphens
21-
SID=$(awk -v id="$SID" 'BEGIN {
22-
printf "0x%s%s%s%s\n",
23-
substr(id,7,2) substr(id,5,2) substr(id,3,2) substr(id,1,2),
24-
substr(id,11,2) substr(id,9,2),
25-
substr(id,15,2) substr(id,13,2),
26-
substr(id,17)
27-
}') # Reverse the byte order for the first three sections of the GUID and concatenate
20+
ACCESS_TOKEN=$(az account get-access-token --resource-type oss-rdbms --query accessToken --output tsv)
2821

29-
echo "$(date +"%Y-%m-%dT%H:%M:%S") Granting $MANAGED_IDENTITY_NAME (ID: $SID) in Resource group $CLUSTER_RESOURCE_GROUP_NAME permissions on $SQL_SERVER/$SQL_DATABASE_NAME database"
22+
echo "$(date +"%Y-%m-%dT%H:%M:%S") Granting $MANAGED_IDENTITY_NAME (Client ID: $MANAGED_IDENTITY_CLIENT_ID) permissions on $POSTGRES_HOST/$DATABASE_NAME database"
3023

31-
# Execute the SQL script using mssql-scripter. Pass the script as a heredoc to sqlcmd to allow for complex SQL.
32-
sqlcmd -S $SQL_SERVER -d $SQL_DATABASE_NAME --authentication-method=ActiveDirectoryDefault --exit-on-error << EOF
33-
IF NOT EXISTS (SELECT [name] FROM [sys].[database_principals] WHERE [name] = '$MANAGED_IDENTITY_NAME' AND [type] = 'E')
24+
# PostgreSQL uses roles instead of SQL Server users. Create a role for the managed identity
25+
# and grant it the necessary permissions. The pgaadauth_create_principal function handles
26+
# Entra ID principal creation in Azure Database for PostgreSQL Flexible Server.
27+
ENTRA_USER=$(az postgres flexible-server microsoft-entra-admin list --resource-group $CLUSTER_RESOURCE_GROUP_NAME --server-name $POSTGRES_SERVER_NAME --query "[0].principalName" --output tsv)
28+
PGPASSWORD=$ACCESS_TOKEN psql "host=$POSTGRES_HOST dbname=$DATABASE_NAME user='$ENTRA_USER' sslmode=require" << EOF
29+
DO \$\$
3430
BEGIN
35-
CREATE USER [$MANAGED_IDENTITY_NAME] WITH SID = $SID, TYPE = E;
36-
ALTER ROLE db_datareader ADD MEMBER [$MANAGED_IDENTITY_NAME];
37-
ALTER ROLE db_datawriter ADD MEMBER [$MANAGED_IDENTITY_NAME];
38-
ALTER ROLE db_ddladmin ADD MEMBER [$MANAGED_IDENTITY_NAME];
31+
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$MANAGED_IDENTITY_NAME') THEN
32+
PERFORM pgaadauth_create_principal('$MANAGED_IDENTITY_NAME', false, false);
33+
END IF;
3934
END
40-
GO
35+
\$\$;
36+
37+
GRANT CONNECT ON DATABASE "$DATABASE_NAME" TO "$MANAGED_IDENTITY_NAME";
38+
GRANT USAGE ON SCHEMA public TO "$MANAGED_IDENTITY_NAME";
39+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "$MANAGED_IDENTITY_NAME";
40+
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO "$MANAGED_IDENTITY_NAME";
41+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "$MANAGED_IDENTITY_NAME";
42+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO "$MANAGED_IDENTITY_NAME";
4143
EOF

0 commit comments

Comments
 (0)