Skip to content

Commit 5a5f481

Browse files
Merge pull request #291983 from msangapu-msft/pythonROPC
Python ROPC
2 parents 91e07a4 + 779cbde commit 5a5f481

9 files changed

+61
-45
lines changed

articles/app-service/configure-language-python.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ Existing web applications can be redeployed to Azure as follows:
108108
1. **App service resources**: Create a resource group, App Service plan, and App Service web app to host your application. You can do this easily by running the Azure CLI command [`az webapp up`](/cli/azure/webapp#az-webapp-up). Or, you can create and deploy resources as shown in [Tutorial: Deploy a Python (Django or Flask) web app with PostgreSQL](tutorial-python-postgresql-app.md). Replace the names of the resource group, App Service plan, and web app to be more suitable for your application.
109109
110110
1. **Environment variables**: If your application requires any environment variables, create equivalent [App Service application settings](configure-common.md#configure-app-settings). These App Service settings appear to your code as environment variables, as described in [Access environment variables](#access-app-settings-as-environment-variables).
111-
- Database connections, for example, are often managed through such settings, as shown in [Tutorial: Deploy a Django web app with PostgreSQL - verify connection settings](tutorial-python-postgresql-app.md#2-verify-connection-settings).
111+
- Database connections, for example, are often managed through such settings, as shown in [Tutorial: Deploy a Django web app with PostgreSQL - verify connection settings](tutorial-python-postgresql-app.md#2-secure-connection-secrets).
112112
- See [Production settings for Django apps](#production-settings-for-django-apps) for specific settings for typical Django apps.
113113
114114
1. **App startup**: Review the section [Container startup process](#container-startup-process) later in this article to understand how App Service attempts to run your app. App Service uses the Gunicorn web server by default, which must be able to find your app object or *wsgi.py* folder. If you need to, you can [Customize the startup command](#customize-startup-command).
@@ -430,7 +430,7 @@ When attempting to run database migrations with a Django app, you might see "sql
430430

431431
Check the `DATABASES` variable in the app's *settings.py* file to ensure that your app is using a cloud database instead of SQLite.
432432

433-
If you're encountering this error with the sample in [Tutorial: Deploy a Django web app with PostgreSQL](tutorial-python-postgresql-app.md), check that you completed the steps in [Verify connection settings](tutorial-python-postgresql-app.md#2-verify-connection-settings).
433+
If you're encountering this error with the sample in [Tutorial: Deploy a Django web app with PostgreSQL](tutorial-python-postgresql-app.md), check that you completed the steps in [Verify connection settings](tutorial-python-postgresql-app.md#2-secure-connection-secrets).
434434

435435
#### Other issues
436436

51.6 KB
Loading
43.6 KB
Loading
60.7 KB
Loading
88.4 KB
Loading
17.7 KB
Loading
37.8 KB
Loading
37 KB
Loading

articles/app-service/tutorial-python-postgresql-app.md

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -244,94 +244,110 @@ Sign in to the [Azure portal](https://portal.azure.com/) and follow these steps
244244

245245
-----
246246

247-
## 2. Verify connection settings
247+
## 2. Secure connection secrets
248248

249-
The creation wizard generated the connectivity variables for you already as [app settings](configure-common.md#configure-app-settings). App settings are one way to keep connection secrets out of your code repository. When you're ready to move your secrets to a more secure location, here's an [article on storing in Azure Key Vault](/azure/key-vault/certificates/quick-create-python).
250-
251-
### [Flask](#tab/flask)
249+
The creation wizard generated the database connectivity string for you already as an [app setting](configure-common.md#configure-app-settings). However, the security best practice is to keep secrets out of App Service completely. You move your secrets to a key vault and change your app setting to a [Key Vault reference](app-service-key-vault-references.md) with the help of Service Connectors.
252250

253251
:::row:::
254252
:::column span="2":::
255-
**Step 1:** In the App Service page, in the left menu, select **Configuration**.
253+
**Step 1: Retrieve the existing connection string**
254+
1. In the left menu of the App Service page, select **Settings > Environment variables**.
255+
1. Select **AZURE_POSTGRESQL_CONNECTIONSTRING**.
256+
1. In **Add/Edit application setting**, in the **Value** field, find the *password=* part at the end of the string.
257+
1. Copy the password string after *Password=* for use later.
258+
This app setting lets you connect to the Postgres database secured behind a private endpoint. However, the secret is saved directly in the App Service app, which isn't the best. You'll change this.
256259
:::column-end:::
257260
:::column:::
258-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-1.png" alt-text="A screenshot showing how to open the configuration page in App Service (Flask)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-1.png":::
261+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-1.png" alt-text="A screenshot showing how to see the value of an app setting." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-1.png":::
259262
:::column-end:::
260263
:::row-end:::
261264
:::row:::
262265
:::column span="2":::
263-
**Step 2:** In the **Application settings** tab of the **Configuration** page, verify that `AZURE_POSTGRESQL_CONNECTIONSTRING` is present. That will be injected into the runtime environment as an environment variable.
266+
**Step 2: Create a key vault for secure management of secrets**
267+
1. In the top search bar, type "*key vault*", then select **Marketplace** > **Key Vault**.
268+
1. In **Resource Group**, select **msdocs-python-postgres-tutorial**.
269+
1. In **Key vault name**, type a name that consists of only letters and numbers.
270+
1. In **Region**, set it to the same location as the resource group.
264271
:::column-end:::
265272
:::column:::
266-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-2.png" alt-text="A screenshot showing how to see the autogenerated connection string (Flask)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-2.png":::
273+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-2.png" alt-text="A screenshot showing how to create a key vault." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-2.png":::
267274
:::column-end:::
268275
:::row-end:::
269276
:::row:::
270277
:::column span="2":::
271-
**Step 3:** In a terminal or command prompt, run the following Python script to generate a unique secret: `python -c 'import secrets; print(secrets.token_hex())'`. Copy the output value to use in the next step.
278+
**Step 3: Secure the key vault with a Private Endpoint**
279+
1. Select the **Networking** tab.
280+
1. Unselect **Enable public access**.
281+
1. Select **Create a private endpoint**.
282+
1. In **Resource Group**, select **msdocs-python-postgres-tutorial**.
283+
1. In **Name**, type a name for the private endpoint that consists of only letters and numbers.
284+
1. In **Region**, set it to the same location as the resource group.
285+
1. In the dialog, in **Location**, select the same location as your App Service app.
286+
1. In **Resource Group**, select **msdocs-python-postgres-tutorial**.
287+
1. In **Name**, type **msdocs-python-spostgres-XYZVaultEndpoint**.
288+
1. In **Virtual network**, select **msdocs-python-postgres-XYZVnet**.
289+
1. In **Subnet**, **msdocs-python-postgres-XYZSubnet**.
290+
1. Select **OK**.
291+
1. Select **Review + create**, then select **Create**. Wait for the key vault deployment to finish. You should see "Your deployment is complete."
272292
:::column-end:::
273293
:::column:::
294+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-3.png" alt-text="A screenshot showing how to secure a key vault with a private endpoint." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-3.png":::
274295
:::column-end:::
275296
:::row-end:::
276297
:::row:::
277298
:::column span="2":::
278-
**Step 4:** Back in the **Configuration** page, select **New application setting**. Name the setting `SECRET_KEY`. Paste the value from the previous value. Select **OK**.
299+
**Step 4: Configure the Service Connector**
300+
1. In the top search bar, type *msdocs-python-postgres*, then select the App Service resource called **msdocs-python-postgres-XYZ**.
301+
1. In the App Service page, in the left menu, select **Settings > Service Connector**. There's already a connector, which the app creation wizard created for you.
302+
1. Select checkbox next to the connector, then select **Edit**.
303+
1. In the **Basics** tab, under **PostgreSQL database** select the PostgreSQL database that was created.
304+
1. Select the **Authentication** tab.
305+
1. In **Password**, paste the password you copied earlier.
306+
1. Select **Store Secret in Key Vault**.
307+
1. Under **Key Vault Connection**, select **Create new**.
308+
A **Create connection** dialog is opened on top of the edit dialog.
279309
:::column-end:::
280310
:::column:::
281-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting.png" alt-text="A screenshot showing how to set the SECRET_KEY app setting in the Azure portal (Django)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting.png":::
311+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-4.png" alt-text="A screenshot showing how to edit a service connector with a key vault connection." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-4.png":::
282312
:::column-end:::
283313
:::row-end:::
284314
:::row:::
285315
:::column span="2":::
286-
**Step 5:** Select **Save**.
316+
**Step 5: Establish the Key Vault connection**
317+
1. In the **Create connection** dialog for the Key Vault connection, in **Key Vault**, select the key vault you created earlier.
318+
1. Select **Review + Create**.
319+
1. When validation completes, select **Create**.
287320
:::column-end:::
288321
:::column:::
289-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting-save.png" alt-text="A screenshot showing how to save the SECRET_KEY app setting in the Azure portal (Django)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting-save.png":::
322+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-5.png" alt-text="A screenshot showing how to configure a key vault service connector." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-5.png":::
290323
:::column-end:::
291324
:::row-end:::
292-
293-
### [Django](#tab/django)
294-
295325
:::row:::
296326
:::column span="2":::
297-
**Step 1:** In the App Service page, in the left menu, select **Configuration**.
327+
**Step 6: Finalize the Service Connector configuration**
328+
1. You're back in the edit dialog for **defaultConnector**. In the **Authentication** tab, wait for the key vault connector to be created. When it's finished, the **Key Vault Connection** dropdown automatically selects it.
329+
1. Select **Next: Networking**.
330+
1. Select **Save**. Wait until the **Update succeeded** notification appears.
298331
:::column-end:::
299332
:::column:::
300-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-1.png" alt-text="A screenshot showing how to open the configuration page in App Service (Django)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-1.png":::
333+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-6.png" alt-text="A screenshot showing the key vault connection selected in the defaultConnector." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-6.png":::
301334
:::column-end:::
302335
:::row-end:::
303336
:::row:::
304337
:::column span="2":::
305-
**Step 2:** In the **Application settings** tab of the **Configuration** page, verify that `AZURE_POSTGRESQL_CONNECTIONSTRING` and `AZURE_REDIS_CONNECTIONSTRING` are present. They will be injected into the runtime environment as an environment variable.
338+
**Step 7: Verify the Key Vault integration**
339+
1. From the left menu, select **Settings > Environment variables** again.
340+
1. Next to **AZURE_POSTGRESQL_CONNECTIONSTRING**, select **Show value**. The value should be `@Microsoft.KeyVault(...)`, which means that it's a [key vault reference](app-service-key-vault-references.md) because the secret is now managed in the key vault.
306341
:::column-end:::
307342
:::column:::
308-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-2-django.png" alt-text="A screenshot showing how to see the autogenerated connection string (Django)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-get-connection-string-2.png":::
309-
:::column-end:::
310-
:::row-end:::
311-
:::row:::
312-
:::column span="2":::
313-
**Step 3:** In a terminal or command prompt, run the following Python script to generate a unique secret: `python -c 'import secrets; print(secrets.token_hex())'`. Copy the output value to use in the next step.
314-
:::column-end:::
315-
:::column:::
316-
:::column-end:::
317-
:::row-end:::
318-
:::row:::
319-
:::column span="2":::
320-
**Step 4:** Back in the **Configuration** page, select **New application setting**. Name the setting `SECRET_KEY`. Paste the value from the previous value. Select **OK**.
321-
:::column-end:::
322-
:::column:::
323-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting.png" alt-text="A screenshot showing how to set the SECRET_KEY app setting in the Azure portal (Django)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting.png":::
324-
:::column-end:::
325-
:::row-end:::
326-
:::row:::
327-
:::column span="2":::
328-
**Step 5:** Select **Save**.
329-
:::column-end:::
330-
:::column:::
331-
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting-save.png" alt-text="A screenshot showing how to save the SECRET_KEY app setting in the Azure portal (Django)." lightbox="./media/tutorial-python-postgresql-app/azure-portal-app-service-app-setting-save.png":::
343+
:::image type="content" source="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-7.png" alt-text="A screenshot showing how to see the value of the MySQL environment variable in Azure." lightbox="./media/tutorial-python-postgresql-app/azure-portal-secure-connection-secrets-7.png":::
332344
:::column-end:::
333345
:::row-end:::
334346

347+
To summarize, the process involved retrieving the MySQL connection string from the App Service's environment variables, creating an Azure Key Vault for secure secret management with private access, and updating the service connector to store the password in the key vault. A secure connection between the App Service app and key vault was established using a system-assigned managed identity, and the setup was verified by confirming the connection string uses a Key Vault reference.
348+
349+
Having issues? Check the [Troubleshooting section](#troubleshooting).
350+
335351
-----
336352

337353
## 3. Deploy sample code

0 commit comments

Comments
 (0)