Are "Cross Application Queries" possible using the Azure API format for app insights? - azure

I'm trying to make a query to Application Insights using the Azure API format to retrieve data on multiple applications. I can successfully make queries for any application without a join.
I have previously done this using the Public API format, following the documentation for making "cross-application queries" successfully. Under the Azure API schema, however, once I add a second application to a query - either using the implicit or explicit mechanisms described in the documentation - I get an error of type InsufficientAccessError with the message: "The provided credentials have insufficient access to perform the requested operation".
If there are sufficient permissions to access either table individually, I would expect there to be sufficient to do a join. Is there a separate permission required to make these queries, or is it an issue with the API itself?
For reference, the Azure AD application has delegated permissions for:
user_impersonation
Directory.Read.All
Group.Read.All
User.Read
User.ReadBasic.All
User.ReadWrite
The user which is making the requests has the Owner role on all relevant applications.
And the final request has a JSON body (with the blanks filled in):
{
"query": "requests \n| summarize avgRequestDuration=avg(duration) by bin(timestamp, 1h)",
"applications": [
"/subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/microsoft.operationalinsights/components/<applicationName>"
],
"timespan": "P1D"
}
Edit: I've tried this query using different forms of the resource identifiers as mentioned in the documentation, including the recommended "/providers/microsoft.operationalinsights/applications/" and "/providers/microsoft.operationalinsights/components/".

Based on a couple of things I've discovered, I believe it is impossible to do a cross-resource query in the Azure API URL format.
All experimentation with adding different roles to users and experimenting with permissions failed to find anything that worked.
The Go SDK uses the Azure API URL format and does not allow cross-resource queries, the .NET SDK uses the Public API URL format and does allow cross-resource queries, indicating that the feature set is different for the two APIs.
I would be happy to be proven wrong or to have this proven correct with a better reference.

Related

How to expose some API methods without subscription while keeping subscription for others?

I am using Azure API Management to proxy requests from Internet to our backend systems. I have a Product entry on Azure Portal and an API entry associated with the product. Generally access to the API must be by subscription, but I would like the method returning OpenAPI specification (as well as probably few other methods) to be accessible without subscription (freely).
I see "Requires subscription" checkbox on the Product level as well as on API level, but not on a method's level. So I need either:
bypass subscription check for certain methods while keeping access by subscription for others, or:
same but vice versa: keep the access free for API, but enforce subscription check for certain methods (not preferable, as this fraction is greater).
I checked the list of policies and did not find anything applicable for my case. Moreover this link states:
Subscriptions can be associated with various scopes: product, all
APIs, or an individual API.
Is there a way I can workaround this limitation?
I mean that, maybe you wanna some of the methods(less amount) in an Api can be called without a subscription while the left need. And I searched the ms document but failed to find such policy.
The link you provided also intended that. From my point of view,
how about trying to add a separated Api containing those methods that
don't need subscription?

Implement row level security (RLS) in Azure Data Explorer

