Skip to content

Commit ac52276

Browse files
committed
feat: Update AzureStorageConfig to use Managed Identity and enhance deploy script for network ACL handling
1 parent ccef2ea commit ac52276

2 files changed

Lines changed: 33 additions & 5 deletions

File tree

sample-app/api/src/main/java/com/example/evidence/config/AzureStorageConfig.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.example.evidence.config;
22

3+
import com.azure.core.credential.TokenCredential;
34
import com.azure.identity.DefaultAzureCredentialBuilder;
5+
import com.azure.identity.ManagedIdentityCredentialBuilder;
46
import com.azure.storage.file.datalake.DataLakeServiceClient;
57
import com.azure.storage.file.datalake.DataLakeServiceClientBuilder;
68
import org.springframework.beans.factory.annotation.Value;
@@ -10,14 +12,20 @@
1012

1113
/**
1214
* Builds a DataLakeServiceClient for ADLS Gen2 using a Managed Identity
13-
* (or Azure CLI / dev credential) via DefaultAzureCredential. Shared keys
14-
* are disabled on the target storage account; all auth flows through Entra
15-
* ID + Storage Blob Data Contributor RBAC.
15+
* (or Azure CLI / dev credential). Shared keys are disabled on the target
16+
* storage account; all auth flows through Entra ID + Storage Blob Data
17+
* Contributor RBAC.
1618
*
1719
* The endpoint targets *.dfs.core.windows.net which, from inside the VNet,
1820
* resolves to the Private Endpoint NIC IP via the privatelink.dfs.* DNS
1921
* zone. From outside the VNet (e.g. local dev), the public DFS endpoint is
2022
* used and access is gated by the storage networkAcls.
23+
*
24+
* When running in App Service we pin to ManagedIdentityCredential to
25+
* avoid the DefaultAzureCredential chain falling back to a stale or wrong
26+
* principal (the chain has logged "EnvironmentCredential unavailable"
27+
* before failing over). The presence of the IDENTITY_ENDPOINT environment
28+
* variable is the standard signal that an MI endpoint is available.
2129
*/
2230
@Configuration
2331
@Profile("!dev")
@@ -30,7 +38,14 @@ public class AzureStorageConfig {
3038
public DataLakeServiceClient dataLakeServiceClient() {
3139
return new DataLakeServiceClientBuilder()
3240
.endpoint("https://" + accountName + ".dfs.core.windows.net")
33-
.credential(new DefaultAzureCredentialBuilder().build())
41+
.credential(buildCredential())
3442
.buildClient();
3543
}
44+
45+
private TokenCredential buildCredential() {
46+
if (System.getenv("IDENTITY_ENDPOINT") != null) {
47+
return new ManagedIdentityCredentialBuilder().build();
48+
}
49+
return new DefaultAzureCredentialBuilder().build();
50+
}
3651
}

scripts/deploy.ps1

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,20 @@ if (-not $SkipUpload) {
344344

345345
# The CLI's storage commands work transparently against HNS-enabled
346346
# accounts. We use --auth-mode login so no shared keys leave the
347-
# workstation. RBAC + IP allow-list were both granted in Step 3.
347+
# workstation. RBAC was granted in Step 3. The IP allow-list set by
348+
# Step 3 is unreliable when the workstation egresses through a NAT
349+
# pool with multiple public IPs (corporate network, Wi-Fi tethering),
350+
# so we briefly flip the storage networkAcls.defaultAction to Allow
351+
# for the duration of the upload, then Step 10 sets it back to Deny
352+
# along with publicNetworkAccess=Disabled.
353+
Write-Host ' Temporarily setting storage networkAcls.defaultAction=Allow for the seed upload'
354+
az storage account update `
355+
--resource-group $ResourceGroup `
356+
--name $storageAccountName `
357+
--default-action Allow `
358+
--output none
359+
Start-Sleep -Seconds 10
360+
348361
for ($i = 1; $i -le 6; $i++) {
349362
az storage container create `
350363
--account-name $storageAccountName `

0 commit comments

Comments
 (0)