@@ -2023,6 +2023,168 @@ param storagesku string
20232023 defaultAction: 'Allow'
20242024 }
20252025 minimumTlsVersion: 'TLS1_2'
2026+ allowSharedKeyAccess: false
2027+ }
2028+ }
2029+
2030+ resource blobService_vTLU20GRg 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
2031+ parent: storageAccount_1XR3Um8QY
2032+ name: 'default'
2033+ properties: {
2034+ }
2035+ }
2036+
2037+ resource roleAssignment_Gz09cEnxb 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
2038+ scope: storageAccount_1XR3Um8QY
2039+ name: guid(storageAccount_1XR3Um8QY.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'))
2040+ properties: {
2041+ roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
2042+ principalId: principalId
2043+ principalType: principalType
2044+ }
2045+ }
2046+
2047+ resource roleAssignment_HRj6MDafS 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
2048+ scope: storageAccount_1XR3Um8QY
2049+ name: guid(storageAccount_1XR3Um8QY.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'))
2050+ properties: {
2051+ roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')
2052+ principalId: principalId
2053+ principalType: principalType
2054+ }
2055+ }
2056+
2057+ resource roleAssignment_r0wA6OpKE 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
2058+ scope: storageAccount_1XR3Um8QY
2059+ name: guid(storageAccount_1XR3Um8QY.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88'))
2060+ properties: {
2061+ roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')
2062+ principalId: principalId
2063+ principalType: principalType
2064+ }
2065+ }
2066+
2067+ output blobEndpoint string = storageAccount_1XR3Um8QY.properties.primaryEndpoints.blob
2068+ output queueEndpoint string = storageAccount_1XR3Um8QY.properties.primaryEndpoints.queue
2069+ output tableEndpoint string = storageAccount_1XR3Um8QY.properties.primaryEndpoints.table
2070+
2071+ """ ;
2072+ output . WriteLine ( storageManifest . BicepText ) ;
2073+ Assert . Equal ( expectedBicep , storageManifest . BicepText ) ;
2074+
2075+ // Check blob resource.
2076+ var blob = storage . AddBlobs ( "blob" ) ;
2077+
2078+ var connectionStringBlobResource = ( IResourceWithConnectionString ) blob . Resource ;
2079+
2080+ Assert . Equal ( "https://myblob" , await connectionStringBlobResource . GetConnectionStringAsync ( ) ) ;
2081+ var expectedBlobManifest = """
2082+ {
2083+ "type": "value.v0",
2084+ "connectionString": "{storage.outputs.blobEndpoint}"
2085+ }
2086+ """ ;
2087+ var blobManifest = await ManifestUtils . GetManifest ( blob . Resource ) ;
2088+ Assert . Equal ( expectedBlobManifest , blobManifest . ToString ( ) ) ;
2089+
2090+ // Check queue resource.
2091+ var queue = storage . AddQueues ( "queue" ) ;
2092+
2093+ var connectionStringQueueResource = ( IResourceWithConnectionString ) queue . Resource ;
2094+
2095+ Assert . Equal ( "https://myqueue" , await connectionStringQueueResource . GetConnectionStringAsync ( ) ) ;
2096+ var expectedQueueManifest = """
2097+ {
2098+ "type": "value.v0",
2099+ "connectionString": "{storage.outputs.queueEndpoint}"
2100+ }
2101+ """ ;
2102+ var queueManifest = await ManifestUtils . GetManifest ( queue . Resource ) ;
2103+ Assert . Equal ( expectedQueueManifest , queueManifest . ToString ( ) ) ;
2104+
2105+ // Check table resource.
2106+ var table = storage . AddTables ( "table" ) ;
2107+
2108+ var connectionStringTableResource = ( IResourceWithConnectionString ) table . Resource ;
2109+
2110+ Assert . Equal ( "https://mytable" , await connectionStringTableResource . GetConnectionStringAsync ( ) ) ;
2111+ var expectedTableManifest = """
2112+ {
2113+ "type": "value.v0",
2114+ "connectionString": "{storage.outputs.tableEndpoint}"
2115+ }
2116+ """ ;
2117+ var tableManifest = await ManifestUtils . GetManifest ( table . Resource ) ;
2118+ Assert . Equal ( expectedTableManifest , tableManifest . ToString ( ) ) ;
2119+ }
2120+
2121+ [ Fact ]
2122+ public async Task AddAzureStorageViaRunModeAllowSharedKeyAccessOverridesDefaultFalse ( )
2123+ {
2124+ using var builder = TestDistributedApplicationBuilder . Create ( ) ;
2125+
2126+ var storagesku = builder . AddParameter ( "storagesku" ) ;
2127+ var storage = builder . AddAzureStorage ( "storage" , ( _ , _ , sa ) =>
2128+ {
2129+ sa . AssignProperty ( x => x . Sku . Name , storagesku ) ;
2130+ sa . AssignProperty ( x => x . AllowSharedKeyAccess , "true" ) ;
2131+ } ) ;
2132+
2133+ storage . Resource . Outputs [ "blobEndpoint" ] = "https://myblob" ;
2134+ storage . Resource . Outputs [ "queueEndpoint" ] = "https://myqueue" ;
2135+ storage . Resource . Outputs [ "tableEndpoint" ] = "https://mytable" ;
2136+
2137+ // Check storage resource.
2138+ Assert . Equal ( "storage" , storage . Resource . Name ) ;
2139+
2140+ var storageManifest = await ManifestUtils . GetManifestWithBicep ( storage . Resource ) ;
2141+
2142+ var expectedStorageManifest = """
2143+ {
2144+ "type": "azure.bicep.v0",
2145+ "path": "storage.module.bicep",
2146+ "params": {
2147+ "principalId": "",
2148+ "principalType": "",
2149+ "storagesku": "{storagesku.value}"
2150+ }
2151+ }
2152+ """ ;
2153+ Assert . Equal ( expectedStorageManifest , storageManifest . ManifestNode . ToString ( ) ) ;
2154+
2155+ var expectedBicep = """
2156+ targetScope = 'resourceGroup'
2157+
2158+ @description('')
2159+ param location string = resourceGroup().location
2160+
2161+ @description('')
2162+ param principalId string
2163+
2164+ @description('')
2165+ param principalType string
2166+
2167+ @description('')
2168+ param storagesku string
2169+
2170+
2171+ resource storageAccount_1XR3Um8QY 'Microsoft.Storage/storageAccounts@2022-09-01' = {
2172+ name: toLower(take('storage${uniqueString(resourceGroup().id)}', 24))
2173+ location: location
2174+ tags: {
2175+ 'aspire-resource-name': 'storage'
2176+ }
2177+ sku: {
2178+ name: storagesku
2179+ }
2180+ kind: 'StorageV2'
2181+ properties: {
2182+ accessTier: 'Hot'
2183+ networkAcls: {
2184+ defaultAction: 'Allow'
2185+ }
2186+ minimumTlsVersion: 'TLS1_2'
2187+ allowSharedKeyAccess: true
20262188 }
20272189 }
20282190
@@ -2182,6 +2344,168 @@ param storagesku string
21822344 defaultAction: 'Allow'
21832345 }
21842346 minimumTlsVersion: 'TLS1_2'
2347+ allowSharedKeyAccess: false
2348+ }
2349+ }
2350+
2351+ resource blobService_vTLU20GRg 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
2352+ parent: storageAccount_1XR3Um8QY
2353+ name: 'default'
2354+ properties: {
2355+ }
2356+ }
2357+
2358+ resource roleAssignment_Gz09cEnxb 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
2359+ scope: storageAccount_1XR3Um8QY
2360+ name: guid(storageAccount_1XR3Um8QY.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'))
2361+ properties: {
2362+ roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
2363+ principalId: principalId
2364+ principalType: principalType
2365+ }
2366+ }
2367+
2368+ resource roleAssignment_HRj6MDafS 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
2369+ scope: storageAccount_1XR3Um8QY
2370+ name: guid(storageAccount_1XR3Um8QY.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'))
2371+ properties: {
2372+ roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')
2373+ principalId: principalId
2374+ principalType: principalType
2375+ }
2376+ }
2377+
2378+ resource roleAssignment_r0wA6OpKE 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
2379+ scope: storageAccount_1XR3Um8QY
2380+ name: guid(storageAccount_1XR3Um8QY.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88'))
2381+ properties: {
2382+ roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')
2383+ principalId: principalId
2384+ principalType: principalType
2385+ }
2386+ }
2387+
2388+ output blobEndpoint string = storageAccount_1XR3Um8QY.properties.primaryEndpoints.blob
2389+ output queueEndpoint string = storageAccount_1XR3Um8QY.properties.primaryEndpoints.queue
2390+ output tableEndpoint string = storageAccount_1XR3Um8QY.properties.primaryEndpoints.table
2391+
2392+ """ ;
2393+ output . WriteLine ( storageManifest . BicepText ) ;
2394+ Assert . Equal ( expectedBicep , storageManifest . BicepText ) ;
2395+
2396+ // Check blob resource.
2397+ var blob = storage . AddBlobs ( "blob" ) ;
2398+
2399+ var connectionStringBlobResource = ( IResourceWithConnectionString ) blob . Resource ;
2400+
2401+ Assert . Equal ( "https://myblob" , await connectionStringBlobResource . GetConnectionStringAsync ( ) ) ;
2402+ var expectedBlobManifest = """
2403+ {
2404+ "type": "value.v0",
2405+ "connectionString": "{storage.outputs.blobEndpoint}"
2406+ }
2407+ """ ;
2408+ var blobManifest = await ManifestUtils . GetManifest ( blob . Resource ) ;
2409+ Assert . Equal ( expectedBlobManifest , blobManifest . ToString ( ) ) ;
2410+
2411+ // Check queue resource.
2412+ var queue = storage . AddQueues ( "queue" ) ;
2413+
2414+ var connectionStringQueueResource = ( IResourceWithConnectionString ) queue . Resource ;
2415+
2416+ Assert . Equal ( "https://myqueue" , await connectionStringQueueResource . GetConnectionStringAsync ( ) ) ;
2417+ var expectedQueueManifest = """
2418+ {
2419+ "type": "value.v0",
2420+ "connectionString": "{storage.outputs.queueEndpoint}"
2421+ }
2422+ """ ;
2423+ var queueManifest = await ManifestUtils . GetManifest ( queue . Resource ) ;
2424+ Assert . Equal ( expectedQueueManifest , queueManifest . ToString ( ) ) ;
2425+
2426+ // Check table resource.
2427+ var table = storage . AddTables ( "table" ) ;
2428+
2429+ var connectionStringTableResource = ( IResourceWithConnectionString ) table . Resource ;
2430+
2431+ Assert . Equal ( "https://mytable" , await connectionStringTableResource . GetConnectionStringAsync ( ) ) ;
2432+ var expectedTableManifest = """
2433+ {
2434+ "type": "value.v0",
2435+ "connectionString": "{storage.outputs.tableEndpoint}"
2436+ }
2437+ """ ;
2438+ var tableManifest = await ManifestUtils . GetManifest ( table . Resource ) ;
2439+ Assert . Equal ( expectedTableManifest , tableManifest . ToString ( ) ) ;
2440+ }
2441+
2442+ [ Fact ]
2443+ public async Task AddAzureStorageViaPublishModeEnableAllowSharedKeyAccessOverridesDefaultFalse ( )
2444+ {
2445+ using var builder = TestDistributedApplicationBuilder . Create ( DistributedApplicationOperation . Publish ) ;
2446+
2447+ var storagesku = builder . AddParameter ( "storagesku" ) ;
2448+ var storage = builder . AddAzureStorage ( "storage" , ( _ , _ , sa ) =>
2449+ {
2450+ sa . AssignProperty ( x => x . Sku . Name , storagesku ) ;
2451+ sa . AssignProperty ( x => x . AllowSharedKeyAccess , "true" ) ;
2452+ } ) ;
2453+
2454+ storage . Resource . Outputs [ "blobEndpoint" ] = "https://myblob" ;
2455+ storage . Resource . Outputs [ "queueEndpoint" ] = "https://myqueue" ;
2456+ storage . Resource . Outputs [ "tableEndpoint" ] = "https://mytable" ;
2457+
2458+ // Check storage resource.
2459+ Assert . Equal ( "storage" , storage . Resource . Name ) ;
2460+
2461+ var storageManifest = await ManifestUtils . GetManifestWithBicep ( storage . Resource ) ;
2462+
2463+ var expectedStorageManifest = """
2464+ {
2465+ "type": "azure.bicep.v0",
2466+ "path": "storage.module.bicep",
2467+ "params": {
2468+ "principalId": "",
2469+ "principalType": "",
2470+ "storagesku": "{storagesku.value}"
2471+ }
2472+ }
2473+ """ ;
2474+ Assert . Equal ( expectedStorageManifest , storageManifest . ManifestNode . ToString ( ) ) ;
2475+
2476+ var expectedBicep = """
2477+ targetScope = 'resourceGroup'
2478+
2479+ @description('')
2480+ param location string = resourceGroup().location
2481+
2482+ @description('')
2483+ param principalId string
2484+
2485+ @description('')
2486+ param principalType string
2487+
2488+ @description('')
2489+ param storagesku string
2490+
2491+
2492+ resource storageAccount_1XR3Um8QY 'Microsoft.Storage/storageAccounts@2022-09-01' = {
2493+ name: toLower(take('storage${uniqueString(resourceGroup().id)}', 24))
2494+ location: location
2495+ tags: {
2496+ 'aspire-resource-name': 'storage'
2497+ }
2498+ sku: {
2499+ name: storagesku
2500+ }
2501+ kind: 'StorageV2'
2502+ properties: {
2503+ accessTier: 'Hot'
2504+ networkAcls: {
2505+ defaultAction: 'Allow'
2506+ }
2507+ minimumTlsVersion: 'TLS1_2'
2508+ allowSharedKeyAccess: true
21852509 }
21862510 }
21872511
0 commit comments