I have a function app and need to give it permission to write to blob/table storage. I turned on "System Assigned Managed Identity", and I set the following permissions for it with the scope being the Storage Account I need to access.
Storage Account Contributor
Storage Blob Data Owner
Storage Table Data Contributor
Storage Queue Data Contributor
UPDATE I remove AZURE_CLIENT_ID, AZURE_CLIENT_SECRET and AZURE_TENANT_ID and then I receive an environment configuration error. I am not running this locally or debugging, I'm triggering it through API Management.
Executed 'Create' (Failed, Duration=1406ms)EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot
^ The above link tells me I should add those environment variables back, but it seems like I shouldn't need them according to Peter Bon's answer below
One piece that I find very confusing (because I can't find good documentation on this anywhere) is that I am required by Azure to include three variables
- AZURE_CLIENT_ID
- AZURE_CLIENT_SECRET
- AZURE_TENANT_ID
I am inferring that they are needed to actually allow my function app to access the storage account, which confused me at first because if I just gave it permission explicitly with assigned roles, why do I also need to create something completely outside of my function app to give it permission to do the thing I already gave it permission to do?
My question about this though is "HOW DO I MAKE THIS?" If I need to make an App Registration, what should the callback URL be? What should the API Permissions be? I gave it my best guess and did not get a satisfactory result.
App Registration:
API permissions -> Microsoft.Graph User.Read
Authentication -> https://<mydomain>.onmicrosoft.com/.auth/login/aad/callback
-> ID Tokens
-> Accounts in this organization
Secrets -> Generated new secret to use for AZURE_CLIENT_SECRET
Roles & Admissions -> Cloud application administrator
I then set AZURE_CLIENT_ID to be the app id of this App Registration, AZURE_CLIENT_SECRET to the app registration's secret and AZURE_TENANT_ID to my tenant ID.
Then in my code, I attempt to do the following
var tableUri = new Uri(string.Format("https://{0}.table.core.windows.net/", storageAccountName));
var credential = new DefaultAzureCredential(options);
services.AddScoped(x => new TableServiceClient(tableUri, credential));
And it fails when accessing my table storage with the following error:
Executed 'Create' (Failed, Id=<id>, Duration=2108ms)Server failed to authenticate the request. Please refer to the information in the www-authenticate header.RequestId:<id>Time:2022-10-21T12:15:21.6998519ZStatus: 401 (Server failed to authenticate the request. Please refer to the information in the www-authenticate header.)ErrorCode: InvalidAuthenticationInfoContent:{"odata.error":{"code":"InvalidAuthenticationInfo","message":{"lang":"en-US","value":"Server failed to authenticate the request. Please refer to the information in the www-authenticate header.\nRequestId:<id>\nTime:2022-10-21T12:15:21.6998519Z"}}}Headers:Server: Microsoft-HTTPAPI/2.0x-ms-request-id: <id>x-ms-error-code: REDACTEDWWW-Authenticate: Bearer authorization_uri=https://login.microsoftonline.com/<tenant_id>/oauth2/authorize resource_id=https://storage.azure.comDate: Fri, 21 Oct 2022 12:15:21 GMTContent-Length: 279Content-Type: application/json
and if I update the Authentication redirect to
https://storage.azure.com
then I get the following error:
Executed 'Create' (Failed, Id=<id>, Duration=2349ms)This request is not authorized to perform this operation using this permission.RequestId:<request>Time:2022-10-21T13:14:29.0955823ZStatus: 403 (Forbidden)ErrorCode: AuthorizationPermissionMismatchContent:{"odata.error":{"code":"AuthorizationPermissionMismatch","message":{"lang":"en-US","value":"This request is not authorized to perform this operation using this permission.\nRequestId:<id>\nTime:2022-10-21T13:14:29.0955823Z"}}}Headers:Cache-Control: no-cacheTransfer-Encoding: chunkedServer: Windows-Azure-Table/1.0,Microsoft-HTTPAPI/2.0x-ms-request-id: <id>x-ms-client-request-id: <id>x-ms-version: REDACTEDX-Content-Type-Options: REDACTEDDate: Fri, 21 Oct 2022 13:14:28 GMTContent-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8
I am honestly pretty confused at this point, can someone please help me understand how to successfully set up system assigned managed identities?
CodePudding user response:
When using a managed identity you should not provide these env variables. It would also defeat the purpose of not having to store a secret. They are not required in that scenario. It is just one of the many ways DefaultAzureCredential
tries to get valid credentials. See this section. If you do not provide them, it will fall back trying to use a managed identity.
CodePudding user response:
I use User Managed Identities for fine grained permissions from a Function App. e.g the following uses a User Managed Identity to access the Graph API from a Function App:
DefaultAzureCredentialOptions defaultAzureCredentialOptions = new()
{
ManagedIdentityClientId = clientIdOfMailSenderManagedIdentity,
ExcludeInteractiveBrowserCredential = true,
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true,
ExcludeAzureCliCredential = false,
ExcludeSharedTokenCacheCredential = true,
ExcludeAzurePowerShellCredential = true
};
var graphServiceClient = new GraphServiceClient(new DefaultAzureCredential(defaultAzureCredentialOptions),
new[] { "https://graph.microsoft.com/.default" });
Not excluding commandline authentication:
ExcludeAzureCliCredential = false
lets me run the code locally after using az login
to authenticate as managed identites cannot be used locally.