How to use Azure Managed Identity in Azure Function to access Service Bus with a trigger? - triggers

I have created a ServiceBus namespace in Azure, along with a topic and a subscription. I also have a simple Azure version 1 function that triggers on a received topic in the ServiceBus, like this:
[FunctionName("MyServiceBusTriggerFunction")]
public static void Run([ServiceBusTrigger("myTopic", "mySubscription", Connection = "MyConnection")]string mySbMsg, TraceWriter log)
{
log.Info($"C# ServiceBus topic trigger function processed message: {mySbMsg}");
}
The function triggers nicely for the topics in the ServiceBus when I define the connection string in functions Application Settings by using Shared Access Policy for topic, like this:
Endpoint=sb://MyNamespace.servicebus.windows.net/;SharedAccessKeyName=mypolicy;SharedAccessKey=UZ...E0=
Now, instead of Shared Access Keys, I would like to use Managed Service Identity (MSI) for accessing the ServiceBus. According to this (https://learn.microsoft.com/en-us/azure/active-directory/managed-service-identity/services-support-msi) it should be possible, unless I have misunderstood something. I haven't managed to get it working though.
What I tried, was to
set the Managed Service Identity "On" for my function in Azure portal
give Owner role for the function in ServiceBus Access Control section in Azure Portal
set the connection string for MyFunction like this: Endpoint=sb://MyNamespace.servicebus.windows.net/
The function is not triggering in this set-up, so what am I missing or what am I doing wrong?
I'd be grateful for any advice to help me get further. Thanks.

Update for Microsoft.Azure.WebJobs.Extensions.ServiceBus version 5.x
There is now an offical docs for the latest version of the package in here.
{
"Values": {
"<connection_name>__fullyQualifiedNamespace": "<service_bus_namespace>.servicebus.windows.net"
}
}
Previous answer:
This actually seems to be possible now, at least worked just fine for me. You need to use this connection string:
Endpoint=sb://service-bus-namespace-name.servicebus.windows.net/;Authentication=ManagedIdentity
I have not actually found any documentation about this on Microsoft site, but in a blog here.
Microsoft does have documentation though on roles that you can use and how to limit them to scope in here. Example:
az role assignment create \
--role $service_bus_role \
--assignee $assignee_id \
--scope /subscriptions/$subscription_id/resourceGroups/$resource_group/providers/Microsoft.ServiceBus/namespaces/$service_bus_namespace/topics/$service_bus_topic/subscriptions/$service_bus_subscription

what am I missing or what am I doing wrong?
You may mix up with MSI and Shared Access Policy.They are using different provider to access to Azure servicebus. You could just use connectionstring or just use MSI to authenticate.
When you use Managed Service Identity(MSI) to authenticate, you need to create a token provider for the managed service identity with the following code.
TokenProvider.CreateManagedServiceIdentityTokenProvider(ServiceAudience.ServiceBusAudience).
This TokenProvider's implementation uses the AzureServiceTokenProvider found in the Microsoft.Azure.Services.AppAuthentication library. AzureServiceTokenProvider will follow a set number of different methods, depending on the environment, to get an access token. And then initialize client to operate the servicebus.
For more details, you could refer to this article.
When you use servicebus connectionstring to access which using the Shared Access Token (SAS) token provider, so you can operate directly.

Agreed that from azure function we cannot access the resource like ASB directly. However, one still does not need to put in the password in this case "SharedAccessKeyName" in the connectionstring directly.
Azure function can work with Azure KeyVault. Thus one can store the connectionstring with sensitive information as a secret in the KeyVault and then grant System assigned identity from azure functions access over KeyVault and then specify the value for the settings in the portal as
#Microsoft.KeyVault(SecretUri={theSecretUri})
Details on how to achieve the above is mentioned in the following blog.
https://medium.com/statuscode/getting-key-vault-secrets-in-azure-functions-37620fd20a0b
This will still avoid specifying the connectionstring directly in Azure functions and provides with single point of access via Vault to be disabled in case of a security breach

Related

How to use Azure Data Factory, Key Vaults and ADF Private Endpoints together

I've created new ADF instance on Azure with Managed Virtual Network integration enabled.
I planned to connect to Azure Key Vault to retrieve credentials for my pipeline’s source and sink systems using Key Vault Private Endpoint. I was able to successfully create it using Azure Data Factory Studio. I have also created Azure Key Vault linked service.
However, when I try to configure another Linked Services for source and destination systems the only option available for retrieving credentials from Key Vault is AVK Linked Service. I'm not able to select related Private Endpoint anywhere (please see below screen).
Do I miss something?
Are there any additional configuration steps required? Is the scenario I've described possible at all?
Any help will be appreciated!
UPDATE: Screen comparing 2 linked services (one with managed network and private endpoint selected and another one where I'm not able to set this options up):
Managed Virtual Network integration enabled, Make sure check which region you are using unfortunately ADF managed virtual network is not supported for East Asia.
I have tried in my environment even that option is not available
So, I have gathered some information even if you create a private endpoint for Key Vault, this column is always shown as blank .it validates URL format but doesn't do any network operation
As per official document if you want to use new link service, instead of key vault try to create other database services like azure sql, azure synapse service like as below
For your Reference:
Store credentials in Azure Key Vault - Azure Data Factory | Microsoft Docs
Azure Data Factory and Key Vault - Tech Talk Corner

Azure function ServiceBusTrigger connection string value not in application settings

Before I deploy a function app and functions through PowerShell > ARM template I dynamically get a service bus connection string and update the value in the connection binding in the function.json file. Then I deploy the function app and function.
Deployment works, but the function app returns an error message:
Microsoft.Azure.WebJobs.ServiceBus: Microsoft Azure WebJobs SDK ServiceBus connection string 'Endpoint=sb://sbname.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;[Hidden Credential]' is missing or empty.
The question is: Do we really have to create an application setting on the function app with this connection string in it? Is there no other option than using the app setting?
It feels like storing the connection string in another location than on the service bus would just create another vulnerability.
I am aware that I could define "connection": "RootManageSharedAccessKey_SERVICEBUS" in the function.json file and then create an app setting with that same name, but that's not the way forward I want to go.
Please check if my findings help to:
Instead of storing the Service Bus Connection String directly, you can utilize the Azure Key Vault Service or Azure App Configuration Service.
You can store the confidential values like Connection Strings, Key-value pairs, Client Secrets, Certificate Passwords, etc. in Azure Key Vault.
Assume you have stored the ServiceBus connection string in the Key Vault. That you want to retrieve in the Function App through Application Settings but here in the app setting you can define as:
"connection": #Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/RootManageSharedAccessKey_SERVICEBUS/)
This KeyVault URI cannot be accessed by any other user until they are assigned with System or User Assigned Managed Identity Permission.
Azure App Configuration is a central place where you can manage application settings and secure their accesses in one place. Refer here for more information.

Access to read module twin data via Azure IoT Hub's APIs?

I'd like to be able to pull an IoT Edge device's module twin via an HTTPS GET request just like the Azure Portal does. In the portal, I see this firing...
https://my-hub.azure-devices.net/twins/my-device/modules/my-module?api-version=2020-09-30&_=164130947416
...and returning JSON. I'd like to do the same outside of the portal (like in Postman or something).
Obviously, by being logged in to the portal, I have credentials that permit that.
I've tried creating a Shared Access Signature and using it as a header like so...
"Authorization": "SharedAccessSignature sr=my-hub.azure-devices.net&sig=...
...but I get back ErrorCode:IotHubUnauthorizedAccess;Unauthorized
Am I missing something? Maybe a step where I use that SAS to get some additional credential or something?
Or maybe I can't create a SAS that works with any device-id?
In the end, I'd just like to be able to GET the reported properties for a module twin from any of my IoT Hub devices. No setting, no subscribing.
The API you're referring to is documented here. You're doing the right thing, but perhaps your method of creating a Shared Access Signature isn't working. One easy way to create a valid SAS token is by using the az cli command: az iot hub generate-sas-token -n <iot-hub-name>. By default it will create a token for the iothubowner policy, which should give you access to the module twin.
I used Postman, with the Authorization header as you mentioned to check the twin of my device $edgeHub module:
https://<my-iot-hub>.azure-devices.net/twins/<device-id>/modules/$edgeHub?api-version=2020-05-31-preview

How to make Keycloak use its database password from keyvault instead of env file

Currently I am using keycloak on postgres db. and the db creds are provided to environment files. Wanted to know how I can make keycloak obtain the db creds from keyvault something like Azure keyvault ? Is there any documentation / guideline around it?
As per the official documentation ,some part already done but look like still work in progress
To use a vault, a vault provider must be registered within Keycloak.
It is possible to either use a built-in provider described below or
implement your own provider. See the Server Developer Guide for more
information.
To obtain a secret from a vault instead of entering it directly, enter the following specially crafted string into the appropriate field: ${vault.entry-name} where you replace the entry-name with the name of the secret as recognized by the vault.
https://www.keycloak.org/docs/latest/server_admin/#_vault-administration
https://issues.redhat.com/browse/KEYCLOAK-3205

Azure Resource Manager Service Connection not connecting

We currently have one DevOps repository, with a functional CI/CD pipeline. We have another website hosted on a different instance (and different region) on Azure. We are trying to use our existing repo to deploy to the other Azure instance, but it is giving is the following message:
Failed to query service connection API: 'https://management.azure.com/subscriptions/c50b0601-a951-446c-b637-afa8d6bb1a1d?api-version=2016-06-01'. Status Code: 'Forbidden', Response from server: '{"error":{"code":"AuthorizationFailed","message":"The client '2317de35-b2c2-4e32-a922-e0d076a429f5' with object id '2317de35-b2c2-4e32-a922-e0d076a429f5' does not have authorization to perform action 'Microsoft.Resources/subscriptions/read' over scope '/subscriptions/c50b0601-a951-446c-b637-afa8d6bb1a1d'."}}'
I have tried all of the recommended trouble-shooting, making sure that the user is in a Global Administrator role and what-not, but still not luck. The secondary Azure subscription that we are hoping to push our builds to is a trial account. I'm not sure if it being a trial account matters.
I came across the same error. It turns out that, as the error message states, the service principal didn't have Read permission over the subscription. So the solution was to go to Azure Portal, select the subscription, select IAM and assign the role Reader to my service principal. Full explanation on here:
https://clydedz.medium.com/connecting-azure-devops-with-azure-46a908e3048f
I have the same problem. There are one repository and two instances of the application on the Azure portal. For the first instance, the subscription Pay-As-You-Go is used, and there were no problems for it when creating the service connection and CI/CD settings. For the second instance, a free subscription is used and when trying to create a new service connection (Azure Resource Manager) I get the same error.
I tried to do it with the permissions of Owner and Contributor
UPD: I was helped by the re-creation of the application in the azure portal
https://learn.microsoft.com/en-ca/azure/active-directory/develop/howto-create-service-principal-portal
Another option would be to save without verification if the Service Principle will not require permissions at the Subscription level. Like for example providing access to a Keyvault.
Check if the service connection for the second instance is correctly added in project settings: