Hello Folks,
I'm here to talk about an interesting topic today. I will be sharing my experience on how to create SFTP users for Azure Storage Accounts. This is a three-part series. In this first part, we will cover the basics of SFTP and how to create an SFTP user for an Azure Storage Account using Bicep. In the second part, we will discuss how to create a password for the SFTP user and how to use it to connect to the Azure Storage Account.
๐ Blob Storage and SFTPโ
As we all know, Azure Blob Storage now supports the SSH File Transfer Protocol (SFTP). This means you can use SFTP to transfer files to and from Azure Blob Storage. SFTP is a secure file transfer protocol that provides file access, file transfer, and file management over any reliable data stream. Before the introduction of the SFTP feature for Blob Storage, you could enable an SFTP endpoint for Blob Storage accounts by changing a single property in the storage account. Then, you can set up local SFTP Users in the storage account and start using it by accessing the storage account endpoint through port 22.
I will be going through the steps of creating an SFTP user for an Azure Storage Account using Bicep. Let's start with the basics.First, we need to create a new Bicep file. We will name it main.bicep
. Then, we will add the following code to the file for shaping variable structure.
targetScope = 'resourceGroup'
param storageAccount object = {
name: 'storageaccountsftp02'
type: 'Standard_GRS'
location: 'uksouth'
containers: [
{
name: 'container01'
users: [
'user01'
'user02'
]
}
{
name: 'container02'
users: [
'user03'
'user04'
]
}
]
}
I structured the variable as an object to define the scaffold of the storage account and its containers. This object includes the name
, type
, location
, and containers and users
. Each container is identified by a name and associated with users; considering the potential need for multiple local users per container, this block is designed as an array. We will use this variable schema to manage the creation of all resources efficiently.
๐ Creating the Storage Accountโ
Now, let's jump into exciting part โ actually building our storage account and setting up the blob endpoint. Imagine we're laying down the foundation of resources for our SFTP users. We will use the storageAccount
object to create the storage account and its blob service. Here is Bicep code looks like:
targetScope = 'resourceGroup'
param storageAccount object = {
name: 'storageaccountsftp02'
type: 'Standard_GRS'
location: 'uksouth'
containers: [
{
name: 'container01'
users: [
'user01'
'user02'
]
}
{
name: 'container02'
users: [
'user03'
'user04'
]
}
]
}
var containers = [for (item, idx) in contains(storageAccount, 'containers') ? storageAccount.containers : []: {
name: item.name
isUserExists: contains(item, 'users') ? true : false
users: contains(item, 'users') ? item.users : []
}
]
// Get the users for the containers
var sftpUsers = flatten(
map(containers, container =>
map(container.isUserExists == true ? container.users : [], user => {
containerName: container.name
name: user
})
))
// Create the storage accounts
resource stfpStorageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccount.name
location: storageAccount.location
sku: {
name: storageAccount.type
}
kind: 'StorageV2'
properties: {
accessTier: 'Hot'
isHnsEnabled: true
isSftpEnabled: true
}
}
// Initialise the blob service
resource stfpStorageAccountBlobService 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = {
parent: stfpStorageAccount
name: 'default'
properties: {
containerDeleteRetentionPolicy: {
enabled: true
days: 30
}
deleteRetentionPolicy: {
enabled: true
days: 30
}
}
}
Let me briefly explain why I have come up with the specific variables in the code we have above and list all of them for a better understanding
containers
variable: I need to ensure the storage account object includes containers and an indication of whether users are associated with them. If so, I will create a list of containers as objects and indicate whether users exist with isUserExists.sftpUsers
variable: It's necessary to identify the users associated with each container. This allows me to iterate through my resource block for each user to create an SFTP user for each container.
My first attempt to deploy the Bicep file into my resource group was successful. I was able to see in what-if
mode that the storage account and blob service were created as expected.
Resource and property changes are indicated with these symbols:
+ Create
* Ignore
The deployment will update the following scope:
Scope: "/subscriptions/*********/resourceGroups/******"
+ Microsoft.Storage/storageAccounts/storageaccountsftp02 [2023-01-01]
apiVersion: "2023-01-01"
id: "/subscriptions/***/resourceGroups/******/providers/Microsoft.Storage/storageAccounts/storageaccountsftp02"
kind: "StorageV2"
location: "uksouth"
name: "storageaccountsftp02"
properties.accessTier: "Hot"
properties.isHnsEnabled: true
properties.isSftpEnabled: true
sku.name: "Standard_GRS"
type: "Microsoft.Storage/storageAccounts"
+ Microsoft.Storage/storageAccounts/storageaccountsftp02/blobServices/default [2023-01-01]
apiVersion: "2023-01-01"
id: "/subscriptions/***/resourceGroups/******/providers/Microsoft.Storage/storageAccounts/storageaccountsftp02/blobServices/default"
name: "default"
properties.containerDeleteRetentionPolicy.days: 30
properties.containerDeleteRetentionPolicy.enabled: true
properties.deleteRetentionPolicy.days: 30
properties.deleteRetentionPolicy.enabled: true
type: "Microsoft.Storage/storageAccounts/blobServices"
Resource changes: 2 to create, 0 to ignore.
In this part of our series, we've covered everything that I want, focusing on creating the storage account and initializing the blob service without getting sidetracked. So far, we've looked at how to set up the storage account and blob service. Next, we'll move on to creating SFTP users for the storage account and containers. We'll also walk through how to create a password for these users and how to use it to connect to the Azure Storage Account.
Stay tuned for the next part of the series!