In Microsoft's documentation for user delegation key, it says:
A SAS token for access to a container, directory, or blob may be
secured by using either Azure AD credentials or an account key. A SAS
secured with Azure AD credentials is called a user delegation SAS.
Microsoft recommends that you use Azure AD credentials when possible
as a security best practice, rather than using the account key, which
can be more easily compromised. When your application design requires
shared access signatures, use Azure AD credentials to create a user
delegation SAS for superior security.
Why do this approach give "superior security"? I guess the SAS tokens are both safe? So why exactly is one approach safer than the other? If you use Stored Access Policy, you can also revoke SAS tokens when they have been issues with account keys.
A user-delegation SAS token is more secure that it does not rely on the permissions included in the SAS token only. It also takes into consideration the RBAC permissions of the user who created this SAS token. A SAS token created using shared access key simply considers the permissions included in the SAS token.
For example, let's say the user who's creating a user-delegation SAS only has Read permissions on a blob container (i.e. they can only list or download blobs in a blob container). Now let's say the user creates a SAS token with Write permission. When this SAS token is used to upload a blob, the operation will fail because the user does not have Write permissions on that blob container whereas the upload operation would have succeeded if the SAS token was created using shared access key.
More information on this can be found here (emphasis mine):
When a client accesses a Blob storage resource with a user delegation
SAS, the request to Azure Storage is authorized with the Azure AD
credentials that were used to create the SAS. The role-based access
control (RBAC) permissions granted for that Azure AD account, together
with the permissions explicitly granted on the SAS, determine the
client's access to the resource. This approach provides an additional
level of security and avoids the need to store your account access key
with your application code. For these reasons, creating a SAS using
Azure AD credentials is a security best practice.
The permissions granted to a client who possesses the SAS are the
intersection of the permissions granted to the security principal that
requested the user delegation key and the permissions granted to the
resource on the SAS token using the signedPermissions (sp) field. If a
permission granted to the security principal via RBAC is not also
granted on the SAS token, then that permission is not granted to the
client who attempts to use the SAS to access the resource. When
creating a user delegation SAS, make sure that the permissions granted
via RBAC and the permissions granted via the SAS token both align to
the level of access required by the client.
Related
I have an Azure Storage Account with public access disabled. Inside the storage account are a few Blob Storage Containers. Each container has access managed with AzureAD with varying permissions for each user/group to different Blob Containers.
I want to be able to download items inside the Blob Storage using tools like wget or curl using HTTP Basic Auth or specifying user information in the request.
I'm aware that AzCopy can be used to download Blobs from the containers, but previously we have used http requests to download artifacts and would like to continue using that method.
This question from 2016 Makes it seem like that its possible to do this with Shared Access Signature, which makes me believe that its possible to use with User Delegation SAS, but I have not found a way to set this up, and it requires a lot of parameters, more than a username/password or token.
Does Azure Blob Storage have a way where a user can access blob storage without AzCopy or any other specialized tools and authenticate via a method that does not require additional resources?
No. You must make a separate request for a token to send to Blob.
When a security principal (a user, group, or application) attempts to
access a blob resource, the request must be authorized, unless it is a
blob available for anonymous access. With Azure AD, access to a
resource is a two-step process. First, the security principal's
identity is authenticated and an OAuth 2.0 token is returned. Next,
the token is passed as part of a request to the Blob service and used
by the service to authorize access to the specified resource.
The authentication step requires that an application request an OAuth
2.0 access token at runtime.
Overview of Azure AD for blobs
In order to connect to Azure Shared Storage(in particularly File Share) to perform tasks like copying/removing/modifying files from remote to azure storage, we need either SAS(Shared Access Signature) or Active Directory Settings Enabled (and then assign roles based on requirement).
I wanted to implement the access using SAS approach, I tried generating SAS from UI, tried generating SAS by making use of Access Keys(Present Inside Storage Account - Confidential and most important key for storage account) both worked. But UI approach isn't conducive in my case, and Access token can't be given to anyone apart from the administrator.
So is there a way to generate SAS using Azure AD credentials or some service where we can create an account and password/key and that account can be used to create SAS token via curl(REST call) and not generating SAS via access keys(admin key).
The tricky part is to let your users create a sas token for the file share without granting them permissions on the whole storage account.
You can use a middle tier application that creates the SAS token and allow the users to use that app. An azure function with an HTTP trigger can be used for example. You grant the azure function access to the storage account using a Managed Service Identity and secure the access to the Azure function either with Active Directory or a function key, that you distribute to your users.
You can try with this approach:
A SAS token for access to a container, directory, or blob may be secured by using either Azure AD credentials or an account key.
Microsoft recommends that you use Azure AD credentials when possible as a security best practice, rather than using the account key, which can be more easily compromised. When your application design requires shared access signatures, use Azure AD credentials to create a user delegation SAS for superior security.
Create a User delegation SAS
Generate a User Delegation Key:
POST https://myaccount.blob.core.windows.net/?restype=service&comp=userdelegationkey
In the Microsoft documentation, it is recommended that professionals use User Delegation Shared Access Signatures rather than key-based Shared Access Signatures. Specifically, why is this the case?
In this document, it is specified that:
Microsoft recommends that you use Azure AD credentials when possible
as a security best practice, rather than using the account key, which
can be more easily compromised. When your application design requires
shared access signatures for access to Blob storage, use Azure AD
credentials to create a user delegation SAS when possible for superior
security.
This Azure official document explains why it is recommended to use User Delegation Shared Access Signatures.
When a client accesses a blob service resource with a user delegation SAS, the request to Azure Storage is authorized with the Azure AD credentials that were used to create the SAS. The role-based access control (RBAC) permissions granted for that Azure AD account, together with the permissions explicitly granted on the SAS, determine the client's access to the resource. This approach provides an additional level of security and avoids the need to store your account access key with your application code. For these reasons, creating a SAS using Azure AD credentials is a security best practice.
I am trying to understand few points about delegating authorization to Azure BLOB using Azure service principles.
How I configure Azure:
Create and Configure Service Principal: in Active Directory I created an application, created a key (password), and set its required permissions to access Azure Storage;
Configure IAM of Azure Storage: under Storage accounts section, I chose my storage account, and under IAM I assigned my account (my login account as XYZ#hotmail.com) to Storage BLOB Data Contributor role.
How I use the configuration in my client App:
With the aforementioned configuration; my application takes tenant ID, client ID, client secret, and etc. and sends authorization request to /authorize endpoint.
Then a window pops-up and asks me to login (using e.g., XYZ#hotmail.com), and then a consent screen pops-up and asks for my permission to allow the service principal to read my Azure storage.
After I approve, my client application receives OAuth2.0 code.
Then I exchange this code with an access_key via the /token endpoint.
Q1: does this access_key grant my client application same privileges as XYZ#hotmail.com or service principal?
Using the obtained access key I can read/write azure blob.
Q2: if XYZ#hotmail.com does not have read/write access (i.e., not assigned with the Storage BLOB Data Contributor role), my client app would not be able to read/write for the blob, regardless of the Service Principal's role. This is where I get confused, I am under the impression that my client App is assuming Service Principal, hence it will have same privileges as the Service Principal, not XYZ#hotmail.com. For instance, XYZ#hotmail.com can have Contributor role (i.e., read/write), while the service principle would be assigned with a Reader role. In that case, I would have a full access to BLOB storage, while my client app will have only a read access to the BLOB storage. However, it seems client app gets same permissions as XYZ#hotmail.com. What am I missing here?
Q1: does this access_key grant my client application same privileges
as XYZ#hotmail.com or service principal?
The access_token you got has the delegated permissions which onbehalf of XYZ#hotmail.com. This is because that you used Authorization code grant flow.
What am I missing here?
For your scenario, I suggest you can use client_credentials flow for your app.
With client_credentials flow, you will get access token only with the application permissions configured in AAD. Also, this access token is actually onbehalf of your AAD application itself. If you assign a role to your service principal, you will get the access token with the permission of that role.
If you use Authorization code grant flow, you will get the access token onbehalf of the user, not the service principal. So, the access token will have the permission of that user.
We are using MS Azure and developing SAAS based Multi-Tenant Application.
For each Tenant we have BLOB Container Private and assigned to each Tenant.
Also there is a requirement that Client can share files with other client users.
Eg.
Client C1 has Container "C1" and it has files "C1f1", "C1f2" and "C1f3".
User U1 and U2. U1 has access permission for C1f1 and U2 has C1f2 access only.
How can we do this in MS Azure Permission or Security? This needs to be done RUNTtime?
Please suggest How can this be done - What is BEST way to do
I believe you have two options.
Either generate and use SAS tokens per client/user with the right permissions. With a SAS token you can provide access to a specific resource up to a specific point in time. The disadvantage is that SAS tokens cannot be revoked on a per token basis. You can only revoke all tokens by rolling the storage access key that was used to generate the SAS token. Another disadvantage is that you have to provide a SAS token per item you want to grant access to. (For more info see also https://azure.microsoft.com/nl-nl/documentation/articles/storage-dotnet-shared-access-signature-part-1/)
Create a Web Service that encapsulates the Azure storage and serves files to your customers. In this service implement authorization management yourself.