-
Couldn't load subscription status.
- Fork 713
Improve managed identity for sql server #9041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 17 commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
d888208
WIP
sebastienros 57bf64c
Try more
sebastienros 22661a5
Fix template
sebastienros de6ba42
Add log to show app identity is added after our BeforeEventStart
sebastienros 8c5312b
Fix script templates
sebastienros f506018
Remove unused location
sebastienros a2992a9
Move code into role assignments
sebastienros cdc8f85
Create deployment script with mi
sebastienros a2e1aaa
Use powershell script
sebastienros 35e5927
Add support for userPrincipalName
sebastienros 6629c4c
Use dedicated admin for server
sebastienros 3bfef19
Use free sku
sebastienros 5ccf7b3
Nits
sebastienros b7cd953
Add manifest
sebastienros 452d42e
Fix reference() usage issue for script identity
sebastienros 0027495
Update manifest
sebastienros 6613528
Merge remote-tracking branch 'origin/main' into sebros/bicep
sebastienros 29973ef
Remove dependency on Azure.Provisioning.AppContainers
sebastienros af11bcf
Remove unnecessary userPrincipalName
sebastienros c526fea
Rename ContainerAppEnvironmentVariable
sebastienros 51fd43d
Rename clientId to objectId
sebastienros 0946bb1
Update manifests
sebastienros 86a69c5
Use id interpolation
sebastienros 6a13552
Nits
sebastienros 3d16cab
Use client id and fixed sample
sebastienros 4484410
Improve script resource identifier and name
sebastienros 2206e1a
Add db and server in name
sebastienros 3eb57f1
Male SqlServerE2E free
sebastienros f6b9a7f
Handle both users and managed identities
sebastienros d74c616
Use RunMode
sebastienros d3bfbb5
Don't add role assignment for existing resource
sebastienros 0d74417
Feedback
sebastienros 0e80007
Improve name reference expression
sebastienros d62e5c6
Remove unnused code
sebastienros 981cd0e
Merge branch 'main' into sebros/bicep
sebastienros 2a71382
Update tests
sebastienros b1974c4
Update role assignment tests
sebastienros 726399f
Delete verification file
sebastienros e115e61
Update API
sebastienros a0b4be1
Feedback
sebastienros 8a369c9
Merge remote-tracking branch 'origin/main' into sebros/bicep
sebastienros 41a35e9
Fix build
sebastienros 801ff69
Merge remote-tracking branch 'origin/main' into sebros/bicep
sebastienros f98bd3e
Fix tests
sebastienros File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>$(DefaultTargetFramework)</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| <IsAspireHost>true</IsAspireHost> | ||
| <UserSecretsId>f6d0abe5-33e8-4825-861a-35b3767a490b</UserSecretsId> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <AspireProjectOrPackageReference Include="Aspire.Hosting.Azure" /> | ||
| <AspireProjectOrPackageReference Include="Aspire.Hosting.Azure.Sql" /> | ||
| <AspireProjectOrPackageReference Include="Aspire.Hosting.AppHost" /> | ||
| <AspireProjectOrPackageReference Include="Aspire.Hosting.Azure.AppContainers" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\WebApplication1\WebApplication1.csproj" /> | ||
| <ProjectReference Include="..\WebApplication2\WebApplication2.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using Aspire.Hosting; | ||
| using Azure.Provisioning.Sql; | ||
|
|
||
| var builder = DistributedApplication.CreateBuilder(args); | ||
|
|
||
| builder.AddAzureContainerAppEnvironment("env"); | ||
|
|
||
| var dbServer = builder.AddAzureSqlServer("mysqlserver") | ||
| .ConfigureInfrastructure(c => | ||
| { | ||
| const string FREE_DB_SKU = "GP_S_Gen5_2"; | ||
|
|
||
| foreach (var database in c.GetProvisionableResources().OfType<SqlDatabase>()) | ||
| { | ||
| database.Sku = new SqlSku() { Name = FREE_DB_SKU }; | ||
| } | ||
| }); | ||
|
|
||
| var todosDb = dbServer.AddDatabase("todosdb"); | ||
|
|
||
| builder.AddProject<Projects.WebApplication1>("api1").WithReference(todosDb).WaitFor(todosDb); | ||
| builder.AddProject<Projects.WebApplication2>("api2").WithReference(todosDb).WaitFor(todosDb); | ||
|
|
||
| builder.Build().Run(); |
29 changes: 29 additions & 0 deletions
29
playground/SqlServerScript/AppHost1/Properties/launchSettings.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| { | ||
| "$schema": "https://json.schemastore.org/launchsettings.json", | ||
| "profiles": { | ||
| "https": { | ||
| "commandName": "Project", | ||
| "dotnetRunMessages": true, | ||
| "launchBrowser": true, | ||
| "applicationUrl": "https://localhost:17077;http://localhost:15242", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development", | ||
| "DOTNET_ENVIRONMENT": "Development", | ||
| "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21045", | ||
| "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22270" | ||
| } | ||
| }, | ||
| "http": { | ||
| "commandName": "Project", | ||
| "dotnetRunMessages": true, | ||
| "launchBrowser": true, | ||
| "applicationUrl": "http://localhost:15242", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development", | ||
| "DOTNET_ENVIRONMENT": "Development", | ||
| "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19139", | ||
| "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20080" | ||
| } | ||
| } | ||
| } | ||
| } |
15 changes: 15 additions & 0 deletions
15
playground/SqlServerScript/AppHost1/api1-identity.module.bicep
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| @description('The location for the resource(s) to be deployed.') | ||
| param location string = resourceGroup().location | ||
|
|
||
| resource api1_identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { | ||
| name: take('api1_identity-${uniqueString(resourceGroup().id)}', 128) | ||
| location: location | ||
| } | ||
|
|
||
| output id string = api1_identity.id | ||
|
|
||
| output clientId string = api1_identity.properties.clientId | ||
|
|
||
| output principalId string = api1_identity.properties.principalId | ||
|
|
||
| output principalName string = api1_identity.name |
53 changes: 53 additions & 0 deletions
53
playground/SqlServerScript/AppHost1/api1-roles-mysqlserver.module.bicep
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| @description('The location for the resource(s) to be deployed.') | ||
| param location string = resourceGroup().location | ||
|
|
||
| param mysqlserver_outputs_name string | ||
|
|
||
| param principalName string | ||
|
|
||
| param principalId string | ||
|
|
||
| param mysqlserver_outputs_sqlserveradminname string | ||
|
|
||
| resource mysqlserver 'Microsoft.Sql/servers@2021-11-01' existing = { | ||
| name: mysqlserver_outputs_name | ||
| } | ||
|
|
||
| resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { | ||
| name: mysqlserver_outputs_sqlserveradminname | ||
| } | ||
|
|
||
| resource script_81de323e2cb9c0ad 'Microsoft.Resources/deploymentScripts@2023-08-01' = { | ||
| name: take('scriptdeecbcad${uniqueString(resourceGroup().id)}', 24) | ||
| location: location | ||
| identity: { | ||
| type: 'UserAssigned' | ||
| userAssignedIdentities: { | ||
| '${sqlServerAdmin.id}': { } | ||
| } | ||
| } | ||
| kind: 'AzurePowerShell' | ||
| properties: { | ||
| scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$username = "\$env:USERNAME"\r\n\$clientId = "\$env:CLIENTID"\r\n\r\n# Install SqlServer module\r\nInstall-Module -Name SqlServer -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @principal_name SYSNAME = \'\$username\';\r\nDECLARE @clientId UNIQUEIDENTIFIER = \'\$clientId\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castClientId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @clientId), 1);\r\n\r\n-- Construct command: CREATE USER [@principal_name] WITH SID = @castClientId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @principal_name + \'] WITH SID = \' + @castClientId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_datareader ADD MEMBER [\' + @principal_name + \']\';\r\nEXEC (@role1);\r\n\r\nDECLARE @role2 NVARCHAR(MAX) = N\'ALTER ROLE db_datawriter ADD MEMBER [\' + @principal_name + \']\';\r\nEXEC (@role2);\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' | ||
| azPowerShellVersion: '7.4' | ||
| retentionInterval: 'PT1H' | ||
| environmentVariables: [ | ||
| { | ||
| name: 'DBNAME' | ||
| value: 'todosdb' | ||
| } | ||
| { | ||
| name: 'DBSERVER' | ||
| value: mysqlserver.properties.fullyQualifiedDomainName | ||
| } | ||
| { | ||
| name: 'USERNAME' | ||
| value: principalName | ||
| } | ||
| { | ||
| name: 'CLIENTID' | ||
| value: principalId | ||
| } | ||
| ] | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| @description('The location for the resource(s) to be deployed.') | ||
| param location string = resourceGroup().location | ||
|
|
||
| param api1_identity_outputs_id string | ||
|
|
||
| param api1_identity_outputs_clientid string | ||
|
|
||
| param api1_containerport string | ||
|
|
||
| param mysqlserver_outputs_sqlserverfqdn string | ||
|
|
||
| param env_outputs_azure_container_apps_environment_default_domain string | ||
|
|
||
| param env_outputs_azure_container_apps_environment_id string | ||
|
|
||
| param env_outputs_azure_container_registry_endpoint string | ||
|
|
||
| param env_outputs_azure_container_registry_managed_identity_id string | ||
|
|
||
| param api1_containerimage string | ||
|
|
||
| resource api1 'Microsoft.App/containerApps@2024-03-01' = { | ||
| name: 'api1' | ||
| location: location | ||
| properties: { | ||
| configuration: { | ||
| activeRevisionsMode: 'Single' | ||
| ingress: { | ||
| external: false | ||
| targetPort: api1_containerport | ||
| transport: 'http' | ||
| } | ||
| registries: [ | ||
| { | ||
| server: env_outputs_azure_container_registry_endpoint | ||
| identity: env_outputs_azure_container_registry_managed_identity_id | ||
| } | ||
| ] | ||
| } | ||
| environmentId: env_outputs_azure_container_apps_environment_id | ||
| template: { | ||
| containers: [ | ||
| { | ||
| image: api1_containerimage | ||
| name: 'api1' | ||
| env: [ | ||
| { | ||
| name: 'OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES' | ||
| value: 'true' | ||
| } | ||
| { | ||
| name: 'OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES' | ||
| value: 'true' | ||
| } | ||
| { | ||
| name: 'OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY' | ||
| value: 'in_memory' | ||
| } | ||
| { | ||
| name: 'ASPNETCORE_FORWARDEDHEADERS_ENABLED' | ||
| value: 'true' | ||
| } | ||
| { | ||
| name: 'HTTP_PORTS' | ||
| value: api1_containerport | ||
| } | ||
| { | ||
| name: 'ConnectionStrings__todosdb' | ||
| value: 'Server=tcp:${mysqlserver_outputs_sqlserverfqdn},1433;Encrypt=True;Authentication="Active Directory Default";Database=todosdb' | ||
| } | ||
| { | ||
| name: 'AZURE_CLIENT_ID' | ||
| value: api1_identity_outputs_clientid | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| scale: { | ||
| minReplicas: 1 | ||
| } | ||
| } | ||
| } | ||
| identity: { | ||
| type: 'UserAssigned' | ||
| userAssignedIdentities: { | ||
| '${api1_identity_outputs_id}': { } | ||
| '${env_outputs_azure_container_registry_managed_identity_id}': { } | ||
| } | ||
| } | ||
| } |
15 changes: 15 additions & 0 deletions
15
playground/SqlServerScript/AppHost1/api2-identity.module.bicep
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| @description('The location for the resource(s) to be deployed.') | ||
| param location string = resourceGroup().location | ||
|
|
||
| resource api2_identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { | ||
| name: take('api2_identity-${uniqueString(resourceGroup().id)}', 128) | ||
| location: location | ||
| } | ||
|
|
||
| output id string = api2_identity.id | ||
|
|
||
| output clientId string = api2_identity.properties.clientId | ||
|
|
||
| output principalId string = api2_identity.properties.principalId | ||
|
|
||
| output principalName string = api2_identity.name |
53 changes: 53 additions & 0 deletions
53
playground/SqlServerScript/AppHost1/api2-roles-mysqlserver.module.bicep
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| @description('The location for the resource(s) to be deployed.') | ||
| param location string = resourceGroup().location | ||
|
|
||
| param mysqlserver_outputs_name string | ||
|
|
||
| param principalName string | ||
|
|
||
| param principalId string | ||
|
|
||
| param mysqlserver_outputs_sqlserveradminname string | ||
|
|
||
| resource mysqlserver 'Microsoft.Sql/servers@2021-11-01' existing = { | ||
| name: mysqlserver_outputs_name | ||
| } | ||
|
|
||
| resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { | ||
| name: mysqlserver_outputs_sqlserveradminname | ||
| } | ||
|
|
||
| resource script_d4d29beaabeca77b 'Microsoft.Resources/deploymentScripts@2023-08-01' = { | ||
| name: take('scriptddbeaabecab${uniqueString(resourceGroup().id)}', 24) | ||
| location: location | ||
| identity: { | ||
| type: 'UserAssigned' | ||
| userAssignedIdentities: { | ||
| '${sqlServerAdmin.id}': { } | ||
| } | ||
| } | ||
| kind: 'AzurePowerShell' | ||
| properties: { | ||
| scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$username = "\$env:USERNAME"\r\n\$clientId = "\$env:CLIENTID"\r\n\r\n# Install SqlServer module\r\nInstall-Module -Name SqlServer -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @principal_name SYSNAME = \'\$username\';\r\nDECLARE @clientId UNIQUEIDENTIFIER = \'\$clientId\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castClientId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @clientId), 1);\r\n\r\n-- Construct command: CREATE USER [@principal_name] WITH SID = @castClientId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @principal_name + \'] WITH SID = \' + @castClientId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_datareader ADD MEMBER [\' + @principal_name + \']\';\r\nEXEC (@role1);\r\n\r\nDECLARE @role2 NVARCHAR(MAX) = N\'ALTER ROLE db_datawriter ADD MEMBER [\' + @principal_name + \']\';\r\nEXEC (@role2);\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' | ||
| azPowerShellVersion: '7.4' | ||
| retentionInterval: 'PT1H' | ||
| environmentVariables: [ | ||
| { | ||
| name: 'DBNAME' | ||
| value: 'todosdb' | ||
| } | ||
| { | ||
| name: 'DBSERVER' | ||
| value: mysqlserver.properties.fullyQualifiedDomainName | ||
| } | ||
| { | ||
| name: 'USERNAME' | ||
| value: principalName | ||
| } | ||
| { | ||
| name: 'CLIENTID' | ||
| value: principalId | ||
| } | ||
| ] | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.