Skip to content

Commit 72c15be

Browse files
author
Mike Swantek
committed
post release updates for process steps and code break fixes and hardening
1 parent c0528a4 commit 72c15be

File tree

8 files changed

+84
-45
lines changed

8 files changed

+84
-45
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ For the first attempt, the lowest-risk path is to keep Fabric and Purview disabl
6565
| PostgreSQL mirroring | PostgreSQL enabled in the deployment with `postgreSqlNetworkIsolation = false`, then follow the post-deploy mirror steps | Database deploys, but mirroring is not completed |
6666
| Private networking | `networkIsolation = true` and enough deployment time for private endpoint provisioning | Deployment takes longer and is harder to troubleshoot if other prerequisites are not already stable |
6767

68+
> **Purview note:** If you enable Purview integration, the identity running `azd` must have **Purview Collection Admin** (or equivalent) on the target collection. To ensure a collection is created or resolved, set `purviewCollectionName` so automation captures `PURVIEW_COLLECTION_ID` and the scan can be assigned.
69+
6870
### Choose Your Starting Path
6971

7072
| Goal | Recommended path |
@@ -110,7 +112,7 @@ Follow the deployment guide to deploy this solution to your own Azure subscripti
110112
111113
1. Run `azd auth login` and confirm the target subscription with `az account show`
112114
2. Create a new environment and set `AZURE_SUBSCRIPTION_ID` and `AZURE_LOCATION`
113-
3. Review `infra/main.bicepparam`, especially `principalId`, `aiSearchAdditionalAccessObjectIds`, `fabricCapacityPreset`, `fabricWorkspacePreset`, `fabricCapacityAdmins`, `purviewAccountResourceId`, `networkIsolation`, `postgreSqlNetworkIsolation`, and `postgreSqlAllowAzureServices`
115+
3. Review `infra/main.bicepparam`, especially `principalId`, `aiSearchAdditionalAccessObjectIds`, `fabricCapacityPreset`, `fabricWorkspacePreset`, `fabricCapacityAdmins`, `purviewAccountResourceId`, `purviewCollectionName`, `networkIsolation`, `postgreSqlNetworkIsolation`, and `postgreSqlAllowAzureServices`
114116
4. Run `azd up`
115117
5. Follow [docs/post_deployment_steps.md](./docs/post_deployment_steps.md) to verify the deployment
116118

