|
| 1 | +--- |
| 2 | +title: Restrict data exfiltration to Azure Storage - Azure CLI |
| 3 | +description: In this article, you learn how to limit and restrict virtual network data exfiltration to Azure Storage resources with virtual network service endpoint policies using the Azure CLI. |
| 4 | +services: virtual-network |
| 5 | +documentationcenter: virtual-network |
| 6 | +author: rdhillon |
| 7 | +manager: '' |
| 8 | +editor: '' |
| 9 | +tags: azure-resource-manager |
| 10 | +Customer intent: I want only specific Azure Storage account to be allowed access from a virtual network subnet. |
| 11 | + |
| 12 | +ms.assetid: |
| 13 | +ms.service: virtual-network |
| 14 | +ms.devlang: azurecli |
| 15 | +ms.topic: article |
| 16 | +ms.tgt_pltfrm: virtual-network |
| 17 | +ms.workload: infrastructure-services |
| 18 | +ms.date: 02/03/2020 |
| 19 | +ms.author: rdhillon |
| 20 | +ms.custom: |
| 21 | +--- |
| 22 | + |
| 23 | +# Manage data exfiltration to Azure Storage accounts with virtual network service endpoint policies using the Azure CLI |
| 24 | + |
| 25 | +Virtual network service endpoint policies enable you to apply access control on Azure Storage accounts from within a virtual network over service endpoints. This is a key to securing your workloads, managing what storage accounts are allowed and where data exfiltration is allowed. |
| 26 | +In this article, you learn how to: |
| 27 | + |
| 28 | +* Create a virtual network and add a subnet. |
| 29 | +* Enable service endpoint for Azure Storage. |
| 30 | +* Create two Azure Storage accounts and allow network access to it from the subnet created above. |
| 31 | +* Create a service endpoint policy to allow access only to one of the storage accounts. |
| 32 | +* Deploy a virtual machine (VM) to the subnet. |
| 33 | +* Confirm access to the allowed storage account from the subnet. |
| 34 | +* Confirm access is denied to the non-allowed storage account from the subnet. |
| 35 | + |
| 36 | +If you don't have an Azure subscription, create a [free account](https://azure.microsoft.com/free/?WT.mc_id=A261C142F) before you begin. |
| 37 | + |
| 38 | +[!INCLUDE [cloud-shell-try-it.md](../../includes/cloud-shell-try-it.md)] |
| 39 | + |
| 40 | +If you choose to install and use the CLI locally, this quickstart requires that you are running the Azure CLI version 2.0.28 or later. To find the version, run `az --version`. If you need to install or upgrade, see [Install Azure CLI]( /cli/azure/install-azure-cli). |
| 41 | + |
| 42 | +## Create a virtual network |
| 43 | + |
| 44 | +Before creating a virtual network, you have to create a resource group for the virtual network, and all other resources created in this article. Create a resource group with [az group create](/cli/azure/group). The following example creates a resource group named *myResourceGroup* in the *eastus* location. |
| 45 | + |
| 46 | +```azurecli-interactive |
| 47 | +az group create \ |
| 48 | + --name myResourceGroup \ |
| 49 | + --location eastus |
| 50 | +``` |
| 51 | + |
| 52 | +Create a virtual network with one subnet with [az network vnet create](/cli/azure/network/vnet). |
| 53 | + |
| 54 | +```azurecli-interactive |
| 55 | +az network vnet create \ |
| 56 | + --name myVirtualNetwork \ |
| 57 | + --resource-group myResourceGroup \ |
| 58 | + --address-prefix 10.0.0.0/16 \ |
| 59 | + --subnet-name Private \ |
| 60 | + --subnet-prefix 10.0.0.0/24 |
| 61 | +``` |
| 62 | + |
| 63 | +## Enable a service endpoint |
| 64 | + |
| 65 | +In this example, a service endpoint for *Microsoft.Storage* is created for the subnet *Private*: |
| 66 | + |
| 67 | +```azurecli-interactive |
| 68 | +az network vnet subnet create \ |
| 69 | + --vnet-name myVirtualNetwork \ |
| 70 | + --resource-group myResourceGroup \ |
| 71 | + --name Private \ |
| 72 | + --address-prefix 10.0.0.0/24 \ |
| 73 | + --service-endpoints Microsoft.Storage |
| 74 | +``` |
| 75 | + |
| 76 | +## Restrict network access for a subnet |
| 77 | + |
| 78 | +Create a network security group with [az network nsg create](/cli/azure/network/nsg). The following example creates a network security group named *myNsgPrivate*. |
| 79 | + |
| 80 | +```azurecli-interactive |
| 81 | +az network nsg create \ |
| 82 | + --resource-group myResourceGroup \ |
| 83 | + --name myNsgPrivate |
| 84 | +``` |
| 85 | + |
| 86 | +Associate the network security group to the *Private* subnet with [az network vnet subnet update](/cli/azure/network/vnet/subnet). The following example associates the *myNsgPrivate* network security group to the *Private* subnet: |
| 87 | + |
| 88 | +```azurecli-interactive |
| 89 | +az network vnet subnet update \ |
| 90 | + --vnet-name myVirtualNetwork \ |
| 91 | + --name Private \ |
| 92 | + --resource-group myResourceGroup \ |
| 93 | + --network-security-group myNsgPrivate |
| 94 | +``` |
| 95 | + |
| 96 | +Create security rules with [az network nsg rule create](/cli/azure/network/nsg/rule). The rule that follows allows outbound access to the public IP addresses assigned to the Azure Storage service: |
| 97 | + |
| 98 | +```azurecli-interactive |
| 99 | +az network nsg rule create \ |
| 100 | + --resource-group myResourceGroup \ |
| 101 | + --nsg-name myNsgPrivate \ |
| 102 | + --name Allow-Storage-All \ |
| 103 | + --access Allow \ |
| 104 | + --protocol "*" \ |
| 105 | + --direction Outbound \ |
| 106 | + --priority 100 \ |
| 107 | + --source-address-prefix "VirtualNetwork" \ |
| 108 | + --source-port-range "*" \ |
| 109 | + --destination-address-prefix "Storage" \ |
| 110 | + --destination-port-range "*" |
| 111 | +``` |
| 112 | + |
| 113 | +Each network security group contains several [default security rules](security-overview.md#default-security-rules). The rule that follows overrides a default security rule that allows outbound access to all public IP addresses. The `destination-address-prefix "Internet"` option denies outbound access to all public IP addresses. The previous rule overrides this rule, due to its higher priority, which allows access to the public IP addresses of Azure Storage. |
| 114 | + |
| 115 | +```azurecli-interactive |
| 116 | +az network nsg rule create \ |
| 117 | + --resource-group myResourceGroup \ |
| 118 | + --nsg-name myNsgPrivate \ |
| 119 | + --name Deny-Internet-All \ |
| 120 | + --access Deny \ |
| 121 | + --protocol "*" \ |
| 122 | + --direction Outbound \ |
| 123 | + --priority 110 \ |
| 124 | + --source-address-prefix "VirtualNetwork" \ |
| 125 | + --source-port-range "*" \ |
| 126 | + --destination-address-prefix "Internet" \ |
| 127 | + --destination-port-range "*" |
| 128 | +``` |
| 129 | + |
| 130 | +The following rule allows SSH traffic inbound to the subnet from anywhere. The rule overrides a default security rule that denies all inbound traffic from the internet. SSH is allowed to the subnet so that connectivity can be tested in a later step. |
| 131 | + |
| 132 | +```azurecli-interactive |
| 133 | +az network nsg rule create \ |
| 134 | + --resource-group myResourceGroup \ |
| 135 | + --nsg-name myNsgPrivate \ |
| 136 | + --name Allow-SSH-All \ |
| 137 | + --access Allow \ |
| 138 | + --protocol Tcp \ |
| 139 | + --direction Inbound \ |
| 140 | + --priority 120 \ |
| 141 | + --source-address-prefix "*" \ |
| 142 | + --source-port-range "*" \ |
| 143 | + --destination-address-prefix "VirtualNetwork" \ |
| 144 | + --destination-port-range "22" |
| 145 | +``` |
| 146 | + |
| 147 | +## Restrict network access to Azure Storage resources |
| 148 | + |
| 149 | +This section lists steps to restrict network access for an Azure Storage account from the given subnet in a Virtual network via service endpoint. |
| 150 | + |
| 151 | +### Create a storage account |
| 152 | + |
| 153 | +Create two Azure storage accounts with [az storage account create](/cli/azure/storage/account). |
| 154 | + |
| 155 | +```azurecli-interactive |
| 156 | +storageAcctName1="allowedstorageacc" |
| 157 | +
|
| 158 | +az storage account create \ |
| 159 | + --name $storageAcctName1 \ |
| 160 | + --resource-group myResourceGroup \ |
| 161 | + --sku Standard_LRS \ |
| 162 | + --kind StorageV2 |
| 163 | +
|
| 164 | +storageAcctName2="notallowedstorageacc" |
| 165 | +
|
| 166 | +az storage account create \ |
| 167 | + --name $storageAcctName2 \ |
| 168 | + --resource-group myResourceGroup \ |
| 169 | + --sku Standard_LRS \ |
| 170 | + --kind StorageV2 |
| 171 | +``` |
| 172 | + |
| 173 | +After the storage accounts are created, retrieve the connection string for the storage accounts into a variable with [az storage account show-connection-string](/cli/azure/storage/account). The connection string is used to create a file share in a later step. |
| 174 | + |
| 175 | +```azurecli-interactive |
| 176 | +saConnectionString1=$(az storage account show-connection-string \ |
| 177 | + --name $storageAcctName1 \ |
| 178 | + --resource-group myResourceGroup \ |
| 179 | + --query 'connectionString' \ |
| 180 | + --out tsv) |
| 181 | +
|
| 182 | +saConnectionString2=$(az storage account show-connection-string \ |
| 183 | + --name $storageAcctName2 \ |
| 184 | + --resource-group myResourceGroup \ |
| 185 | + --query 'connectionString' \ |
| 186 | + --out tsv) |
| 187 | +``` |
| 188 | + |
| 189 | +<a name="account-key"></a>View the contents of the variable and note the value for **AccountKey** returned in the output, because it's used in a later step. |
| 190 | + |
| 191 | +```azurecli-interactive |
| 192 | +echo $saConnectionString1 |
| 193 | +
|
| 194 | +echo $saConnectionString2 |
| 195 | +``` |
| 196 | + |
| 197 | +### Create a file share in the storage account |
| 198 | + |
| 199 | +Create a file share in the storage account with [az storage share create](/cli/azure/storage/share). In a later step, this file share is mounted to confirm network access to it. |
| 200 | + |
| 201 | +```azurecli-interactive |
| 202 | +az storage share create \ |
| 203 | + --name my-file-share1 \ |
| 204 | + --quota 2048 \ |
| 205 | + --connection-string $saConnectionString1 > /dev/null |
| 206 | +
|
| 207 | +az storage share create \ |
| 208 | + --name my-file-share2 \ |
| 209 | + --quota 2048 \ |
| 210 | + --connection-string $saConnectionString2 > /dev/null |
| 211 | +``` |
| 212 | + |
| 213 | +### Deny all network access to the storage account |
| 214 | + |
| 215 | +By default, storage accounts accept network connections from clients in any network. To limit access to selected networks, change the default action to *Deny* with [az storage account update](/cli/azure/storage/account). Once network access is denied, the storage account is not accessible from any network. |
| 216 | + |
| 217 | +```azurecli-interactive |
| 218 | +az storage account update \ |
| 219 | + --name $storageAcctName1 \ |
| 220 | + --resource-group myResourceGroup \ |
| 221 | + --default-action Deny |
| 222 | +
|
| 223 | +az storage account update \ |
| 224 | + --name $storageAcctName2 \ |
| 225 | + --resource-group myResourceGroup \ |
| 226 | + --default-action Deny |
| 227 | +``` |
| 228 | + |
| 229 | +### Enable network access from virtual network subnet |
| 230 | + |
| 231 | +Allow network access to the storage account from the *Private* subnet with [az storage account network-rule add](/cli/azure/storage/account/network-rule). |
| 232 | + |
| 233 | +```azurecli-interactive |
| 234 | +az storage account network-rule add \ |
| 235 | + --resource-group myResourceGroup \ |
| 236 | + --account-name $storageAcctName1 \ |
| 237 | + --vnet-name myVirtualNetwork \ |
| 238 | + --subnet Private |
| 239 | +
|
| 240 | +az storage account network-rule add \ |
| 241 | + --resource-group myResourceGroup \ |
| 242 | + --account-name $storageAcctName2 \ |
| 243 | + --vnet-name myVirtualNetwork \ |
| 244 | + --subnet Private |
| 245 | +``` |
| 246 | + |
| 247 | +## Allow access to only the valid storage account via service endpoint policy |
| 248 | + |
| 249 | +Azure Service Endpoint policies are only available for Azure Storage. So, we'll be enabling Service Endpoint for *Microsoft.Storage* on this subnet for this example setup. |
| 250 | + |
| 251 | +Service endpoint policies are applied over service endpoints. We will start by creating a service endpoint policy. We will then create the policy definitions under this policy for Azure Storage accounts to be whitelisted for this subnet |
| 252 | + |
| 253 | +Create a service endpoint policy |
| 254 | + |
| 255 | +```azurecli-interactive |
| 256 | +az network service-endpoint policy create \ |
| 257 | + --resource-group myResourceGroup \ |
| 258 | + --name mysepolicy \ |
| 259 | + --location eastus |
| 260 | +``` |
| 261 | + |
| 262 | +Save the resource URI for the allowed storage account in a variable. Before executing the command below, replace *\<your-subscription-id>* with actual value of your subscription ID. |
| 263 | + |
| 264 | +```azurecli-interactive |
| 265 | +$serviceResourceId="/subscriptions/<your-subscription-id>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/allowedstorageacc" |
| 266 | +``` |
| 267 | + |
| 268 | +Create & add a policy definition for allowing the above Azure Storage account to the service endpoint policy |
| 269 | + |
| 270 | +```azurecli-interactive |
| 271 | +az network service-endpoint policy-definition create \ |
| 272 | + --resource-group myResourceGroup \ |
| 273 | + --policy-name mysepolicy \ |
| 274 | + --name mypolicydefinition \ |
| 275 | + --service "Microsoft.Storage" \ |
| 276 | + --service-resources $serviceResourceId |
| 277 | +``` |
| 278 | + |
| 279 | +And update the virtual network subnet to associate with it the service endpoint policy created in the previous step |
| 280 | + |
| 281 | +```azurecli-interactive |
| 282 | +az network vnet subnet update \ |
| 283 | + --vnet-name myVirtualNetwork \ |
| 284 | + --resource-group myResourceGroup \ |
| 285 | + --name Private \ |
| 286 | + --service-endpoints Microsoft.Storage \ |
| 287 | + --service-endpoint-policy mysepolicy |
| 288 | +``` |
| 289 | + |
| 290 | +## Validate access restriction to Azure Storage accounts from the virtual network |
| 291 | + |
| 292 | +### Create the virtual machine |
| 293 | + |
| 294 | +To test network access to a storage account, deploy a VM to the subnet. |
| 295 | + |
| 296 | +Create a VM in the *Private* subnet with [az vm create](/cli/azure/vm). If SSH keys do not already exist in a default key location, the command creates them. To use a specific set of keys, use the `--ssh-key-value` option. |
| 297 | + |
| 298 | +```azurecli-interactive |
| 299 | +az vm create \ |
| 300 | + --resource-group myResourceGroup \ |
| 301 | + --name myVmPrivate \ |
| 302 | + --image UbuntuLTS \ |
| 303 | + --vnet-name myVirtualNetwork \ |
| 304 | + --subnet Private \ |
| 305 | + --generate-ssh-keys |
| 306 | +``` |
| 307 | + |
| 308 | +The VM takes a few minutes to create. After creation, take note of the **publicIpAddress** in the output returned. This address is used to access the VM from the internet in a later step. |
| 309 | + |
| 310 | +### Confirm access to storage account |
| 311 | + |
| 312 | +SSH into the *myVmPrivate* VM. Replace *\<publicIpAddress>* with the public IP address of your *myVmPrivate* VM. |
| 313 | + |
| 314 | +```bash |
| 315 | +ssh <publicIpAddress> |
| 316 | +``` |
| 317 | + |
| 318 | +Create a folder for a mount point: |
| 319 | + |
| 320 | +```bash |
| 321 | +sudo mkdir /mnt/MyAzureFileShare1 |
| 322 | +``` |
| 323 | + |
| 324 | +Mount the Azure file share to the directory you created. Before executing the command below, replace *\<storage-account-key>* with value of *AccountKey* from **$saConnectionString1**. |
| 325 | + |
| 326 | +```bash |
| 327 | +sudo mount --types cifs //allowedstorageacc.file.core.windows.net/my-file-share /mnt/MyAzureFileShare1 --options vers=3.0,username=allowedstorageacc,password=<storage-account-key>,dir_mode=0777,file_mode=0777,serverino |
| 328 | +``` |
| 329 | + |
| 330 | +You receive the `user@myVmPrivate:~$` prompt. The Azure file share successfully mounted to */mnt/MyAzureFileShare*. |
| 331 | + |
| 332 | +### Confirm access is denied to storage account |
| 333 | + |
| 334 | +From the same VM *myVmPrivate*, create a directory for a mount point: |
| 335 | + |
| 336 | +```bash |
| 337 | +sudo mkdir /mnt/MyAzureFileShare2 |
| 338 | +``` |
| 339 | + |
| 340 | +Attempt to mount the Azure file share from storage account *notallowedstorageacc* to the directory you created. |
| 341 | +This article assumes you deployed the latest version of Ubuntu. If you are using earlier versions of Ubuntu, see [Mount on Linux](../storage/files/storage-how-to-use-files-linux.md?toc=%2fazure%2fvirtual-network%2ftoc.json) for additional instructions about mounting file shares. |
| 342 | + |
| 343 | +Before executing the command below, replace *\<storage-account-key>* with value of *AccountKey* from **$saConnectionString2**. |
| 344 | + |
| 345 | +```bash |
| 346 | +sudo mount --types cifs //notallowedstorageacc.file.core.windows.net/my-file-share /mnt/MyAzureFileShare2 --options vers=3.0,username=notallowedstorageacc,password=<storage-account-key>,dir_mode=0777,file_mode=0777,serverino |
| 347 | +``` |
| 348 | + |
| 349 | +Access is denied, and you receive a `mount error(13): Permission denied` error, because this storage account is not in the allow list of the service endpoint policy we applied to the subnet. |
| 350 | + |
| 351 | +Exit the SSH session to the *myVmPublic* VM. |
| 352 | + |
| 353 | +## Clean up resources |
| 354 | + |
| 355 | +When no longer needed, use [az group delete](/cli/azure) to remove the resource group and all of the resources it contains. |
| 356 | + |
| 357 | +```azurecli-interactive |
| 358 | +az group delete --name myResourceGroup --yes |
| 359 | +``` |
| 360 | + |
| 361 | +## Next steps |
| 362 | + |
| 363 | +In this article, you applied a service endpoint policy over an Azure virtual network service endpoint to Azure Storage. You created Azure Storage accounts and limited network access to only certain storage accounts (and thus denied others) from a virtual network subnet. To learn more about service endpoint policies, see [Service endpoints policies overview](virtual-network-service-endpoint-policies-overview.md). |
0 commit comments