diff --git a/azure.yaml b/azure.yaml index e15e71b..9c37fe8 100644 --- a/azure.yaml +++ b/azure.yaml @@ -21,9 +21,7 @@ hooks: continueOnError: false run: | echo " - CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME=\"$CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME\" CONFIGURATION__AZURECOSMOSDB__ENDPOINT=\"$CONFIGURATION__AZURECOSMOSDB__ENDPOINT\" - CONFIGURATION__AZURECOSMOSDB__KEY=\"$CONFIGURATION__AZURECOSMOSDB__KEY\" CONFIGURATION__AZURECOSMOSDB__TABLENAME=\"$CONFIGURATION__AZURECOSMOSDB__TABLENAME\" " > ./src/.env windows: @@ -32,8 +30,6 @@ hooks: continueOnError: false run: | echo " - CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME=""$env:CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME"" CONFIGURATION__AZURECOSMOSDB__ENDPOINT=""$env:CONFIGURATION__AZURECOSMOSDB__ENDPOINT"" - CONFIGURATION__AZURECOSMOSDB__KEY=""$env:CONFIGURATION__AZURECOSMOSDB__KEY"" CONFIGURATION__AZURECOSMOSDB__TABLENAME=""$env:CONFIGURATION__AZURECOSMOSDB__TABLENAME"" " > ./src/.env \ No newline at end of file diff --git a/infra/main.bicep b/infra/main.bicep index 6f50d79..ebc3601 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -23,27 +23,17 @@ var tags = { repo: 'https://github.com/azure-samples/cosmos-db-table-python-quickstart' } -var tableName = 'cosmicworks-products' - -module keyVault 'br/public:avm/res/key-vault/vault:0.10.2' = { - name: 'key-vault' +module managedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.0' = { + name: 'user-assigned-identity' params: { - name: 'key-vault-${resourceToken}' + name: 'managed-identity-${resourceToken}' location: location - sku: 'standard' - enablePurgeProtection: false - enableSoftDelete: false - publicNetworkAccess: 'Enabled' - enableRbacAuthorization: true - secrets: [ - { - name: 'key-vault-secret-azure-cosmos-db-table-key' - value: '' - } - ] + tags: tags } } +var tableName = 'cosmicworks-products' + module cosmosDbAccount 'br/public:avm/res/document-db/database-account:0.8.1' = { name: 'cosmos-db-account' params: { @@ -57,8 +47,8 @@ module cosmosDbAccount 'br/public:avm/res/document-db/database-account:0.8.1' = } ] tags: tags - disableKeyBasedMetadataWriteAccess: false - disableLocalAuth: false + disableKeyBasedMetadataWriteAccess: true + disableLocalAuth: true networkRestrictions: { publicNetworkAccess: 'Enabled' ipRules: [] @@ -68,13 +58,25 @@ module cosmosDbAccount 'br/public:avm/res/document-db/database-account:0.8.1' = 'EnableServerless' 'EnableTable' ] - secretsExportConfiguration: { - keyVaultResourceId: keyVault.outputs.resourceId - primaryWriteKeySecretName: 'key-vault-secret-azure-cosmos-db-table-key' - } + sqlRoleDefinitions: [ + { + name: 'table-data-plane-contributor' + dataAction: [ + 'Microsoft.DocumentDB/databaseAccounts/readMetadata' // Read account metadata + 'Microsoft.DocumentDB/databaseAccounts/tables/*' // Manage tables + 'Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*' // Create entities + ] + } + ] + sqlRoleAssignmentsPrincipalIds: union( + [ + managedIdentity.outputs.principalId + ], + !empty(deploymentUserPrincipalId) ? [deploymentUserPrincipalId] : [] + ) tables: [ { - name: tableName + name: tableName } ] } @@ -127,34 +129,8 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.8.0 } } -module managedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.0' = { - name: 'user-assigned-identity' - params: { - name: 'managed-identity-${resourceToken}' - location: location - tags: tags - } -} - -var keyVaultRole = subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '4633458b-17de-408a-b874-0445c86b69e6' -) // Key Vault Secrets User built-in role - -module keyVaultAppAssignment 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.1' = { - name: 'key-vault-role-assignment-secrets-user' - params: { - principalId: managedIdentity.outputs.principalId - resourceId: keyVault.outputs.resourceId - roleDefinitionId: keyVaultRole - } -} - module containerAppsApp 'br/public:avm/res/app/container-app:0.9.0' = { name: 'container-apps-app' - dependsOn: [ - keyVaultAppAssignment // Need to wait for the role assignment to complete before creating the container app - ] params: { name: 'container-app-${resourceToken}' environmentResourceId: containerAppsEnvironment.outputs.resourceId @@ -185,13 +161,8 @@ module containerAppsApp 'br/public:avm/res/app/container-app:0.9.0' = { value: 'https://${cosmosDbAccount.outputs.name}.table.cosmos.azure.com:443/' } { - name: 'azure-cosmos-db-table-account-name' - value: cosmosDbAccount.outputs.name - } - { - identity: managedIdentity.outputs.resourceId - name: 'azure-cosmos-db-table-write-key' - keyVaultUrl: cosmosDbAccount.outputs.exportedSecrets['key-vault-secret-azure-cosmos-db-table-key'].secretUri + name: 'user-assigned-managed-identity-client-id' + value: managedIdentity.outputs.clientId } ] } @@ -204,22 +175,18 @@ module containerAppsApp 'br/public:avm/res/app/container-app:0.9.0' = { memory: '.5Gi' } env: [ - { - name: 'CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME' - secretRef: 'azure-cosmos-db-table-account-name' - } { name: 'CONFIGURATION__AZURECOSMOSDB__ENDPOINT' secretRef: 'azure-cosmos-db-table-endpoint' } - { - name: 'CONFIGURATION__AZURECOSMOSDB__KEY' - secretRef: 'azure-cosmos-db-table-write-key' - } { name: 'CONFIGURATION__AZURECOSMOSDB__TABLENAME' value: tableName } + { + name: 'AZURE_CLIENT_ID' + secretRef: 'user-assigned-managed-identity-client-id' + } ] } ] @@ -227,14 +194,8 @@ module containerAppsApp 'br/public:avm/res/app/container-app:0.9.0' = { } // Azure Cosmos DB for Table outputs -output CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME string = cosmosDbAccount.outputs.name output CONFIGURATION__AZURECOSMOSDB__ENDPOINT string = 'https://${cosmosDbAccount.outputs.name}.table.cosmos.azure.com:443/' -#disable-next-line outputs-should-not-contain-secrets // This secret is required -output CONFIGURATION__AZURECOSMOSDB__KEY string = listKeys( - resourceId('Microsoft.DocumentDB/databaseAccounts', 'cosmos-db-table-${resourceToken}'), - '2021-04-15' -).primaryMasterKey output CONFIGURATION__AZURECOSMOSDB__TABLENAME string = tableName // Azure Container Registry outputs -output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer +output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer \ No newline at end of file diff --git a/src/cosmos.py b/src/cosmos.py index 17c8186..92fb916 100644 --- a/src/cosmos.py +++ b/src/cosmos.py @@ -1,7 +1,7 @@ from dotenv import load_dotenv -from azure.core.credentials import AzureNamedKeyCredential from azure.data.tables import TableServiceClient +from azure.identity import DefaultAzureCredential import json import os @@ -14,19 +14,11 @@ def runDemo(writeOutput): load_dotenv() # - accountName = os.getenv("CONFIGURATION__AZURECOSMOSDB__ACCOUNTNAME") - if not accountName: - raise EnvironmentError("Azure Cosmos DB for Table account name not set.") - endpoint = os.getenv("CONFIGURATION__AZURECOSMOSDB__ENDPOINT") if not endpoint: raise EnvironmentError("Azure Cosmos DB for Table account endpoint not set.") - key = os.getenv("CONFIGURATION__AZURECOSMOSDB__KEY") - if not key: - raise EnvironmentError("Azure Cosmos DB for Table write key not set.") - - credential = AzureNamedKeyCredential(accountName, key) + credential = DefaultAzureCredential() client = TableServiceClient(endpoint=endpoint, credential=credential) # diff --git a/src/requirements.txt b/src/requirements.txt index 8be3f92..a01904a 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,6 +1,7 @@ Flask==3.0.3 Flask-SocketIO==5.4.1 -azure-data-tables==12.5.0 +azure-data-tables==12.6.0 +azure-identity==1.19.0 gunicorn==23.0.0 eventlet==0.37.0 python-dotenv==1.0.1 \ No newline at end of file