docs/deploymentguide.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ To deploy this solution accelerator, ensure you have access to an [Azure subscri
3737
| **Microsoft Fabric** | Access to create F8 capacity and workspace, OR existing Fabric capacity ID |
3838
| **Microsoft Purview** | Existing tenant-level Purview account resource ID |
3939

40+
> **Purview requirement:** The identity running `azd` must have **Purview Collection Admin** (or equivalent) on the target collection. If the collection cannot be created or resolved, scan automation will skip collection assignment.
41+
4042
### Region Availability
4143

4244
Check [Azure Products by Region](https://azure.microsoft.com/en-us/explore/global-infrastructure/products-by-region/) to ensure the following services are available in your target region:
@@ -164,6 +166,7 @@ Edit `infra/main.bicepparam` or set environment variables:
164166
| Parameter | Description | Example |
165167
|-----------|-------------|---------|
166168
| `purviewAccountResourceId` | Resource ID of existing Purview account | `/subscriptions/.../Microsoft.Purview/accounts/...` |
169+
| `purviewCollectionName` | Optional. Purview collection name to create or resolve for scans. If blank, scripts create `collection-<env name>`. | `ai-prod-collection` |
167170
| `fabricCapacityPreset` | Fabric capacity preset: `create`, `byo`, or `none` | `create` |
168171
| `fabricWorkspacePreset` | Fabric workspace preset: `create`, `byo`, or `none` | `create` |
169172
| `fabricCapacitySku` | Fabric capacity SKU (only used when `fabricCapacityPreset=create`) | `F8` (default) |
@@ -177,6 +180,11 @@ Edit `infra/main.bicepparam` or set environment variables:
177180
# (Edit infra/main.bicepparam)
178181
# param purviewAccountResourceId = "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Purview/accounts/<account-name>"
179182

183+
# Example: Set Purview collection (optional)
184+
# (Edit infra/main.bicepparam)
185+
# param purviewCollectionName = "ai-prod-collection"
186+
# Leave blank to auto-create collection-<env name>
187+
180188
# Example: Disable all Fabric automation
181189
# (Edit infra/main.bicepparam)
182190
# var fabricCapacityPreset = 'none'

docs/post_deployment_steps.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ If the connection fails, verify RBAC roles are assigned (see Troubleshooting sec
149149

150150
If `purviewCollectionName` is left empty in [infra/main.bicepparam](../infra/main.bicepparam), the automation now uses `collection-<AZURE_ENV_NAME>`.
151151

152+
If the identity running `azd` does not have **Purview Collection Admin** (or equivalent) on the target collection, the Purview scripts will warn and skip collection, datasource, and scan steps. Grant the role, then rerun the Purview scripts.
153+
152154
If you need to rerun the Purview steps after provisioning:
153155

154156
```powershell

docs/postgresql_mirroring.md

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ This is the most common flow when you run `azd up` from a non-VNet machine. The
3434

3535
### Public Access Enabled
3636

37-
Use this path when the PostgreSQL server has `publicNetworkAccess=Enabled`. In this repo, that corresponds to `postgreSqlNetworkIsolation = false`.
37+
Follow this path when the PostgreSQL server has `publicNetworkAccess=Enabled`. In this repo, that corresponds to `postgreSqlNetworkIsolation = false`.
3838

3939
Recommended deployment settings for this path:
4040

@@ -74,7 +74,7 @@ If the database or login fails, confirm `postgreSqlAllowAzureServices = true` (o
7474

7575
### Private Network or Private Endpoint
7676

77-
Use this path when the PostgreSQL server is private-only or Fabric cannot reach it over public networking.
77+
Follow this path when the PostgreSQL server is private-only or Fabric cannot reach it over public networking.
7878

7979
You must supply a Fabric VNet gateway ID for the connection flow in this mode. The repo may add a gateway option in a future update, but today you need to bring your own gateway and set `fabricPostgresGatewayId` before creating the connection.
8080

@@ -85,62 +85,40 @@ You must supply a Fabric VNet gateway ID for the connection flow in this mode. T
8585

8686
### What to Do First
8787

88-
If you just need the mirror working with the fewest steps, follow the **Public Access Enabled** flow above.
88+
If you want the shortest path to a working mirror, follow the **Public Access Enabled** flow above.
8989

9090
If you are intentionally staying private for now, skip mirror creation for this provisioning test and continue validating the rest of the deployment.
9191

9292
## Recommended Repo Flow
9393

94-
In this repo, mirroring should be treated as a deliberate follow-up step after the main deployment completes.
94+
In this repo, mirroring is prepared during postprovision and only needs a short manual follow-up after the main deployment completes.
9595

9696
That means:
9797

98-
1. `azd up` deploys the infrastructure and core postprovision automation.
98+
1. `azd up` deploys the infrastructure and runs the mirroring prep automation.
9999
2. PostgreSQL mirroring is not a required same-run success criterion.
100-
3. If you want mirroring, run it afterward from a runner that can actually reach PostgreSQL, Key Vault, and Fabric.
100+
3. The only required follow-up is a short manual Fabric registration step (see below).
101101

102102
The cleanest sequence is:
103103

104104
1. Run `azd up`.
105105
2. Validate the deployment with [post_deployment_steps.md](./post_deployment_steps.md).
106-
3. Connect to the deployed VM or another runner with PostgreSQL network reachability.
107-
4. Run the mirroring follow-up flow, or use the manual steps above if you are not on the VNet.
106+
3. Temporarily enable Key Vault public access (if needed) to retrieve the Fabric user secret.
107+
4. Register the PostgreSQL connection in Fabric and create the mirror.
108108
5. Verify the Fabric connection and mirrored database.
109109

110110
Running from the deployed VM is usually the least fragile option because it avoids local DNS, firewall, VPN, and endpoint-security issues.
111111

112-
### Follow-Up Wrapper
112+
### Manual Follow-Up (Required)
113113

114-
If you want the repo-managed sequence, run:
114+
After `azd up`, no additional scripts are required. Complete these manual steps:
115115

116-
```powershell
117-
pwsh -NoProfile -File .\scripts\automationScripts\FabricWorkspace\mirror\run_postgresql_mirroring_followup.ps1
118-
```
119-
120-
That wrapper runs, in order:
121-
122-
1. `test_postgresql_mirroring_prereqs.ps1`
123-
2. `prepare_postgresql_for_mirroring.ps1`
124-
3. `create_postgresql_mirror.ps1`
125-
126-
### Preflight First
127-
128-
Before attempting mirroring from a VM or any other runner, use the read-only preflight:
129-
130-
```powershell
131-
pwsh -NoProfile -File .\scripts\automationScripts\FabricWorkspace\mirror\test_postgresql_mirroring_prereqs.ps1
132-
```
133-
134-
It checks the things that usually break the flow:
135-
136-
1. `az` and `azd` availability
137-
2. Azure sign-in
138-
3. required `azd` environment values
139-
4. DNS resolution for PostgreSQL
140-
5. TCP connectivity to PostgreSQL on `5432`
141-
6. Fabric token acquisition
116+
1. Temporarily enable Key Vault public access (if it is private).
117+
2. Retrieve the Fabric user secret from Key Vault.
118+
3. Register the PostgreSQL connection in Fabric.
119+
4. Create the mirror in Fabric and validate sync.
142120

143-
If preflight fails, fix the runner first instead of continuing into SQL prep or Fabric connection creation.
121+
If you need to troubleshoot connectivity from a runner, use the preflight script as a diagnostic, but it is no longer required for the normal flow.
144122

145123
## Automation status
146124

infra/main.bicepparam

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using './main.bicep'
1+
using './main.bicep'
22

33
// ========================================
44
// REQUIRED INPUTS
@@ -205,7 +205,7 @@ param containerAppsList = [
205205
]
206206

207207
param vmAdminPassword = readEnvironmentVariable('VM_ADMIN_PASSWORD', '$(secretOrRandomPassword)')
208-
param vmSize = 'Standard_D2s_v3'
208+
param vmSize = 'Standard_D2s_v4'
209209

210210
// ========================================
211211
// FABRIC CAPACITY PARAMETERS
@@ -244,9 +244,8 @@ param fabricWorkspaceName = '' // optional (helpful for naming/UX)
244244
// Fabric capacity SKU.
245245
param fabricCapacitySku = 'F8'
246246

247-
// Fabric capacity admin members (email addresses or object IDs).
248-
var fabricAdminValue = readEnvironmentVariable('fabricCapacityAdmins', '')
249-
param fabricCapacityAdmins = empty(fabricAdminValue) ? [] : split(fabricAdminValue, ',')
247+
// Fabric capacity admin members (UPN emails preferred).
248+
param fabricCapacityAdmins = []
250249

251250
// ========================================
252251
// PURVIEW PARAMETERS (Optional)

scripts/automationScripts/FabricPurviewAutomation/create_purview_collection.ps1

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ function Resolve-PurviewFromResourceId([string]$resourceId) {
114114
}
115115
}
116116

117+
function Test-PurviewCollectionAdmin([string]$endpoint, [hashtable]$headers) {
118+
try {
119+
Invoke-SecureRestMethod -Uri "$endpoint/account/collections?api-version=2019-11-01-preview" -Headers $headers -Method Get -ErrorAction Stop | Out-Null
120+
return $true
121+
} catch {
122+
Warn "Purview collection access check failed. Ensure the current identity has Purview Collection Admin on the target collection."
123+
return $false
124+
}
125+
}
126+
117127
function Get-DefaultPurviewCollectionName() {
118128
$environmentName = $env:AZURE_ENV_NAME
119129
if (-not $environmentName) { $environmentName = Get-AzdEnvValue -key 'AZURE_ENV_NAME' }
@@ -198,6 +208,11 @@ if (-not $purviewToken) { Fail 'Failed to acquire Purview access token' }
198208
$purviewHeaders = New-SecureHeaders -Token $purviewToken
199209

200210
$endpoint = "https://$purviewAccountName.purview.azure.com"
211+
if (-not (Test-PurviewCollectionAdmin -endpoint $endpoint -headers $purviewHeaders)) {
212+
Warn "Skipping Purview collection setup due to missing collection permissions."
213+
Clear-SensitiveVariables -VariableNames @("accessToken", "fabricToken", "purviewToken", "powerBIToken", "storageToken")
214+
exit 0
215+
}
201216
# Check existing collections
202217
$allCollections = Invoke-SecureRestMethod -Uri "$endpoint/account/collections?api-version=2019-11-01-preview" -Headers $purviewHeaders -Method Get -ErrorAction Stop
203218
$existing = $null

scripts/automationScripts/FabricPurviewAutomation/trigger_purview_scan_for_fabric_workspace.ps1

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ function Resolve-PurviewFromResourceId([string]$resourceId) {
6464
}
6565
}
6666

67+
function Test-PurviewCollectionAdmin([string]$endpoint, [hashtable]$headers) {
68+
try {
69+
Invoke-SecureRestMethod -Uri "$endpoint/account/collections?api-version=2019-11-01-preview" -Headers $headers -Method Get -ErrorAction Stop | Out-Null
70+
return $true
71+
} catch {
72+
Warn "Purview collection access check failed. Ensure the current identity has Purview Collection Admin on the target collection."
73+
return $false
74+
}
75+
}
76+
6777
# Resolve Purview account name
6878
$PurviewAccountName = $env:PURVIEW_ACCOUNT_NAME
6979
$PurviewSubscriptionId = $env:PURVIEW_SUBSCRIPTION_ID
@@ -166,6 +176,13 @@ if (-not $purviewToken) { Fail "Failed to acquire Purview access token" }
166176

167177
$endpoint = "https://$PurviewAccountName.purview.azure.com"
168178

179+
$purviewHeaders = New-SecureHeaders -Token $purviewToken
180+
if (-not (Test-PurviewCollectionAdmin -endpoint $endpoint -headers $purviewHeaders)) {
181+
Warn "Skipping Purview scan trigger due to missing collection permissions."
182+
Clear-SensitiveVariables -VariableNames @("accessToken", "fabricToken", "purviewToken", "powerBIToken", "storageToken")
183+
exit 0
184+
}
185+
169186
# Determine Purview datasource name. If a previous script created it, fabric_datasource.env in the temp directory will contain FABRIC_DATASOURCE_NAME. If missing or empty, skip scan creation.
170187
$datasourceName = 'Fabric'
171188
$tempDir = [IO.Path]::GetTempPath()
@@ -313,7 +330,7 @@ for ($attempt = 1; $attempt -le $maxCreateAttempts; $attempt++) {
313330
Warn "Scan create/update failed (HTTP $code): $respBody"
314331
if ($collectionId) {
315332
try {
316-
Warn "Retrying scan create/update without collection assignment..."
333+
Warn "Retrying scan create/update without collection assignment (collection reference may be missing or invalid)..."
317334
$payloadNoCollection = $payload.PSObject.Copy()
318335
if ($payloadNoCollection.properties -and $payloadNoCollection.properties.PSObject.Properties.Name -contains 'collection') {
319336
$payloadNoCollection.properties.PSObject.Properties.Remove('collection')
@@ -356,7 +373,9 @@ if (-not $createSucceeded -and -not $scanExists) {
356373
if ($lastCreateStatus -or $lastCreateBody) {
357374
Warn "Final scan create/update response (HTTP $lastCreateStatus): $lastCreateBody"
358375
}
359-
Fail "Could not create or retrieve scan definition after $maxCreateAttempts attempts."
376+
Warn "Could not create or retrieve scan definition after $maxCreateAttempts attempts. Continuing without a Purview scan run."
377+
Clear-SensitiveVariables -VariableNames @("accessToken", "fabricToken", "purviewToken", "powerBIToken", "storageToken")
378+
exit 0
360379
}
361380

362381
# Trigger a run with retries

scripts/automationScripts/FabricWorkspace/CreateWorkspace/register_fabric_datasource.ps1

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@ function Get-DefaultPurviewCollectionName() {
164164
return "collection-$($environmentName.Trim())"
165165
}
166166

167+
function Test-PurviewCollectionAdmin([string]$endpoint, [hashtable]$headers) {
168+
try {
169+
Invoke-SecureRestMethod -Uri "$endpoint/account/collections?api-version=2019-11-01-preview" -Headers $headers -Method Get -ErrorAction Stop | Out-Null
170+
return $true
171+
} catch {
172+
Warn "Purview collection access check failed. Ensure the current identity has Purview Collection Admin on the target collection."
173+
return $false
174+
}
175+
}
176+
167177
# Resolve Purview account and collection name from outputs/env/azd
168178
$outputs = $null
169179
if ($env:AZURE_OUTPUTS_JSON) {
@@ -317,6 +327,12 @@ try {
317327
# Create secure headers
318328
$purviewHeaders = New-SecureHeaders -Token $purviewToken
319329

330+
if (-not (Test-PurviewCollectionAdmin -endpoint $endpoint -headers $purviewHeaders)) {
331+
Warn "Skipping Purview datasource registration due to missing collection permissions."
332+
Clear-SensitiveVariables -VariableNames @('purviewToken')
333+
exit 0
334+
}
335+
320336
# Debug: print the identity running this script
321337
try {
322338
$acctName = & az account show --query name -o tsv 2>$null

0 commit comments

Comments
 (0)