I designed a PowerShell script that it's able to properly configure various settings of a Function App (including CORS e.g.).
The Function App works and can be called from an Api Manegement service.
When the need arose to configure Azure AD, I've used Az/CLI to replicate exactly what I do using Portal UI (and what I set manually perfectly works).
But it stopped working, APIM returns HTTP status code 401 (unauthorized).
The part of the script that configures Azure AD is the following:
# $add is a simple class that contains value to be configured
# actually AllowedTokens is always empty
if ($aad) {
'Setting Function App AAD configuration.' | Write-Verbose
$allowedTokens = if ($aad.AllowedTokens) { "--aad-allowed-token-audiences $($aad.AllowedTokens -join ' ')" } else { '' }
"az webapp auth update --name $name --resource-group $group --enabled $($aad.Enabled.ToString().ToLower())" +
" --action LoginWithAzureActiveDirectory --aad-client-id $($aad.ClientId) --aad-client-secret $($aad.ClientSecret)" +
" --token-store true" +
" --aad-token-issuer-url $($aad.TokenIssuerUrl) $allowedTokens" |
Invoke-Expression
'Function App AAD configuration set.' | Write-Verbose
}
The first strange thing is that if I disable authentication/authorization,
I save settings, enable and save again everything start working.
So I've started again and launched the script. I've examined the resource.
az auth show says that unauthenticatedClientAction is set to RedirectToLoginpage.
az resource show says that unauthenticatedClientAction is set to null.
When I do the trick described above:
az auth show says that unauthenticatedClientAction is set to AllowAnonymous.
az resource show says that unauthenticatedClientAction is set to null.
So I think this is the important difference to make the Function App properly works (or better this is the way to properly configure it).
Since I've used this method with success for other settings, I've tried to set this property with Az/CLI:
az resource update --name web --resource-group $group --namespace Microsoft.Web --resource-type config `
--parent "sites/$funcName" --set properties.siteAuthSettings.unauthenticatedClientAction=AllowAnonymous
The JSON returned as response shows nothing changed. Inspecting the resource confirms it.
One more thing, when I export the resource group I can't see any unauthenticatedClientAction in any Function App template.
What's the correct way to set unauthenticatedClientAction to AllowAnonymous?
Any help will be really appreciated!
First, answer your question, to set unauthenticatedClientAction to AllowAnonymous, just use
az webapp auth update --name <functionapp-name> --resource-group <group-name> --action AllowAnonymous
Actually, when you do the trick in the portal, it will change the
to
This is the unauthenticatedClientAction setting.
Then the question is coming, I am not sure if you want to secure your azure function with Azure AD or not. Because when you set unauthenticatedClientAction to AllowAnonymous, your function will allow the anonymous request, the Azure AD auth will not take effect.
When the need arose to configure Azure AD, I've used Az/CLI to replicate exactly what I do using Portal UI (and what I set manually perfectly works). But it stopped working, APIM returns HTTP status code 401 (unauthorized).
Yes, the 401 error represents the Azure AD auth toke effect, if you enable the Azure AD auth(set Log in with Azure Active Directory), you need to get the access token for your client/user, then use the token to access the function. (Not sure how to implement it in APIM, I am not an expert in APIM:-))
For more details, you could check this blog and this post.
Related
After running a DevOps pipeline that created several resources, only two (a new resource group and a Functions app) show up in Azure CLI using az ... list --subscription ....
Other resources, like Static Web Apps and a SQL Server don't show up in that list or when running az staticwebapp list --subscription ... or az sql server list --subscription ... with the subscription argument specified. I have confirmed that these resources DO show up in the portal, and my account is listed as an owner (inherited from subscription) for them in the portal.
I have deployed Azure Static WebApp using Azure Devops.
Followed this MSDoc to publish the static web app.
By using,
az staticwebapp list --resource-group YourRGName
and
az staticwebapp list --subscription YourSubscriptionID
,Iam able to get the StaticWeb App list
For anyone else running into this:
I have not found a solution to getting the az staticwebapp list command to work for my use case, as the results that show up immediately after creating a resource are just inconsistent. However, as a workaround that should satisfy most use cases, using this API (using az rest command) to find all resources associated with the group created by the pipeline, then filtering those down to find the Static Web App I want, seems to work.
Then, when using other APIs that reference that app before it shows up in the normal list, fully specifying subscription and resource group alongside the app's name seems to make things more reliable too.
As far as I can tell, this is probably just a limitation with the inconsistency of how long information about newly deployed resources takes to propagate that shows up when trying to find a resource immediately after creating it.
I'm trying to use a User Assign Managed Identity to retrieve access in KeyVault reference in Azure Function.
I'm following this doc https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references?tabs=azure-cli#:~:text=you%20haven%27t%20already.-,Configure,-the%20app%20to to reference the keyvault in the application configuration.
I followed these steps:
Created User Assign Managed Identity.
Created a policy in Keyvault and gave permissions GET and LIST to User Assign Managed Identity.
Set the User Assign Managed Identity in Azure Function Identity
Set properties application setting like this:
mysecureapp - #Microsoft.KeyVault(SecretUri=https://mykv.vault.azure.net/secrets/mysecret/id)
keyVaultReferenceIdentity - /subscriptions/subsid/resourceGroups/rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/mgid
Any thoughts on this?
I realized that in addition to setting the property keyVaultReferenceIdentity via app-setting, we need to change this property of the same name in the resource function. The default value is SystemAssign if you enable it. Unfortunately the MS documentation is unclear on this.
I found the property that can be used in the terraform documentation, follow the link: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/function_app#:~:text=key_vault_reference_identity_id
After setting this property to the value of User Assign Managed Identity this worked fine.
just found that when the keyVaultReferenceIdentity property is created in the Function using the portal our IaC (App Settings), it doesn't recognize the User Assigned identity as the one to authenticate in KeyVault, but if you run the PATCH described in the following link using PowerShell, it works.
https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references?tabs=azure-powershell#access-vaults-with-a-user-assigned-identity
it should be enough to the reference to KeyVault works
wow !
I'm also searching the same topic for user identity and the same issue.
I just followed the marked answer , its worked and able to retrieve the value.
Thanks # Magno Oliveira to bring this question to the community.
just need to run the CLI command in azure portal ! give resource group name and useridentity name and function app name to the below command
userAssignedIdentityResourceId=$(az identity show -g resourcegroupname -n manageidenityname --query id -o tsv)
appResourceId=$(az webapp show -g resourcegroupname -n functionappname --query id -o tsv)
az rest --method PATCH --uri "${appResourceId}?api-version=2021-01-01" --body "{'properties':{'keyVaultReferenceIdentity':'${userAssignedIdentityResourceId}'}}"
I hope you already done all the steps. But one thing you may missed i.e.,
you have to enable the system-assigned identity for your application.
This error MSINotEnabled comes mostly during the absence of a managed Identity for your application, and it clearly says i.e., System assigned Managed identity.
Refer to this medium article where we will find the troubleshooting steps had given along with all these kind of errors with resolutions were described.
I previously created and subsequently deleted an Azure API Management service using Terraform. It disappeared in Azure Portal. A few hours after that, when I tried to recreate API Management with the same name, I got this error in the Azure Portal :
"name already in use. Please select a different name."
Also got similar error in Terraform as well.
Anyone knows why the name cannot be reused even though I am no longer seeing that name in my resource group?
Check if your APIM service have been soft deleted or not. If the resource has been soft-deleted, and you want to create a new one with the same name,what you need to do is purge the resource and then recreate.
Get a soft-deleted instance by name:
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.ApiManagement/locations/{location}/deletedservices/{serviceName}?api-version=2020-06-01-preview
List all soft-deleted instances for a given subscription:
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.ApiManagement/deletedservices?api-version=2020-06-01-preview
Recover a deleted APIM instance:
PUT https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.ApiManagement/service/{apimServiceName}?api-version=2020-06-01-preview
Purge a soft-deleted APIM instance:
DELETE https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.ApiManagement/locations/{location}/deletedservices/{serviceName}?api-version=2020-06-01-preview
I wrote an article with some PowerShell code (function) that wraps the REST calls, so you can just call the function with a few parameters like below.
Purge-ApiManagementInstance -SubscriptionId $subId -Location $location -Name $apimInstanceName
https://www.linkedin.com/pulse/purging-azure-api-management-instance-james-hughes/
As others already mentioned, your instance has been soft deleted.
You need terraform to purge the instance on destroy, this is done by adding some config options on provider section
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/features-block#api_management
provider "azurerm" {
api_management {
# does not seem to work, insufficient rights?
purge_soft_delete_on_destroy = true
# as of now next attribute exists only on docs, never worked for me
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/features-block#api_management
#recover_soft_deleted_api_management = false
}
----
}
According to terraform docs your SP also needs to have recover permission.
You can also use az rest to delete it
az rest --method delete --header "Accept=application/json" -u 'https://management.azure.com/subscriptions/123-123-123/providers/Microsoft.ApiManagement/locations/[eastus]/deletedservices/cloud-devops-test?api-version=2020-06-01-preview'
Also, you can use AZ CLI for that now:
az apim deletedservice purge --help
example:
az apim deletedservice purge -l APIM_LOCALTION -n APIM_NAME
I am using Azure app service api to view server details like worker process and region etc. for management purpose. After generating token from AuthenticationContext.AcquireTokenAsync method, I am requesting following URL for server details https://management.azure.com/subscriptions/<sub ID>/resourceGroups/<resource group name>/providers/Microsoft.Web/serverfarms/?api-version=2018-02-01
In the response I am getting AuthorizationFailed error code with the detail given bellow:
The client does not have authorization to perform action 'Microsoft.Web/serverfarms/read' over scope '/subscriptions/xxxxxxxx-xxxxxxx-xxxx/resourceGroups/xxxxxxxxxxx/providers/Microsoft.Web/serverfarms/xxxx' or the scope is invalid. If access was recently granted, please refresh your credentials.
But when I try the same verification using https://learn.microsoft.com/en-us/rest/api/appservice/appserviceenvironments/get portal where I can try the APIs for testing, the request is returning expected results.
So, is there any other way to authenticate or should I have to define some permissions to achieve the functionality?
The service principal you are using doesn't have rights within that tenant.
Tenants have subscriptions and service principals belong to tenants. Azure resource manager also exposes role based authorization for a given principal, which would give it rights on Azure resources. It appears the service principal doesn't have rights to read from that subscription.
Go to portal and find your subscription, click on Access Control (IAM) and then click on Add role assignment with correspond service principal which you use to acquire token.
After you have given successful permission, refresh and try again.
I had the same error while running,
az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
I did this shortly after az login.
Problem was I haven't set my subscription properly so what I had to do was run,
az account set --subscription your-subscription-id
After that az aks get-credentials worked fine, the error was gone and you will get an output like,
Merged "myAKSCluster" as current context in C:\Users\UserName\.kube\config
I had the same problem. Initially, I went ahead and added to my user the "Web Plan Contributor" role, as it is the one that should handle those things. Nothing changed - I still had this error.
What turned actual problem turned out to be is a wrong resource group... Turns out I copied some old script where WebAppPlans were in separate RG, and I was searching the app plan there. Completely missleading error. I guess it will bring up the same error message even if the App Plan simply doesn't exist.
Okay, so I messed up, I accidentally ran az ad sp reset-credentials against the Service Principal that our AKS cluster runs under. And now we are getting errors like:
Error creating load balancer (will retry): error getting LB for service test/admin-api: azure.BearerAuthorizer#WithAuthorization: Failed to refresh the Token for request to https://management.azure.com/subscriptions/****/resourceGroups/MC_****/providers/Microsoft.Network/loadBalancers?api-version=2017-09-01: StatusCode=0 -- Original Error: adal: Refresh request failed. Status Code = '401'. Response body: {"error":"invalid_client","error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID:****\r\nCorrelation ID:**** \r\nTimestamp: 2018-08-23 12:01:33Z","error_codes":[70002,50012],"timestamp":"2018-08-23 12:01:33Z","trace_id":"****","correlation_id":"****"}
and
Failed to pull image "****.azurecr.io/****:****": rpc error: code = Unknown desc = Error response from daemon: Get https://****.azurecr.io/v2/****/manifests/****: unauthorized: authentication required
So now I want to find the original client secret that the Service Principal uses, so that I can re-add that as a key to the Service Principal. That's the only solution I can think of other than recreating the entire cluster.
Any ideas?
In the end the solution was quite simple.
In the Azure portal, navigate to the resource group named MC_<resourcegroup>_<aksName>_<region>.
Click one of the resources of the type "Virtual machine".
Scroll down to "Run command"
Choose "RunShellScript"
Enter cat /etc/kubernetes/azure.json and click "Run"
The command will return the contents of the JSON file. The property you need is aadClientSecret
Whoever comes over this issue there's an updated solution from Microsoft
https://learn.microsoft.com/en-us/azure/aks/update-credentials#update-aks-cluster-with-new-credentials
They also mention (something that's not obvious) that:
By default, AKS clusters are created with a service principal that has a one-year expiration time.
Also,
As of Azure CLI 2.0.68, the --password parameter to create a service principal with a user-defined password is no longer supported to prevent the accidental use of weak passwords.
so the initial solution to change the service principal password doesn't work anymore.
It's an annoying thing that you want to do. For your issue, you cannot pull the image without authentication.
First, you have to find out the service principal of your container registry. You can do this in the Azure portal and navigate to the registry panel, then you can find the service principal like this:
Or you can use the Azure CLI command to find the registry ID like this:
az acr show --resource-group groupName --name registryName --query id --output tsv
Then use the command to find the service principal ID like this:
az role assignment list --scope registryID
You can select the service principal which you want.
Then you would get all the secrets with the command kubectl get secrets and kubectl get secrets secretName -o yaml to get the token of the secret. Then analyze one-by-one to check if the username the same as the service principal ID. You can use tools such as JWT to analyze the secret token. The result will like this:
If the username the same as the service principal ID which you find, that is the secret you want. This step is a trouble. You should check the secret one-by-one or you will have a more great way to check them.
By the way, it seems that you can just see the password of the service principal once when you create it. The Azure will not show you again. But if you create the Kubernetes secret, the password is stored in it.
There is new functionality available in the Azure portal to look at the cluster configuration without using the CLI.
Go to the Azure Portal -> Your Cluster Resource -> Overview
On the right hand side there is a button that says "JSON View". Click it and you will see a json file with the cluster details. The service principal ID is visible under: "servicePrincipalProfile".