Skip to content

Commit 67a5ebd

Browse files
Document Entra ID access for Azure Blob Storage SFTP
Add documentation for Entra ID based access for Azure Blob Storage SFTP, detailing features, benefits, and connection instructions.
1 parent eb1c882 commit 67a5ebd

1 file changed

Lines changed: 342 additions & 0 deletions

File tree

Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
---
2+
title: Getting started - Entra ID based access for Azure Blob Storage SFTP
3+
author: Jeevan Manoj
4+
ms.date: 02/24/2026
5+
ms.author: normesta
6+
7+
---
8+
Getting started - Entra ID based access for Azure Blob Storage SFTP
9+
10+
**This feature is currently in public preview and once enabled it is applicable across all storage accounts within the entire subscription. This feature is currently in public preview and once enabled it is applicable across all storage accounts within the entire subscription. **
11+
12+
Azure Blob Storage SFTP now supports Entra ID-based access in public preview. Previously, Azure Blob Storage SFTP only supported local user-based access, requiring either a password or an SSH private key for authentication. With this new feature, users can leverage their Entra ID or Entra External Identities to connect to Azure storage accounts via SFTP without the need to create and maintain local users.
13+
14+
Entra ID-based access brings a host of benefits, including Role Based Access Control (RBAC), Multi-factor Authentication, and Entra ID Access Control Lists (ACLs) to Azure Blob Storage SFTP.
15+
16+
# Key benefits
17+
18+
1. Eliminate Local User Management
19+
20+
With Entra ID-based access, there is no need to create, rotate, or maintain local SFTP users per storage account. Authentication is handled entirely by Entra ID, significantly reducing operational overhead and configuration sprawl
21+
22+
1. Enterprisegrade Identity & Security
23+
24+
SFTP access is backed by Entra ID, enabling:
25+
26+
- Centralized identity lifecycle management
27+
- Strong authentication (including MFA via Entra ID)
28+
- Consistent security posture aligned with enterprise IAM standards
29+
- This improves security compared to static, longlived local credentials
30+
31+
1. Native Azure RBAC, ABAC & ACL Integration
32+
33+
Authorization for SFTP mirrors Azure Blob Storage's existing access control model:
34+
35+
- RoleBased Access Control (RBAC)
36+
- AttributeBased Access Control (ABAC)
37+
- POSIXstyle Access Control Lists (ACLs)
38+
- Users can apply the same roles and permissions used for REST, SDK, and Portal access—now extended seamlessly to SFTP.
39+
40+
1. Faster SFTP Onboarding
41+
42+
Because Entra ID accounts are ubiquitous, users can:
43+
44+
- Reuse existing users, groups, and service principals
45+
- Avoid timeconsuming local user creation and key distribution
46+
- Get SFTP up and running faster with fewer setup steps
47+
- This significantly shortens timetovalue for SFTPbased workflows.
48+
49+
1. Secure External Collaboration
50+
51+
Using Entra ID External Identities, customers can securely grant SFTP access to partners and vendors without managing separate identity systems—while maintaining full control and auditability.
52+
53+
## Overview
54+
55+
Below is a high-level overview of the key steps involved in this process. In summary, you'll first authenticate using Entra ID, then obtain an OpenSSH certificate, and finally connect to Azure Blob Storage SFTP using a compatible client or SDK. Each of these steps is outlined in more detail in the following sections.
56+
57+
58+
59+
1. Authenticate with Entra ID via Azure CLI, PS, SDK etc.
60+
2. Get an OpenSSH Certificate from Entra ID by passing a public key
61+
3. Use any SFTP Client/SDK which supports OpenSSH certificates to connect to Azure Storage with the OpenSSH Certificate and the public key from step 2.
62+
63+
> [!NOTE]
64+
> For Step 3 Password based authentication won't be supported since there are no SFTP clients that have native Entra ID integration to allow an Entra ID UX to accept the passwords.
65+
66+
:::image type="content" source="media/secure-file-transfer-protocol-support-entra-id-based-access/overview-flow-chart.png" alt-text="Flow chart demonstrating the Open SSH certificate workflow":::
67+
68+
69+
70+
# **Connecting to Azure Blob Storage with Entra IDs **
71+
72+
## **Register for the preview feature 'SFTP Entra ID Support' on your Azure subscription**
73+
74+
You can register for public preview features by following this [guide](/azure/azure-resource-manager/management/preview-features). Looks for a preview feature named" SFTP Entra ID Support".
75+
76+
## **Generate OpenSSH certificate**
77+
78+
# [Azure CLI](#tab/azurecli)
79+
80+
Generate the OpenSSH certificate with az cli [az sftp](/cli/azure/sftp) as below
81+
82+
az login
83+
az sftp cert --file /my_cert.pub
84+
85+
> [!NOTE]
86+
> The certificate will be valid only for 65 minutes for security reasons & the command will have to be rerun to obtain certificate again.
87+
88+
> [!NOTE]
89+
> Currently, retrieving SSH certificates is only supported with [az cli](/cli/azure/ssh) or Azure PowerShell. We do not yet have Azure Portal support for downloading SSH certificates.
90+
91+
92+
Optionally, you can generate your own SSH key pair and use them while downloading the certificate as follows.
93+
94+
Generate SSH key pair: You must use RSA keys, since Entra only supports generating RSA certificates.
95+
96+
ssh-keygen -t rsa
97+
1. key files will be generated once the above is executed. They are:
98+
99+
| **File Name** | **Key Type** |
100+
|---|---|
101+
| **id_rsa** | Private key |
102+
| **id_rsa.pub** | Public key |
103+
104+
105+
Use the command below to generate the SSH certificate with the keys generated
106+
107+
`az login`<br>az sftp cert --public-key-file /id_rsa.pub --file /my_cert.pub
108+
109+
If you are using a Service Principal, you can login either using a Client Secret or a Certificate:
110+
111+
Certificate:
112+
az login --service-principal -u <application_id_or_client_id> --tenant <tenant_id> --certificate <path_to_certificate>
113+
Client Secret:
114+
az login --service-principal -u <application_id_or_client_id> -p <secret_value> --tenant <tenant_id>
115+
Afer this you can just run the same command to download the certificate:
116+
az sftp cert --public-key-file /id_rsa.pub --file /my_cert.pub
117+
118+
# [Azure PowerShell](#tab/azurepowershell)
119+
120+
Generate the OpenSSH certificate with [PowersShell Az.Sftp](https://www.powershellgallery.com/packages/Az.Sftp/0.1.0) as below
121+
122+
Connect-AzAccount
123+
New-AzSftpCertificate -CertificatePath "\my_cert.cert"
124+
Optionally, use the command below to generate the OpenSSH certificate with your SSH keys
125+
126+
New-AzSftpCertificate -PublicKeyFile "\id_rsa.pub" -CertificatePath "\my_cert.cert"
127+
Learn more about the PowerShell module [here](/powershell/module/az.sftp/).
128+
129+
> [!NOTE]
130+
> Powershell currently does not support Service Principals and managed Identity Sign ins.
131+
132+
### MSAL.NET
133+
134+
```dotnetcli
135+
using Microsoft.Identity.Client;
136+
using Microsoft.Identity.Client.SSHCertificates;
137+
using Newtonsoft.Json;
138+
using System.Security.Cryptography;
139+
using System.Text;
140+
public class Program
141+
{
142+
private const string AZURE_CLI_CLIENT_ID = "<your-azure-cli-client-id>";
143+
private const string MY_TENANT_ID = "<your-tenant-id>";
144+
public static async Task Main(string[] args)
145+
{
146+
var options = new PublicClientApplicationOptions
147+
{
148+
ClientId = AZURE_CLI_CLIENT_ID,
149+
};
150+
var app = PublicClientApplicationBuilder.CreateWithApplicationOptions(options)
151+
.WithTenantId(MY_TENANT_ID)
152+
.WithDefaultRedirectUri()
153+
.Build();
154+
var scopes = new string[]
155+
{
156+
"`<https://pas.windows.net/CheckMyAccess/Linux/.default>`",
157+
};
158+
var keyId = new byte[32];
159+
Random.Shared.NextBytes(keyId);
160+
var rsa = RSA.Create();
161+
var key = rsa.ExportParameters(includePrivateParameters: true);
162+
if (key.Modulus == null || key.Exponent == null)
163+
throw new InvalidOperationException("RSA key generation failed: Modulus or Exponent is null.");
164+
var localKey = new
165+
{
166+
kty = "RSA",
167+
n = Convert.ToBase64String(key.Modulus).Replace("+", "-").Replace("/", "_"),
168+
e = Convert.ToBase64String(key.Exponent).Replace("+", "-").Replace("/", "_"),
169+
kid = BitConverter.ToString(keyId).Replace("-", string.Empty).ToLower(),
170+
};
171+
var localKeyJson = JsonConvert.SerializeObject(localKey);
172+
Console.WriteLine("RSA Key:");
173+
Console.WriteLine(localKeyJson);
174+
Console.WriteLine();
175+
176+
// Get SSH certificate
177+
178+
AuthenticationResult result = await app.AcquireTokenInteractive(scopes)
179+
.WithSSHCertificateAuthenticationScheme(localKeyJson, localKey.kid)
180+
.ExecuteAsync();
181+
182+
// Define output directory and certificate path
183+
184+
var sshDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".ssh", "entra");
185+
Directory.CreateDirectory(sshDir);
186+
var certPath = Path.Combine(sshDir, "id_rsa-cert.pub");
187+
188+
// Remove read-only attribute if certificate already exists so it can be overwritten
189+
190+
if (File.Exists(certPath))
191+
{
192+
File.SetAttributes(certPath, FileAttributes.Normal);
193+
}
194+
// Save the certificate
195+
var cert = `[$"[email protected]](mailto:$%[email protected])` {result.AccessToken}";
196+
await File.WriteAllTextAsync(certPath, cert);
197+
File.SetAttributes(certPath, FileAttributes.ReadOnly);
198+
// Dump certificate content to console
199+
Console.WriteLine("Cert");
200+
Console.WriteLine(cert);
201+
Console.WriteLine();
202+
}
203+
}
204+
```
205+
206+
## Verify the contents of the OpenSSH certificate [Optional]
207+
208+
Use the following command to view the OpenSSH certificate.
209+
210+
`ssh-keygen -L -f my_cert.pub`
211+
Username is captured in the _Principals_ section highlighted in red
212+
213+
:::image type="content" source="media/secure-file-transfer-protocol-support-entra-id-based-access/verify-opensshcert.jpg" alt-text="Screenshot of the OpenSSH certificate output showing the Principals section highlighted in red.":::
214+
215+
For security reasons, the OpenSSH certificate is valid for 65 minutes. After this period, you will need to request a new certificate to initiate any further transactions. For security reasons, the OpenSSH certificate is valid for 65 minutes. After this period, you will need to request a new certificate to initiate any further transactions.
216+
217+
## Connect to the Storage Account with OpenSSH
218+
219+
### SFTP command
220+
221+
222+
C:\Users\username> sftp -o PubkeyAcceptedKeyTypes="[email protected],rsa-sha2-256" -o IdentityFile="C:\path\to\key\.ssh\id_rsa" -o CertificateFile="C:\path\to\cert\.ssh\my_cert.pub" storageaccountname.username@storageaccountname.blob.core.windows.net
223+
Connected to storageaccountname.blob.core.windows.net.
224+
sftp>
225+
226+
> [!NOTE]
227+
> If the Principal is in the format [[email protected]](mailto:[email protected]), make sure you don't add the domain section in the command and only use the username portion.
228+
229+
> [!NOTE]
230+
> [Both User and Service principals](/entra/identity-platform/app-objects-and-service-principals) are supported. In the case of Service principals, use the service principal id in place of the username in the connection string.
231+
232+
> [!NOTE]
233+
> Adding the container name directly into the connection string or setting it up via Home Directory is currently NOT supported.
234+
235+
Once connected, use the following to upload a file to the Azure Storage via SFTP.
236+
237+
`sftp> put 'C:\path\to\blob\blog.jpeg'`
238+
239+
If you get a permission denied error, please make sure you have the necessary RBAC roles such as Storage Blob Data Contributor or Storage Blob Data Owner
240+
241+
### SFTP desktop clients
242+
243+
OpenSSH based login is supported by SFTP clients such as WinSCP and PuTTY. Steps to connect via WinSCP below.
244+
245+
1. WinSCP: Support for OpenSSH certificates for user authentication was implemented in version 6.0. (<https://winscp.net/tracker/1873>)
246+
2. Obtain the OpenSSH certificate from step 3 above (3. Generate OpenSSH certificate)
247+
3. In WinSCP enter the Host name Username and click on Advanced
248+
249+
:::image type="content" source="media/secure-file-transfer-protocol-support-entra-id-based-access/winscp-login.png" alt-text="Screenshot of the WinSCP login dialog showing the Host name, Username fields, and the Advanced button.":::
250+
251+
1. Navigate to the Authentication section in the SSH Tab on the left and attach the Private Key and Certificate files obtained from the earlier sections and Click 'Ok.'
252+
253+
:::image type="content" source="media/secure-file-transfer-protocol-support-entra-id-based-access/winscp-advanced-settings.png" alt-text="Screenshot of the WinSCP Advanced Site Settings dialog showing the Authentication section with Private Key and Certificate file fields.":::
254+
255+
1. Click 'Login' to Login with the Entra ID account and OpenSSH certificate
256+
257+
:::image type="content" ssource="media/secure-file-transfer-protocol-support-entra-id-based-access/winscp-login-highlight.png" alt-text="Screenshot of the WinSCP login dialog with the Login button to connect using the Entra ID account and OpenSSH certificate.":::
258+
259+
# [Azure CLI](#tab/azurecli)
260+
261+
Use the following command to connect by using the OpenSSH certificate obtained in the previous steps
262+
263+
az sftp connect --storage-account `<<account_name>>` --certificate-file /my_cert.pub
264+
265+
Additionally, you can also get the OpenSSH certificate and connect to SFTP with a single command as follows
266+
267+
`az sftp connect`
268+
`az sftp connect --storage-account <<account_name>>`
269+
270+
More information regarding the commands, see [here](/cli/azure/sftp)
271+
272+
# [Azure PowerShell](#tab/azurepowershell)
273+
274+
Use the following command to connect by using the OpenSSH certificate obtained in the previous steps
275+
276+
Connect-AzSftp -StorageAccount `"<<account_name>>"` -CertificateFile "/my_cert.pub"
277+
278+
Additionally, you can also get the OpenSSH certificate and connect to SFTP with a single command as follows
279+
280+
Connect-AzAccount
281+
Connect-AzSftp –StorageAccount "<<account_name>>"
282+
283+
More information regarding the commands, see [here](/powershell/module/az.sftp/connect-azsftp)
284+
285+
## Entra ID based access control model in Azure Blob Storage SFTP
286+
287+
| **Mechanism** | **Status** | **Tutorial** |
288+
|---|---|---|
289+
| Role-based access control (Azure RBAC) | Supported | [Access control model for Azure Data Lake Storage - Azure Storage &#124; Microsoft Learn](/azure/storage/blobs/data-lake-storage-access-control-model) |
290+
| Access control lists (ACLs) | Supported | [Access control model for Azure Data Lake Storage - Azure Storage &#124; Microsoft Learn](/azure/storage/blobs/data-lake-storage-access-control-model) |
291+
| Attribute-based access control (Azure ABAC) | Not supported in private preview. If any ABAC rule exists, for SFTP it will be ignored. | |
292+
293+
## How permissions are evaluated
294+
295+
**SFTP mirrors the Azure Blob Storage's access control explained** [**here**](/azure/storage/blobs/data-lake-storage-access-control-model)** except that during the private preview, ABAC support is partial. Learn more in the Known issues and limitations section. **
296+
297+
## Sharing access to users outside of the home Entra ID tenant
298+
299+
Organizations often need to share Azure Blob Storage SFTP access with external partners and customers. Entra External Identities can address this requirement by allowing Azure Blob Storage SFTP to provide secure access to external collaborators. This feature enables efficient and secure connections and interactions with storage resources. By using Entra ID External Identity capabilities, organizations can maintain strong access control and security measures while enabling collaboration with external entities. Learn more [here](/entra/external-id/b2b-quickstart-add-guest-users-portal).
300+
301+
302+
## Known issues & limitations
303+
304+
Entra ID support is limited to SSH certificates and public key authentication.
305+
306+
Only RSA certificates are supported. ECDSA is not supported.
307+
308+
1. [ABAC](/azure/storage/blobs/storage-auth-abac-attributes) behavior is inconsistent when using with the Storage Blob Data Owner role (RBAC) and may lead to timeout errors. To use ABAC, choose the Storage Blob Data Contributor role, or use the Storage Blob Data Owner role without ABAC.
309+
310+
ABAC [sub-operations](/azure/storage/blobs/storage-auth-abac-attributes) are unsupported and will behave incorrectly. Specific behaviours of the sub operations are listed below.
311+
312+
List blobs (Blob.List): Users can list Blobs without any restrictions, and the ABAC condition expression(s) are ignored.
313+
314+
Read a blob (NOT Blob.List): Works as expected on the given ABAC condition expression(s). However, for all the other cases, List blobs (Blob.List) action will also inadvertently fail in addition to the expected failure of Read a blob (NOT Blob.List).
315+
316+
_(Deprecated)_ Read content from a blob with tag conditions (Blob.Read.WithTagConditions): The ABAC condition expression(s) are ignored.
317+
318+
Sets the access tier on a blob (Blob.Write.Tier): The ABAC condition expression(s) are ignored.
319+
320+
Write to a blob with blob index tag (Blob.Write.WithTagHeaders): The ABAC condition expression(s) are ignored.
321+
322+
Setting a home directory is not supported.
323+
324+
The connection string cannot include the container name. The user will connect to the root of the Storage Account and then navigate to the destination container and directories with 'change directory' (cd) commands.
325+
326+
Currently, `chown` & `chgrp` require either superuser and manage ownership, or manage ownership, read, and write. In the future, only manage ownership or superuser roles will suffice.
327+
328+
For `chmod`, the current requirement is either superuser and modify permissions, or modify permissions, read, and write. It will later require only modify permissions or superuser.
329+
330+
## Troubleshooting
331+
332+
- Connections to Storage Accounts via WinSCP works and the list of containers are visible after logging in. However, opening any container fails with Access denied
333+
- **Why**: WinSCP automatically tries to **canonicalize every directory** it enters. That means — for _every_ `cd` or directory listing, it sends one or more extra protocol requests to figure out the "true" absolute path.
334+
- The **root directory** shows _containers_
335+
- Each container is **a virtual chroot** — once inside it, you can't go above or outside it.
336+
- Paths are **virtual**, not physical, and Azure doesn't support `/`-based absolute traversal above containers.
337+
- **Fix**: There are two options to resolve this issue
338+
- Disable "Resolve Symbolic Links"
339+
- Advanced->Environment->Directories -> Untick "Resolve Symbolic Links"
340+
- Set Remote Directory
341+
- Advanced->Environment->Directories -> Set "Remote Directory" to "\\<container-name>"
342+
- By setting this you will directly enter the specified container after logging in

0 commit comments

Comments
 (0)