We are trying to implement Row Level Security in Azure Data Explorer (ADX). Out of the box, ADX doesn't provide RLS. Is there any way/ workaround we can implement RLS?
We are trying out below option but no success :
Creating 2 separate databases (DbNonSecure, DbSecure)
DbNonSecure is non-secured, all the rows can be accessible by an authenticated user
DbSecure is secured database and can not be accessible by anyone except AAD APP or some other service account
From DbNonSecure, we are thinking to call functions that access data in DbSecure (using AAD APP or Service Account) and check Row Level Security.
We couldn't find a way to call functions that access data in DbSecure using ADD APP or Service Account.
Also, we know we can add a middle tier (Separate UI) to achieve this but we don't have that much time freedom to develop middle tier.
you're correct - Kusto/ADX doesn't support row level security at the moment (you can upvote the feature request # https://aka.ms/adx.uservoice)
We couldn't find a way to call functions that access data in DbSecure using ADD APP or Service Account.
AAD application authentication is a valid means of authentication to a Kusto/ADX database. There's a full guide on how to set that up here: https://learn.microsoft.com/en-us/azure/kusto/management/access-control/how-to-provision-aad-app
-> Once you've granted the required access to your AAD Application, it can be used for querying the database. Referencing stored functions is simply part of a query, and doesn't require any special setup (asides from, obviously, creating the stored function)
Side note: you may also find interest in the Restricted view access policy (it may or may not fit your requirements).
Just a heads up, ADX Row Level Security is in preview now: https://learn.microsoft.com/en-us/azure/data-explorer/kusto/management/rowlevelsecuritypolicy

Programatically get users group and role from Azure AD

I am new to azure AD.
I have a third party API which gives me a userId. I have written a .NET Core API which should take this userID and get the roles and groups of that specific user.
I have read about the microsoft graph API. Not sure if this is useful in my scenario.
Also is there any other way to access the roles and groups of a AD user programatically.
Which API to use to get groups and role information
Firstly, Microsoft Graph API is your best bet to get the information you're looking for.
Which exact API works best for you depends on your scenario (a. do you need top level direct membership or transitive check? b. do you want only security groups or even O365 groups?), so you're the best judge.
I'll list down 3 of them here and you should get some ideas to pick.
memberOf -
Gets both groups and directory roles that user is a direct member of.
NOTE: only direct membership matters for this one, check is NOT transitive (i.e. User has to be a direct member of the group for that group to be returned. If user is member of a group1, but that group1 is member of group2, then group2 will NOT be returned. This behavior might be ok for some scenarios but not for others)
GET /users/{id | userPrincipalName}/memberOf
getMemberGroups
POST /users/{id | userPrincipalName}/getMemberGroups
Returns all the groups that the user is a member of. Check for this one is Transitive, so you're assured that all groups will be returned. Upto 2046 returned as part of 1 request. It also works with O365 groups and you can filter down to SecurityEnabled groups using a parameter
getMemberObjects
Returns all of the groups, directory roles and administrative units that the user is a member of. The check is again transitive.
Implementation and Code Sample.. How to get token, call API etc.
Acquiring Token for Authentication
You should make use of MSAL or ADAL libraries depending on which Azure AD endpoint you're using MSAL for v2 and ADAL for v1. Using these libraries is not mandatory but recommended because they will follow best practices and do the heavy lifting for you.
Interacting with Microsoft Graph API Endpoints
Since you're writing in .NET, you can make use of Microsoft Graph Client Library for .NET (SDK). Again, it's not mandatory to use the client library but it will make your code more declarative and will be convenient. You can always work with HttpClient and hit the REST endpoints directly if you want.
Code Sample
Microsoft Graph Connect Sample for ASP.NET Core 2.1
Important parts.. Look at the GraphService.cs file for methods that get user information, e.g.
// Load user's profile in formatted JSON.
public static async Task<string> GetUserJson(GraphServiceClient graphClient, string email, HttpContext httpContext)
{
if (email == null) return JsonConvert.SerializeObject(new { Message = "Email address cannot be null." }, Formatting.Indented);
try
{
// Load user profile.
var user = await graphClient.Users[email].Request().GetAsync();
return JsonConvert.SerializeObject(user, Formatting.Indented);
}
NOTE: The sample makes use of delegated permissions. You may need to make use of application permissions directly or On-behalf of flow (if you want to do it under a user's context) since you mention yours is an API being called. Also, this is just one of the samples, that you should look at to understand how to work with SDK, but there are many available readily once you start looking further into Microsoft Graph API and Client library documentation. I'll update the answer if I find a sample closer to your exact scenario.

How can I implement user permissions on operations in Azure API Management?

I have created a .NET Core 2.0 API and published it to Azure. I have an API Management (APIM) instance fronting that API and doing all the wonderful things that it does. However, there is one thing I cannot seem to wrap my head around or find any documentation for. Authorization on operations. (Not to be confused with authentication, which I have working very well).
My API is a simple RESTful service with CRUD actions. Let's take a read operation for example:
GET /api/owner/{ownerid}/thing/{thingid}
In this case, what I want to be able to do is to grant users permissions to READ THINGS within a specific OWNER. The same user may not have read permissions with a different owner. If the user has permissions, 200 OK; otherwise, 403 Forbidden.
Leaving this completely carte blanche, what are some suggestions for implementing this? I assume an inbound policy for each operation within APIM is where the action will take place? If so, how?
Update 1
I was informed of the possibility of using the same validate-jwt policy at the individual operation levels to append to the validate-jwt policy at the root. The idea is that the root policy validates that the user is authenticated while the operation policy checks for specific claims. This appears to work well, but is that the correct method, or just a hack?
Update 2
For the validate-jwt option to work, the permission model would need to align well with roles and groups; otherwise, it's just as much work as setting up your own custom database wherein at least you benefit from your own rules. In the end, I put the permissions in an Azure Storage Account table (any database will do) and used a send-request (with appropriate caching) to gather permissions based on the current operation and user. It works well, but "feels wrong". I am happy to share details to anyone who wants. In the meantime, I'll leave this open for now in case someone has a better idea.
Ultimately the only way to do so is by using policies at operation level. you can use validate-jwt to check for specific claims, you can check some other credentials that are passed to you as a part of request. Or you can use send-request to call some other service and ask for user permissions. In APIM itself there is no place to store any user related data besides some basic info, thus it is required for such authorization information to come from outside of APIM.
In the end it appears that there is no built-in solution. Rolling your own permission model and then validating it yourself is the way to go.
However...
This can still be done in APIM. As I mentioned in my second update, I was able to make a custom solution work. The way it was done was to use an inbound policy at the "all operations" level to retrieve permissions. (A caching mechanism was used so as not to retrieve the permissions on every single call.) Then, each operation determines if the user has permission to that specific operation based on the parameters that were passed in. (That is also cached.)
The result is that the root API has no authentication or authorization built-in, but APIM does and the appropriate behavior is observed.
Still, the preference would be an RBAC approach. For example, imagine the individual operations being seen as services as in this role definition:
{
"Name": "{rolename}",
"Id": "{roleid}",
"IsCustom": true,
"Description": "{roledescription}",
"Actions": [
"GET {myapi}/owner/{ownerid}/*",
"POST {myapi}/owner/{ownerid}/*",
],
"NotActions": [],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/{subscriptionid}"
]
}
If that were possible, we could create roles, assign them to users/groups at the subscription level, then have the claims automatically passed to APIM where they can be evaluated like any other claim.

Unable To Create Schema Extensions

We have multiple Azure accounts for our various environments. I'm able to create schema extensions on the accounts we use for preproduction and development but for our production Azure account I'm unable to create schema extension even though setups are exactly identical.
Like our other accounts I use OAuth 2.0 token of a global admin and make HTTP POST to https://graph.windows.net/ourinstance.onmicrosoft.com/applications/ourmultitenantappId/extensionProperties?api-version=1.6 with the payload:
{
"name": "SA",
"dataType": "String",
"targetObjects": [
"User"
]
}
Graph API returns with HTTP 403 Forbidden with Authorization_RequestDenied error message.
I have definitely verified user account I'm using has global admin access role, I have created multiple global admin user accounts in old Azure portal and the new Azure portal, I have compared all user and multitenant app settings between the production Azure account and preproduction Azure account and have compared the manifests as well but to no avail.
I have done all these checked for at least 5 times. I'm at a loss why I keep getting Authorization_RequestDenied error message.
Anything I could have possibly missed?
As far As I know, there are two kinds of 403 error.
First one is like that Insufficient privileges to complete the operation. For this issue, please ensure the app has Directory.ReadWrite.All permission.
And the second one error is like The size of the object has exceeded its limit. Please reduce the number of values and retry your request. This error occur when if an application tries to set a value for an additional extension property on an object for which 100 extension property values have already been set. At present, there is no work around for this issue please check whether there are schema extensions which is not used and unregistered the extension.
Got the problem resolved through Microsoft Support.
Turns out OAuth token didn't have necessary permissions despite the fact I have added permissions needed in UI. I had to explicitly grant admin consent to the application using https://login.microsoftonline.com/{tenant-id}/oauth2/authorize?client_id={client-id}&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2F&response_mode=query&resource=https%3A%2F%2Fgraph.windows.net%2F&state=12345&prompt=admin_consent

Resources