|
| 1 | +--- |
| 2 | +title: Migrate applications to use passwordless authentication with Azure Service Bus |
| 3 | +titleSuffix: Azure Service Bus |
| 4 | +description: Learn to migrate existing Service Bus applications away from connection strings to use Azure AD and Azure RBAC for enhanced security. |
| 5 | +author: alexwolfmsft |
| 6 | +ms.author: alexwolf |
| 7 | +ms.reviewer: randolphwest |
| 8 | +ms.date: 12/07/2022 |
| 9 | +ms.service: service-bus |
| 10 | +ms.topic: how-to |
| 11 | +ms.custom: |
| 12 | + - devx-track-csharp |
| 13 | + - passwordless-dotnet |
| 14 | +ms.devlang: csharp |
| 15 | +--- |
| 16 | + |
| 17 | +# Migrate an application to use passwordless connections with Azure Service Bus |
| 18 | + |
| 19 | +Application requests to Azure Service Bus must be authenticated using either account access keys or passwordless connections. However, you should prioritize passwordless connections in your applications when possible. This tutorial explores how to migrate from traditional authentication methods to more secure, passwordless connections. |
| 20 | + |
| 21 | +## Security risks associated with access keys |
| 22 | + |
| 23 | +The following code example demonstrates how to connect to Azure Service Bus using a connection string that includes an access key. When you create a Service Bus, Azure generates these keys and connection strings automatically. Many developers gravitate towards this solution because it feels familiar to options they've worked with in the past. If your application currently uses connection strings, consider migrating to passwordless connections using the steps described in this document. |
| 24 | + |
| 25 | +```csharp |
| 26 | +var serviceBusClient = new ServiceBusClient( |
| 27 | + "<NAMESPACE-CONNECTION-STRING>", |
| 28 | + clientOptions); |
| 29 | +``` |
| 30 | + |
| 31 | +Connection strings should be used with caution. Developers must be diligent to never expose the keys in an unsecure location. Anyone who gains access to the key is able to authenticate. For example, if an account key is accidentally checked into source control, sent through an unsecure email, pasted into the wrong chat, or viewed by someone who shouldn't have permission, there's risk of a malicious user accessing the application. Instead, consider updating your application to use passwordless connections. |
| 32 | + |
| 33 | +## Migrate to passwordless connections |
| 34 | + |
| 35 | +[!INCLUDE [migrate-to-passwordless-overview](../../includes/passwordless/migration-guide/migrate-to-passwordless-overview.md)] |
| 36 | + |
| 37 | +## Steps to migrate an app to use passwordless authentication |
| 38 | + |
| 39 | +The following steps explain how to migrate an existing application to use passwordless connections instead of a key-based solution. You'll first configure a local development environment, and then apply those concepts to an Azure app hosting environment. These same migration steps should apply whether you're using access keys directly, or through connection strings. |
| 40 | + |
| 41 | +### Configure roles and users for local development authentication |
| 42 | + |
| 43 | +[!INCLUDE [service-bus-assign-roles-tabbed](../../includes/passwordless/service-bus/service-bus-assign-roles-tabbed.md)] |
| 44 | + |
| 45 | +### Sign-in and migrate the app code to use passwordless connections |
| 46 | + |
| 47 | +For local development, make sure you're authenticated with the same Azure AD account you assigned the role to for the Service Bus namespace. You can authenticate via the Azure CLI, Visual Studio, Azure PowerShell, or other tools such as IntelliJ. |
| 48 | + |
| 49 | +[!INCLUDE [default-azure-credential-sign-in](../../includes/passwordless/default-azure-credential-sign-in.md)] |
| 50 | + |
| 51 | +Next you'll need to update your code to use passwordless connections. |
| 52 | + |
| 53 | +1. To use `DefaultAzureCredential` in a .NET application, add the **Azure.Identity** NuGet package to your application. |
| 54 | + |
| 55 | + ```dotnetcli |
| 56 | + dotnet add package Azure.Identity |
| 57 | + ``` |
| 58 | + |
| 59 | +1. At the top of your `Program.cs` file, add the following `using` statement: |
| 60 | + |
| 61 | + ```csharp |
| 62 | + using Azure.Identity; |
| 63 | + ``` |
| 64 | + |
| 65 | +1. Identify the locations in your code that currently create a `ServiceBusClient` to connect to Azure Service Bus. This task is often handled in `Program.cs`, potentially as part of your service registration with the .NET dependency injection container. Update your code to match the following example: |
| 66 | + |
| 67 | + ```csharp |
| 68 | + var clientOptions = new ServiceBusClientOptions |
| 69 | + { |
| 70 | + TransportType = ServiceBusTransportType.AmqpWebSockets |
| 71 | + }; |
| 72 | + |
| 73 | + //TODO: Replace the "<SERVICE-BUS-NAMESPACE-NAME>" placeholder. |
| 74 | + client = new ServiceBusClient( |
| 75 | + "<SERVICE-BUS-NAMESPACE-NAME>.servicebus.windows.net", |
| 76 | + new DefaultAzureCredential(), |
| 77 | + clientOptions); |
| 78 | + ``` |
| 79 | + |
| 80 | +1. Make sure to update the Service Bus namespace in the URI of your `ServiceBusClient`. You can find the namespace on the overview page of the Azure portal. |
| 81 | + |
| 82 | +#### Run the app locally |
| 83 | + |
| 84 | +After making these code changes, run your application locally. The new configuration should pick up your local credentials, such as the Azure CLI, Visual Studio, or IntelliJ. The roles you assigned to your local dev user in Azure will allow your app to connect to the Azure service locally. |
| 85 | + |
| 86 | +### Configure the Azure hosting environment |
| 87 | + |
| 88 | +Once your application is configured to use passwordless connections and runs locally, the same code can authenticate to Azure services after it's deployed to Azure. For example, an application deployed to an Azure App Service instance that has a managed identity enabled can connect to Azure Service Bus. |
| 89 | + |
| 90 | +#### Create the managed identity using the Azure portal |
| 91 | + |
| 92 | +[!INCLUDE [create-managed-identity-portal](../../includes/passwordless/migration-guide/create-managed-identity-portal.md)] |
| 93 | + |
| 94 | +Alternatively, you can also enable managed identity on an Azure hosting environment using the Azure CLI. |
| 95 | + |
| 96 | +### [Service Connector](#tab/service-connector-identity) |
| 97 | + |
| 98 | +You can use Service Connector to create a connection between an Azure compute hosting environment and a target service using the Azure CLI. The CLI automatically handles creating a managed identity and assigns the proper role, as explained in the [portal instructions](#create-the-managed-identity-using-the-azure-portal). |
| 99 | + |
| 100 | +If you're using an Azure App Service, use the `az webapp connection` command: |
| 101 | + |
| 102 | +```azurecli |
| 103 | +az webapp connection create servicebus \ |
| 104 | + --resource-group <resource-group-name> \ |
| 105 | + --name <webapp-name> \ |
| 106 | + --target-resource-group <target-resource-group-name> \ |
| 107 | + --namespace <target-service-bus-namespace> \ |
| 108 | + --system-identity |
| 109 | +``` |
| 110 | + |
| 111 | +If you're using Azure Spring Apps, use the `az spring connection` command: |
| 112 | + |
| 113 | +```azurecli |
| 114 | +az spring connection create servicebus \ |
| 115 | + --resource-group <resource-group-name> \ |
| 116 | + --service <service-instance-name> \ |
| 117 | + --app <app-name> \ |
| 118 | + --deployment <deployment-name> \ |
| 119 | + --target-resource-group <target-resource-group> \ |
| 120 | + --namespace <target-service-bus-namespace> \ |
| 121 | + --system-identity |
| 122 | +``` |
| 123 | + |
| 124 | +If you're using Azure Container Apps, use the `az containerapp connection` command: |
| 125 | + |
| 126 | +```azurecli |
| 127 | +az containerapp connection create servicebus \ |
| 128 | + --resource-group <resource-group-name> \ |
| 129 | + --name <webapp-name> \ |
| 130 | + --target-resource-group <target-resource-group-name> \ |
| 131 | + --namespace <target-service-bus-namespace> \ |
| 132 | + --system-identity |
| 133 | +``` |
| 134 | + |
| 135 | +### [Azure App Service](#tab/app-service-identity) |
| 136 | + |
| 137 | +You can assign a managed identity to an Azure App Service instance with the [az webapp identity assign](/cli/azure/webapp/identity) command. |
| 138 | + |
| 139 | +```azurecli |
| 140 | +az webapp identity assign \ |
| 141 | + --resource-group <resource-group-name> \ |
| 142 | + --name <webapp-name> |
| 143 | +``` |
| 144 | + |
| 145 | +### [Azure Spring Apps](#tab/spring-apps-identity) |
| 146 | + |
| 147 | +You can assign a managed identity to an Azure Spring Apps instance with the [az spring app identity assign](/cli/azure/spring/app/identity) command. |
| 148 | + |
| 149 | +```azurecli |
| 150 | +az spring app identity assign \ |
| 151 | + --resource-group <resource-group-name> \ |
| 152 | + --name <app-name> \ |
| 153 | + --service <service-name> |
| 154 | +``` |
| 155 | + |
| 156 | +### [Azure Container Apps](#tab/container-apps-identity) |
| 157 | + |
| 158 | +You can assign a managed identity to an Azure Container Apps instance with the [az container app identity assign](/cli/azure/containerapp/identity) command. |
| 159 | + |
| 160 | +```azurecli |
| 161 | +az containerapp identity assign \ |
| 162 | + --resource-group <resource-group-name> \ |
| 163 | + --name <app-name> |
| 164 | +``` |
| 165 | + |
| 166 | +### [Azure Virtual Machines](#tab/virtual-machines-identity) |
| 167 | + |
| 168 | +You can assign a managed identity to a virtual machine with the [az vm identity assign](/cli/azure/vm/identity) command. |
| 169 | + |
| 170 | +```azurecli |
| 171 | +az vm identity assign \ |
| 172 | + --resource-group <resource-group-name> \ |
| 173 | + --name <virtual-machine-name> |
| 174 | +``` |
| 175 | + |
| 176 | +### [Azure Kubernetes Service](#tab/aks-identity) |
| 177 | + |
| 178 | +You can assign a managed identity to an Azure Kubernetes Service (AKS) instance with the [az aks update](/cli/azure/aks) command. |
| 179 | + |
| 180 | +```azurecli |
| 181 | +az aks update \ |
| 182 | + --resource-group <resource-group-name> \ |
| 183 | + --name <virtual-machine-name> |
| 184 | + --enable-managed-identity |
| 185 | +``` |
| 186 | + |
| 187 | +--- |
| 188 | + |
| 189 | +#### Assign roles to the managed identity |
| 190 | + |
| 191 | +Next, you need to grant permissions to the managed identity you created to access your Service Bus. You can do this by assigning a role to the managed identity, just like you did with your local development user. |
| 192 | + |
| 193 | +### [Service Connector](#tab/assign-role-service-connector) |
| 194 | + |
| 195 | +If you connected your services using the Service Connector you don't need to complete this step. The necessary configurations were handled for you: |
| 196 | + |
| 197 | +* If you selected a managed identity while creating the connection, a system-assigned managed identity was created for your app and assigned the **Azure Service Bus Data Owner** role on the Service Bus. |
| 198 | + |
| 199 | +* If you selected connection string, the connection string was added as an app environment variable. |
| 200 | + |
| 201 | +### [Azure portal](#tab/assign-role-azure-portal) |
| 202 | + |
| 203 | +1. Navigate to your Service Bus overview page and select **Access Control (IAM)** from the left navigation. |
| 204 | + |
| 205 | +1. Choose **Add role assignment**. |
| 206 | + |
| 207 | + :::image type="content" source="../../includes/passwordless/media/migration-add-role-small.png" alt-text="Screenshot showing how to add a role to a managed identity." lightbox="../../includes/passwordless/media/migration-add-role.png"::: |
| 208 | + |
| 209 | +1. In the **Role** search box, search for *Azure Service Bus Data Owner*, which is a common role used to manage data operations for blobs. You can assign whatever role is appropriate for your use case. Select the *Azure Service Bus Data Owner* from the list and choose **Next**. |
| 210 | + |
| 211 | +1. On the **Add role assignment** screen, for the **Assign access to** option, select **Managed identity**. Then choose **+Select members**. |
| 212 | + |
| 213 | +1. In the flyout, search for the managed identity you created by entering the name of your app service. Select the system assigned identity, and then choose **Select** to close the flyout menu. |
| 214 | + |
| 215 | + :::image type="content" source="../../includes/passwordless/media/migration-select-identity-small.png" alt-text="Screenshot showing how to select the assigned managed identity." lightbox="../../includes/passwordless/media/migration-select-identity.png"::: |
| 216 | + |
| 217 | +1. Select **Next** a couple times until you're able to select **Review + assign** to finish the role assignment. |
| 218 | + |
| 219 | +### [Azure CLI](#tab/assign-role-azure-cli) |
| 220 | + |
| 221 | +To assign a role at the resource level using the Azure CLI, you first must retrieve the resource ID using the `az servicebus show` command. You can filter the output properties using the --query parameter. |
| 222 | + |
| 223 | +```azurecli |
| 224 | +az servicebus show \ |
| 225 | + --resource-group '<your-resource-group-name>' \ |
| 226 | + --name '<your-service-bus-namespace>' \ |
| 227 | + --query id |
| 228 | +``` |
| 229 | + |
| 230 | +Copy the output ID from the preceding command. You can then assign roles using the `az role` command of the Azure CLI. |
| 231 | + |
| 232 | +```azurecli |
| 233 | +az role assignment create \ |
| 234 | + --assignee "<your-username>" \ |
| 235 | + --role "Azure Service Bus Data Owner" \ |
| 236 | + --scope "<your-resource-id>" |
| 237 | +``` |
| 238 | + |
| 239 | +--- |
| 240 | + |
| 241 | +#### Test the app |
| 242 | + |
| 243 | +After making these code changes, browse to your hosted application in the browser. Your app should be able to connect to the Service Bus successfully. Keep in mind that it may take several minutes for the role assignments to propagate through your Azure environment. Your application is now configured to run both locally and in a production environment without the developers having to manage secrets in the application itself. |
| 244 | + |
| 245 | +## Next steps |
| 246 | + |
| 247 | +In this tutorial, you learned how to migrate an application to passwordless connections. |
0 commit comments