This article is contributed. See the original author and article here.

Public read access to Azure containers and blob storage is an easier and convenient way to share data, however it also possesses security risk. For better and enhanced security, public access to entire storage account can be disallow regardless of the public access setting for an individual container present within the storage container. By disallowing public access to storage prevents a user from enabling public access for a container in respective storage account.


Remediating secure access to storage account across subscriptions and storage account can be tedious as we grow. Below solution can help you to disallow public access to storage account at scale. We can extract list of all storage account from azure subscriptions and use the same csv as input to below solution to disallow storage account containers at scale across all your subscriptions.


 



Pre-Requisite:

  Az Modules must be installed

 – Service Principal created as part of Step 1, must be having contributor level access to subscriptions

 

Steps to follow:


Step 1: Create a service principal



Post creation of service principal, please retrieve below values.


  1. Tenant Id

  2. Client Secret

  3. Client Id


 


Step 2: Create a PowerShell function which will be used in generating authorization token

function Get-apiHeader{
[CmdletBinding()]
Param
(
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $TENANTID,
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $ClientId,
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $PasswordClient,
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $resource
)
$tokenresult=Invoke-RestMethod -Uri https://login.microsoftonline.com/$TENANTID/oauth2/token?api-version=1.0 -Method Post -Body @{"grant_type" = "client_credentials"; "resource" = "https://$resource/"; "client_id" = "$ClientId"; "client_secret" = "$PasswordClient" }
$token=$tokenresult.access_token
$Header=@{
  'Authorization'="Bearer $token"
  'Host'="$resource"
  'Content-Type'='application/json'
  }
return $Header
}


 

Step 3: Invoke API to retrieve authorization token using function created in above step



Note: Replace $TenantId, $ClientId and $ClientSecret with value captured in step 1

$AzureApiheaders = Get-apiHeader -TENANTID $TenantId -ClientId $ClientId -PasswordClient $ClientSecret -resource "management.azure.com"


 



Step 4: Extracting list of storage accounts across accessible subscriptions

$subscriptionList =  Get-AzSubscription
$subscriptionIdList = $subscriptionList.Id


foreach($subscriptionId in $subscriptionIdList)
{
$resourceURL = "https://management.azure.com/subscriptions/$($subscriptionId)/providers/Microsoft.Storage/storageAccounts?api-version=2021-01-01"
$resourcedetails=(Invoke-RestMethod  -Uri $resourceURL -Headers $AzureApiheaders -Method GET)
$TableData = $resourcedetails.value.ID
}

 



Step 5: Enable secure access to storage account

foreach($Data in $TableData)
{
  #Select Current Subscription and get All Storage Accounts
  $resourceid=$Data
  $resourceURL="https://management.azure.com$($resourceid)?api-version=2021-02-01"
  $resourcedetails=(Invoke-RestMethod  -Uri $resourceURL -Headers $AzureApiheaders -Method GET)
  $resourcelocation=$resourcedetails.location
  $permissions=$resourcedetails.properties.allowBlobPublicAccess
  if($permissions -eq $false)
  {
   Write-Output "Public access to Storage Account: $($resourcedetails.name) is already disabled"
  }
  Else 
  {
   Write-Output "Changing ACL for Storage Account: $($resourcedetails.name)" 
   $body = @"
   {
    "location":"$($resourcelocation)",
    "properties": {
         "allowBlobPublicAccess":  "false"
                  }
   }"@
   Invoke-RestMethod -Uri $resourceURL -Method Put -Headers $AzureApiheaders -Body $body 
  }
}

 


Overall Script:

function Get-apiHeader{
[CmdletBinding()]
Param
(
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $TENANTID,
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $ClientId,
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $PasswordClient,
 [Parameter(Mandatory=$true)]
 [System.String]
 [ValidateNotNullOrEmpty()]
 $resource
)
$tokenresult=Invoke-RestMethod -Uri https://login.microsoftonline.com/$TENANTID/oauth2/token?api-version=1.0 -Method Post -Body @{"grant_type" = "client_credentials"; "resource" = "https://$resource/"; "client_id" = "$ClientId"; "client_secret" = "$PasswordClient" }
$token=$tokenresult.access_token
$Header=@{
  'Authorization'="Bearer $token"
  'Host'="$resource"
  'Content-Type'='application/json'
  }
return $Header
}

$AzureApiheaders = Get-apiHeader -TENANTID $TenantId -ClientId $ClientId -PasswordClient $ClientSecret -resource "management.azure.com"

$subscriptionList =  Get-AzSubscription
$subscriptionIdList = $subscriptionList.Id

foreach($subscriptionId in $subscriptionIdList)
{
$resourceURL = "https://management.azure.com/subscriptions/$($subscriptionId)/providers/Microsoft.Storage/storageAccounts?api-version=2021-01-01"
$resourcedetails=(Invoke-RestMethod  -Uri $resourceURL -Headers $AzureApiheaders -Method GET)
$TableData = $resourcedetails.value.ID
foreach($Data in $TableData)
{
  #Select Current Subscription and get All Storage Accounts
  $resourceid=$Data
  $resourceURL="https://management.azure.com$($resourceid)?api-version=2021-02-01"
  $resourcedetails=(Invoke-RestMethod  -Uri $resourceURL -Headers $AzureApiheaders -Method GET)
  $resourcelocation=$resourcedetails.location
  $permissions=$resourcedetails.properties.allowBlobPublicAccess
  if($permissions -eq $false)
  {
   Write-Output "Public access to Storage Account: $($resourcedetails.name) is already disabled"
  }
  Else 
  {
   Write-Output "Changing ACL for Storage Account: $($resourcedetails.name)" 
   $body = @"
   {
    "location":"$($resourcelocation)",
    "properties": {
         "allowBlobPublicAccess":  "false"
                  }
   }"@
   Invoke-RestMethod -Uri $resourceURL -Method Put -Headers $AzureApiheaders -Body $body 
  }
}
}

 


References:


https://docs.microsoft.com/en-us/azure/storage/blobs/anonymous-read-access-configure?tabs=powershell









Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.