5
5
using Aspire . Hosting . Azure ;
6
6
using Azure . Provisioning ;
7
7
using Azure . Provisioning . Expressions ;
8
+ using Azure . Provisioning . Primitives ;
8
9
using Azure . Provisioning . Sql ;
9
10
10
11
namespace Aspire . Hosting ;
@@ -226,6 +227,20 @@ private static void CreateSqlServer(
226
227
} ;
227
228
} ) ;
228
229
230
+ // If the resource is an existing resource, we model the administrator access
231
+ // for the managed identity as an "edge" between the parent SqlServer resource
232
+ // and a custom SqlServerAzureADAdministrator resource.
233
+ if ( sqlServer . IsExistingResource )
234
+ {
235
+ var admin = new SqlServerAzureADAdministratorWorkaround ( $ "{ sqlServer . BicepIdentifier } _admin")
236
+ {
237
+ ParentOverride = sqlServer ,
238
+ LoginOverride = principalNameParameter ,
239
+ SidOverride = principalIdParameter
240
+ } ;
241
+ infrastructure . Add ( admin ) ;
242
+ }
243
+
229
244
infrastructure . Add ( new SqlFirewallRule ( "sqlFirewallRule_AllowAllAzureIps" )
230
245
{
231
246
Parent = sqlServer ,
@@ -240,6 +255,7 @@ private static void CreateSqlServer(
240
255
// the principalType.
241
256
var principalTypeParameter = new ProvisioningParameter ( AzureBicepResource . KnownParameters . PrincipalType , typeof ( string ) ) ;
242
257
infrastructure . Add ( principalTypeParameter ) ;
258
+ // Avoid mutating properties on existing resources.
243
259
if ( ! sqlServer . IsExistingResource )
244
260
{
245
261
sqlServer . Administrators . PrincipalType = principalTypeParameter ;
@@ -268,4 +284,79 @@ private static void CreateSqlServer(
268
284
269
285
infrastructure . Add ( new ProvisioningOutput ( "sqlServerFqdn" , typeof ( string ) ) { Value = sqlServer . FullyQualifiedDomainName } ) ;
270
286
}
287
+
288
+ /// <remarks>
289
+ /// Workaround for immutable properties on SqlServerAzureADAdministrator.
290
+ /// </remarks>
291
+ private sealed class SqlServerAzureADAdministratorWorkaround ( string bicepIdentifier ) : SqlServerAzureADAdministrator ( bicepIdentifier )
292
+ {
293
+ private BicepValue < string > ? _name ;
294
+ private BicepValue < string > ? _login ;
295
+ private BicepValue < Guid > ? _sid ;
296
+ private ResourceReference < SqlServer > ? _parent ;
297
+
298
+ /// <summary>
299
+ /// Login name of the server administrator.
300
+ /// </summary>
301
+ public BicepValue < string > LoginOverride
302
+ {
303
+ get
304
+ {
305
+ Initialize ( ) ;
306
+ return _login ! ;
307
+ }
308
+ set
309
+ {
310
+ Initialize ( ) ;
311
+ _login ! . Assign ( value ) ;
312
+ }
313
+ }
314
+
315
+ /// <summary>
316
+ /// SID (object ID) of the server administrator.
317
+ /// </summary>
318
+ public BicepValue < Guid > SidOverride
319
+ {
320
+ get
321
+ {
322
+ Initialize ( ) ;
323
+ return _sid ! ;
324
+ }
325
+ set
326
+ {
327
+ Initialize ( ) ;
328
+ _sid ! . Assign ( value ) ;
329
+ }
330
+ }
331
+
332
+ /// <summary>
333
+ /// Parent resource of the server administrator.
334
+ /// </summary>
335
+ public SqlServer ? ParentOverride
336
+ {
337
+ get
338
+ {
339
+ Initialize ( ) ;
340
+ return _parent ! . Value ;
341
+ }
342
+ set
343
+ {
344
+ Initialize ( ) ;
345
+ _parent ! . Value = value ;
346
+ }
347
+ }
348
+
349
+ private static BicepValue < string > GetNameDefaultValue ( )
350
+ {
351
+ return new StringLiteralExpression ( "ActiveDirectory" ) ;
352
+ }
353
+
354
+ protected override void DefineProvisionableProperties ( )
355
+ {
356
+ _name = DefineProperty ( "Name" , [ "name" ] , defaultValue : GetNameDefaultValue ( ) ) ;
357
+ _login = DefineProperty < string > ( "Login" , [ "properties" , "login" ] ) ;
358
+ _sid = DefineProperty < Guid > ( "Sid" , [ "properties" , "sid" ] ) ;
359
+ _parent = DefineResource < SqlServer > ( "Parent" , [ "parent" ] , isOutput : false , isRequired : true ) ;
360
+ }
361
+ }
271
362
}
0 commit comments