Category: Microsoft
Category Archives: Microsoft
Bing won’t Index My site.
I have been trying in vain for the last month to get my site indexed by Bing. The site has a robots.txt, has a sitemap and is indexed by Google. I’ve used IndexNow, I have followed the Webmaster Guidelines, which by the way is some sort of bible that they just throw at you in case they can’t index you. They don’t give me any specific reason as to why…simply and confusingly they just say,
The inspected URL is known to Bing but has some issues which are preventing indexation. We recommend you to follow Bing Webmaster Guidelines to increase your chances of indexation.
I have reached out to Bing Webmaster Support on several occasions and I get the automated reply. This is so insanely frustrating and I’ve seen it on thread after thread that others have experienced the EXACT same issue. Why does Microsoft ignore this issue and not help users who are experiencing the same issue? I’ve seen threads just like this get shut down but I’m going to raise the question again in hopes that someone can help.
I have been trying in vain for the last month to get my site indexed by Bing. The site has a robots.txt, has a sitemap and is indexed by Google. I’ve used IndexNow, I have followed the Webmaster Guidelines, which by the way is some sort of bible that they just throw at you in case they can’t index you. They don’t give me any specific reason as to why…simply and confusingly they just say, The inspected URL is known to Bing but has some issues which are preventing indexation. We recommend you to follow Bing Webmaster Guidelines to increase your chances of indexation.I have reached out to Bing Webmaster Support on several occasions and I get the automated reply. This is so insanely frustrating and I’ve seen it on thread after thread that others have experienced the EXACT same issue. Why does Microsoft ignore this issue and not help users who are experiencing the same issue? I’ve seen threads just like this get shut down but I’m going to raise the question again in hopes that someone can help. Read More
INDEX Match or Filter
Dear Experts,
Greetings!
I have a Data as below, in Column “E”, I populated the Top 15 values from Column “B”, now I want to have the Row Labels in Column “F” against each of the items , 2 samples in cell E5 and E6:-
Thanks in Advance,
Attached sheet.
Br,
Anupam
Dear Experts, Greetings!I have a Data as below, in Column “E”, I populated the Top 15 values from Column “B”, now I want to have the Row Labels in Column “F” against each of the items , 2 samples in cell E5 and E6:-Thanks in Advance,Attached sheet.Br,Anupam Read More
Calculate median in quartile
Hi group.
Need your help
I have a excel table. In column a is the employee code, in column b is the sex (m man, w woman) and in column c is the amount of their payment.
I need to calculate the paymen median of quartile 1, median of quartile 2, median of quartile 3 and median of quartile 4 for man and woman separately.
Thanks in advance
Hi group.Need your helpI have a excel table. In column a is the employee code, in column b is the sex (m man, w woman) and in column c is the amount of their payment.I need to calculate the paymen median of quartile 1, median of quartile 2, median of quartile 3 and median of quartile 4 for man and woman separately.Thanks in advance Read More
Need Help with a Formula to find difference in cell range
Need help figuring out a formula for calculating weight lost/gained over a cell range. Very beginner level knowledge on my end so I’m struggling with a formula to add/subtract the difference from the starting weight on 3/25/24 in cell C5 to the ending weight on 6/21/24 in cell F5. I need just the total weight lost/gained summed in cell G5.
Example: someone starts at 200, goes to 190, back to 195, then finishes at 185, how do I capture that fluctuation in a formula?
Screen shot below. Thanks in advance for any help!
Need help figuring out a formula for calculating weight lost/gained over a cell range. Very beginner level knowledge on my end so I’m struggling with a formula to add/subtract the difference from the starting weight on 3/25/24 in cell C5 to the ending weight on 6/21/24 in cell F5. I need just the total weight lost/gained summed in cell G5. Example: someone starts at 200, goes to 190, back to 195, then finishes at 185, how do I capture that fluctuation in a formula? Screen shot below. Thanks in advance for any help! Read More
How to find the duplicate
CASINETTO TRADING LLC , PO BOX : 125905 , DUBAI , UAECASINETTO TRADING LLC, PO BOX: 125905, DUBAI, UAE
In this condition, both customers are the same.
In conditional formatting, the duplicate is used. But conditional formatting duplicate is not working
CASINETTO TRADING LLC , PO BOX : 125905 , DUBAI , UAECASINETTO TRADING LLC, PO BOX: 125905, DUBAI, UAEIn this condition, both customers are the same.In conditional formatting, the duplicate is used. But conditional formatting duplicate is not working Read More
Scans succeeded but monitoring links show no information
After I run scans on Azure Data Lake Storage Gen2, which succeeded. But when I went on monitoring links, there is no data show. What could have gone wrong and how do I fix it?
After I run scans on Azure Data Lake Storage Gen2, which succeeded. But when I went on monitoring links, there is no data show. What could have gone wrong and how do I fix it? Read More
Nota de rodapé no Word
Bom dia
Como incluir uma nota de rodapé já existente no Word?
Bom diaComo incluir uma nota de rodapé já existente no Word? Read More
Windows 11 store apps showing blank white icons
Fresh install of Windows 11 – latest updates. Starfield, Forza, Injustice – all purchased from the Microsoft Store. Games run fine but after a few days they show the white page / blank icon. Had one icon that remained and after running sfc /scannow that icon is now blank too.
Have seen a few posts similar to this without resolution. Is there a way to contact MS directly?
Fresh install of Windows 11 – latest updates. Starfield, Forza, Injustice – all purchased from the Microsoft Store. Games run fine but after a few days they show the white page / blank icon. Had one icon that remained and after running sfc /scannow that icon is now blank too. Have seen a few posts similar to this without resolution. Is there a way to contact MS directly? Read More
Account does not exist
Hello
Please i need your help on this issue.
I have recently purchased several email addresses and licenses, when logging into office the dialog box says my account does not exist.
The dialog box says my account does not exist
Hello Please i need your help on this issue. I have recently purchased several email addresses and licenses, when logging into office the dialog box says my account does not exist. The dialog box says my account does not exist Read More
Updates to Security Admin permissions for Microsoft Copilot for Security
Microsoft Tech Community – Latest Blogs –Read More
Seamless Identity Integration: Azure API Management with Azure AD B2C (AADB2C)
Seamless Identity Integration: Azure API Management with Azure (AADB2C)
Introduction
Azure API Management (APIM) is a robust platform for managing and securing your APIs. In this blog post, we will guide you through integrating Azure API Management with Azure Active Directory B2C (AADB2C) for identity management. This integration enhances the security of your APIs by requiring user authentication before access is granted. We will break down the process into three key steps: setting up the Developer Portal to use AADB2C, configuring APIM to use OAuth 2.0 for authorization, and implementing token validation to ensure secure access.
This blog post consolidates information from three separate Microsoft Learn documents, providing a comprehensive, end-to-end guide for setting up AADB2C authentication in your APIM instance. Whether you’re accessing your API via cURL, Postman, the Developer Portal, or other clients, this guide will ensure that your APIM instance is configured to handle authentication from AADB2C.
Part One: Setting up Developer Portal with AADB2C
In this section, we will prepare the Developer Portal to use AADB2C for user authentication.
Create Sign-Up and Sign-In Policy in AADB2C
Set up a “Sign up and sign in” policy in AADB2C.
For this you can use the same policy for both, just create a “Sign up and sign in” policy in AADB2C
Ensure you select all the attributes like Given Name, Surname, and return claims like Email Addresses and User’s ObjectID. Here are the minimum requirements:
Collect Attributes: Given Name, Surname
Return claims: Given Name, Surname, Email Addresses, User’s ObjectID
Configure Identity in Developer Portal
Add AADB2C as an identity provider in the Developer Portal.
Open a new tab and navigate the Azure Portal for APIM and under the Developer Portal, select Identities:
Add a provider by clicking the “Add” button. That will prompt you with a choice of Types, you will want to select “Azure Active Directory B2C”
Use the MSAL (Microsoft Authentication Library) client library for authentication, do not worry about the rest of the attributes just yet, we will come back to them.
Copy the redirect URL for the Developer Portal.
We will need this to create the backend app registration in the next step.
Create Backend App Registration in AADB2C
Register an app to represent your API.
Now, go back to your AADB2C tab, select App Registrations from the list on the left and click “New Registration”.
Enter a name for the app registration, for my example I am calling it `apim-api-backend`
Select the Supported account types that best fit your scenario
Setup the redirect URI (Uniform Resource Identifier) with a Single-page application (SPA) and paste the URI you copied from above.
Click register
Create a client secret for this app registration.
Now that the app registration is created, you will need to create a client secret
Open the app registration you just created
On the overview tab, you will see the Application (client) ID, copy that for later.
Then go to Certificates & secrets and create a new client secret. After you hit the Add button, it will show you the ‘Value’ of your secret. You will need to save this as it will not be shown again for security reasons.
Add Identity Provider in APIM
Now head back to APIM tab you left open earlier (or just open a new tab now and navigate to the APIM instance we have been working with), go to Identities, Add Identity Provider page and fill out the client id, and client secret with the values you copied from above
You will also need to fill out the Signin tenant. This is your AADB2C tenant, and it has the following format: <aadb2c-tenant-name>.onmicrosoft.com. After you fill out that text box, it should fill out the Authority for you, but if not, it is <aadb2c-tenant-name>.b2clogin.com.
Next fill out the sign-up and sign-in policy (we created this earlier in Step 1, so go copy the name you used above), if you have the profile editing and password reset policies you can add those here as well.
Click Add
Now that you have created everything, you will need to republish the developer portal for these configurations to take effect.
It will take a few seconds for the portal to publish, but once it is complete you should be able to navigate to the Developer Portal and see a button to login using AADB2C.
Test configuration
Confirm that you can successfully log into the developer portal using an AADB2C login.
Part Two: Configuring APIM for OAuth 2.0 Authorization
Now that we have AADB2C integrated as an Identity into the Developer Portal, let us configure APIM for OAuth 2.0 authorization. This will let us ensure we can send the request with an Authorization header from the developer portal.
Modify Backend App Registration
Add scopes that represent the APIs you are exposing.
Go back to the AADB2C tenant and navigate to App Registrations
Find the app you created above (this will be our backend app registration; it represents our Api) and open it up
Go to expose an Api, and then click ‘Add a scope’
Create a new scope by giving it a name, and display name and a description
Now click ‘Add Scope’
If this is the first scope you are adding it will ask you to create an Application ID URI, you can use the default or put your own in there it will just need to follow URI format
Here is what the ‘Add a scope’ blade looks like
If you have more than one scope you want to add, repeat these steps. The scopes will represent the things the user will be able to do from the API
Create a new app registration for the client (APIM Developer Portal).
Create the new app registration and give it a meaningful name, I would suggestion something with ‘client’ in it
Leave the Redirect uris empty for now and select ‘Register’
Now that the new app registration is created for the client, you will need to create a client secret like you did for the backend app registration.
Make sure you copy the client id and the secret value so you can use it again when we setup the OAuth server in the next few steps.
Allow Access to Backend App Registration
In the client app registration, add permissions to request scopes from the backend app registration.
Open the client app registration, under Api permissions, go to add a Permission
This will give you a list of APIs to select from, use the ‘APIs my organization uses’ filter and find the backend-app you created earlier
Select Delegated Permissions for all the scopes you want to add and select Add permissions
You will then need to grant the admin consent for these new permissions
Add OAuth 2.0 Auth Server in APIM
Configure OAuth 2.0 settings in APIM, providing details from app registrations.
Navigate back to the APIM tab and go to the ‘Oauth 2.0 + OpenID Connect’ section and click the ‘+ Add’ button under the Oauth 2.0 tab
This should open the ‘Add OAuth2 service’ dialog
Name: This will be how APIM identifies the auth server so use names appropriately
Add a description
The Client registration page URL is the page where users can create and manage their accounts, since AADB2C does not have a direct URL for that (you need to navigate via the azure portal) you can just put `http://localhost`
Next select the Auth grant type, the default is Auth Code, but you will want to make sure to follow what you have set up in the app registrations. In my case I selected both Authorization code and Authorization code + PKCE because I set up my client app registration as a SPA. PKCE stands for Proof Key for Code Exchange
Now enter the authorization endpoint URL, you can get this from the Endpoints page on the Overview tab of an app registration, make sure to select the v2 endpoint
Select POST as the auth request method
Now enter the token endpoint URL, you can also get this from the Endpoints page on the Overview tab of an app registration.
Just use the defaults on the ‘Authorization request method’ and ‘Access token sending method’.
In the Default scope, enter the permission that you exposed on the client app registration from the backend app registration just a few steps above this. You must use the fully qualified scope URL as the scope name here
If you have multiple scopes, you can list them all here…space separated
It will have this format <Application ID URI>/<permission name>
Next, fill out the clientId and clientSecret from the client app registration that you saved a moment ago
This will generate the Redirect URI
**Important Step** You will need to go back to the client app registration and add this Redirect URI that will need to be added back to the client app registration
Hit Create and you are done
Now you should have a new OAuth 2.0 server, you will need to republish the developer portal at this point to make sure the latest configuration is deployed
Go back to the APIM tab and go to Portal overview, click the Revisions tab, and click the Publish button. This will take a few seconds, but you can refresh the table and see status.
Add OAuth 2.0 server to your API
Go to APIM and navigate to APIs -> Setting tab and then scroll down to the Security section. Select User authorization to Oauth 2.0 and then in the dropdown list select the Oauth server that we created above.
If you need to use different scopes for a given Api you can override it here at this level using the Override scope checkbox
Test in Developer Portal
Log in using AADB2C credentials in the Developer Portal.
Access APIs and see OAuth 2.0 authorization in action.
In the Try It section you will see something like this:
Hit the dropdown and select the grant type you setup (in our case it is authorization code)
That should trigger an auth call which will pull the token from your initial login (or prompt you for a new login) and transform it appropriately and populate the ‘Authorization’ header in the test request.
Part Three: Adding Token Validation for Security
The last step ensures secure API access by adding token validation by adding a validation policy.
Add Validate-JWT Policy
In APIM, add a validate-jwt policy to the inbound policy.
Go to the Api you want to add the validation to, or you could set it at the global level:
Use the `validate-jwt` policy. You can find the documentation for it here. This is screenshot of what it might look like, I am using `Named Values` for some variables.
Update the <openid-config URL> property with the correct AADB2C endpoint.
After you add that policy, you will want to update the <openid-config URL> property. The format looks like this:
https://<tenant-name>.b2clogin.com/<tenant-name>.onmicrosoft.com/<user-flow-name>/v2.0/.well-known/openid-configuration
If you want to copy and paste it, you can get this endpoint from the Endpoints section on the overview tab of the app registration. It is under the `Azure AD B2C OpenID Connect metadata document`. You will just need to fill out the policy name for you signin policy you created above.
Configure Audience and Issuers
Specify the audience and issuers for token validation.
Testing and Security:
If the JWT (JSON Web Token) is valid, APIM allows the request to continue to the backend.
If the JWT is invalid, APIM blocks the request, enhancing security.
Conclusion
By following these steps, you can seamlessly integrate Azure API Management with Azure ADB2C, ensuring that your APIs are secure and accessible only to authorized users. This setup offers a robust authentication and authorization mechanism for your APIs, making them more reliable and trustworthy.
Microsoft Tech Community – Latest Blogs –Read More
Samsung Email not requiring to authenticate via MFA
Hi, about 3 weeks ago, my Samsung email doesn’t require me to re-authenticate via MFA. We have ours set to expire in 24 hours and every device prompts to re-authenticate except my Samsung mail.
Opened a ticket with support and they claim that it’s because per-user MFA is being deprecated in 2025. They recommend to test disabling that and used conditional access instead. Still doesn’t work the way I’m thinking it should.
Anyone else experiencing this?
Tommy
Hi, about 3 weeks ago, my Samsung email doesn’t require me to re-authenticate via MFA. We have ours set to expire in 24 hours and every device prompts to re-authenticate except my Samsung mail. Opened a ticket with support and they claim that it’s because per-user MFA is being deprecated in 2025. They recommend to test disabling that and used conditional access instead. Still doesn’t work the way I’m thinking it should. Anyone else experiencing this? Tommy Read More
Creating Start Menu Shortcuts to Launch .CMD Files
I am looking to create an MSIX for a custom app. The app is basically dropped in a folder on C:. I would like to create a Start Menu shortcut in …Start MenuProgramsNewApp and have it point to a .CMD file in the installation folder and use an .ico file in that same folder for the icon.
Is this doable? Super easy to do with an MSI but I’m challenged to do it in an MSIX.
Thanks in advance!
Brian
I am looking to create an MSIX for a custom app. The app is basically dropped in a folder on C:. I would like to create a Start Menu shortcut in …Start MenuProgramsNewApp and have it point to a .CMD file in the installation folder and use an .ico file in that same folder for the icon. Is this doable? Super easy to do with an MSI but I’m challenged to do it in an MSIX. Thanks in advance!Brian Read More
Remove the duplicate
In this below example the we needed to only retain the “3A Cryogenic FZE” and 3C Metal Middle East FZE”
Other remaining should be delete
Some More Examples
I want to remove the “A ONE SWITCHGEAR INDUSTRIES LLC,Manoj Pillai
In this below example the we needed to only retain the “3A Cryogenic FZE” and 3C Metal Middle East FZE” Other remaining should be delete Some More ExamplesI want to remove the “A ONE SWITCHGEAR INDUSTRIES LLC,Manoj Pillai Read More
Microsoft Security Exposure Management Graph: unveiling the power
Introduction
In the complicated and rapidly evolving realm of cybersecurity, Exposure Management plays a pivotal role in fortifying organization’s defenses against potential threats. To empower security teams, Microsoft Security Exposure Management has unveiled two new powerful tables within Advanced Hunting: ExposureGraphNodes and ExposureGraphEdges.
The introduction of these tables opens novel capabilities for security teams. It enables efficient investigation of security posture across organizational assets. This is the first in a series of posts where we will present the tables and share investigation scenarios (along with relevant queries) for Advanced Hunting. These queries unlock capabilities that were previously unattainable. We’ll provide screenshots and Kusto Query Language snippets to guide you through your reading.
Understanding the tables
As John Lambert’s saying that is well-known in the security domain goes, ‘Defenders think in lists. Attackers think in graphs. As long as this is true, attackers win.’ By exposing the context around each asset, relations between assets and the graph-based toolset for exploring them, we hope to start changing this.
Context: Beyond Asset Information
Think of assets and entities as points on a graph, and of relations between them as links between these points. Traditionally, when dealing with an asset (such as a server, device, or network component), we have focused on gathering specific information about that asset. With the powerful combination of the Attack Map and Extended Security Posture Management tables, we can gain a better perspective that zooms out and reveals the entire environment surrounding each asset.
The Tables:
This table represents all the nodes in the Attack Surface Map. According to the table documentation, ExposureGraphNodes contain organizational entities and their properties. These entities include devices, identities, user groups, and cloud assets (such as virtual machines, storage, and containers). Each node corresponds to an individual entity and encapsulates information about its characteristics, attributes, and security-related insights within the organizational structure.
Before diving into specific scenarios, we recommend examining the available data first.
Running the following query will retrieve one node for each type in the environment. This will allow you to see the kinds of nodes present and their properties.
ExposureGraphNodes
| summarize take_any(*) by NodeLabel
This table represents all the edges in the Attack Surface Map. Each edge describes a pairwise relationship between two of the ExposureGraphNodes we have just reviewed. As stated in Advanced Hunting documentation: “The ExposureGraphEdges schema, along with the complementing ExposureGraphNodes schema, provides visibility into relationships between entities and assets in the graph. Many hunting scenarios require exploration of entity relationships and attack paths. For example, when hunting for devices exposed to a specific critical vulnerability, knowing the relationship between entities, can uncover critical organizational assets.”
Similarly, we recommend exploring your data related to edges. Running the following query will retrieve one edge for each edge type in your organization. After running the query, you’ll gain insights into the relations between your organizational entities and the additional data on them.
ExposureGraphEdges
| summarize take_any(*) by EdgeLabel
Now we would like to describe several security-related scenarios that can be investigated using the security exposure graph.
Scenarios
Scenario 1: Nodes with specific properties
Security Exposure Graph displays various assets and entities in your organization (such as storage accounts, devices and users) as nodes in ExposureGraphNodes table, while various properties (such as criticality, sensitive data) appear as node properties.
For proper posture management, it might be interesting to find all nodes filtered by specific types and/or properties. For example, we might want to find all critical assets, or all virtual machines that are exposed to the internet and have vulnerabilities.
Example 1A: Critical assets
Query:
ExposureGraphNodes
| project NodeLabel, NodeName, NodeId, Categories
, criticalityLevel = toint(NodeProperties.rawData.criticalityLevel.criticalityLevel)
| where criticalityLevel > 0
| sort by criticalityLevel desc
Output:
Example 1B: Virtual Machines with specific vulnerabilities (RCE and privilege escalation)
Query:
ExposureGraphNodes
| where NodeLabel == ‘microsoft.compute/virtualmachines’
| project NodeLabel, NodeName, NodeId, NodeProperties
, vulnerableToRCE = isnotnull(NodeProperties.rawData.vulnerableToRCE.type)
, vulnerableToPrivilegeEscalation = isnotnull(NodeProperties.rawData.highRiskVulnerabilityInsights.vulnerableToPrivilegeEscalation)
| where vulnerableToRCE > 0 or vulnerableToPrivilegeEscalation > 0
Output:
Since filtering the assets by specific types and properties can cover various scenarios, it might be useful to wrap such queries in a generic format, that will allow repeated usage with various parameters:
let XGraph_NodesWithTypesAndProperties = (nodeTypes:dynamic, nodeProperties:dynamic)
{
let propertiesFormatted = strcat(‘(‘, strcat_array(nodeProperties, ‘|’), ‘)’);
ExposureGraphNodes
| where NodeLabel in (nodeTypes) or nodeTypes == “[“”]”
| project NodeName, NodeLabel, NodeId, Categories
, propertiesExtracted = iff(nodeProperties != “[“”]”, extract_all(propertiesFormatted, tostring(NodeProperties)), pack_array(”))
| mv-apply propertiesExtracted on (
summarize propertiesExtracted = make_set_if(propertiesExtracted, isnotempty(propertiesExtracted))
)
| extend countProperties = coalesce(array_length(propertiesExtracted), 0)
| where countProperties > 0 or nodeProperties == “[“”]”
| sort by countProperties desc
};
Sample usage – find all vulnerable Virtual Machines:
XGraph_NodesWithTypesAndProperties(
nodeTypes=pack_array(‘microsoft.compute/virtualmachines’)
, nodeProperties=pack_array(‘vulnerableToRCE’, ‘vulnerableToPrivilegeEscalation’))
Note that if any of the parameters is an empty array, the function will not filter on it and bring assets of all types or properties. For example, the following will bring vulnerable assets of any type that have RCE or Privilege Escalation vulnerabilities:
XGraph_NodesWithTypesAndProperties(
nodeTypes=pack_array(”)
, nodeProperties=pack_array(‘vulnerableToRCE’, ‘vulnerableToPrivilegeEscalation’))
Alternatively, you can create and save several specific functions for common usage and use them without any additional parameters.
let XGraph_VulnerableVMs = () {
let nodeTypesList = pack_array(‘microsoft.compute/virtualmachines’);
let nodePropertiesList = pack_array(‘vulnerableToRCE’, ‘vulnerableToPrivilegeEscalation’);
XGraph_NodesWithTypesAndProperties(nodeTypes = nodeTypesList, nodeProperties = nodePropertiesList)
};
Usage –
XGraph_FindVulnerableVMs()
Any function (with or without parameters) can be saved for repeated usage as described here: Custom functions in the advanced hunting schema – Microsoft Defender XDR | Microsoft Learn.
Scenario 2: Connected nodes with specific properties
The relations between assets appear as edges in ExposureGraphEdges table. For example, users that can access a virtual machine will be connected to it with ‘has permissions to’ edge.
We might want to look for pairs of connected assets while filtering by relevant edge types. For example, we might want to find users that have permissions to access keyvaults.
Example 2A: Users that have access to keyvaults
Query:
ExposureGraphEdges
| where EdgeLabel == ‘has permissions to’ and SourceNodeLabel == ‘user’ and TargetNodeLabel == ‘microsoft.keyvault/vaults’
| project SourceNodeName, SourceNodeLabel, SourceNodeId, EdgeLabel, TargetNodeName, TargetNodeLabel, TargetNodeId
Output:
Alternatively, we might want to filter not only by endpoint types, but also by properties. For this, we need to join the edges table with node table (that contains the node properties) both on source and target. Note that the unique identifier of each asset is the NodeId (and not NodeName).
Example 2B: Critical users that can access storage accounts with sensitive data
Query:
ExposureGraphEdges
| where EdgeLabel == ‘has permissions to’ and SourceNodeLabel == ‘user’ and TargetNodeLabel == ‘microsoft.storage/storageaccounts’
| project SourceNodeName, SourceNodeLabel, SourceNodeId, EdgeLabel, TargetNodeName, TargetNodeLabel, TargetNodeId
| join kind = leftouter (ExposureGraphNodes | project SourceNodeId = NodeId, SourceNodeProperties = NodeProperties) on SourceNodeId
| join kind = leftouter (ExposureGraphNodes | project TargetNodeId = NodeId, TargetNodeProperties = NodeProperties) on TargetNodeId
| extend sourceCriticalityLevel = toint(SourceNodeProperties.rawData.criticalityLevel.criticalityLevel)
, targetSensitiveData = isnotempty(TargetNodeProperties.rawData.containsSensitiveData.type)
| where sourceCriticalityLevel > 0 and targetSensitiveData > 0
| project SourceNodeName, SourceNodeLabel, SourceNodeId, EdgeLabel, TargetNodeName, TargetNodeLabel, TargetNodeId, sourceCriticalityLevel, targetSensitiveData
Output:
We can add (and save) a generic function that looks for edges between nodes with specific types and properties as well.
let XGraph_EdgesWithTypesAndProperties = (sourceTypes:dynamic, sourceProperties:dynamic, targetTypes:dynamic, targetProperties:dynamic)
{
let sourcePropertiesFormatted = strcat(‘(‘, strcat_array(sourceProperties, ‘|’), ‘)’);
let targetPropertiesFormatted = strcat(‘(‘, strcat_array(targetProperties, ‘|’), ‘)’);
let edgeTypes = pack_array(‘has role on’, ‘has permissions to’, ‘can authenticate to’, ‘can authenticate as’
, ‘member of’, ‘contains’);
ExposureGraphEdges
| where EdgeLabel in (edgeTypes)
| where (SourceNodeLabel in (sourceTypes) or sourceTypes == “[“”]”) and (TargetNodeLabel in (targetTypes) or targetTypes == “[“”]”)
| project SourceNodeName, SourceNodeLabel, SourceNodeId, EdgeLabel, TargetNodeName, TargetNodeLabel, TargetNodeId
| join hint.strategy = shuffle kind = leftouter (ExposureGraphNodes | project SourceNodeId = NodeId, SourceNodeProperties = NodeProperties) on SourceNodeId
| join hint.strategy = shuffle kind = leftouter (ExposureGraphNodes | project TargetNodeId = NodeId, TargetNodeProperties = NodeProperties) on TargetNodeId
| extend sourcePropertiesExtracted = iff(sourceProperties != “[“”]”, extract_all(sourcePropertiesFormatted, tostring(SourceNodeProperties)), pack_array(”))
, targetPropertiesExtracted = iff(targetProperties != “[“”]”, extract_all(targetPropertiesFormatted, tostring(TargetNodeProperties)), pack_array(”))
| mv-apply sourcePropertiesExtracted, targetPropertiesExtracted on (
summarize sourcePropertiesExtracted = make_set_if(sourcePropertiesExtracted, isnotempty(sourcePropertiesExtracted))
, targetPropertiesExtracted = make_set_if(targetPropertiesExtracted, isnotempty(targetPropertiesExtracted))
)
| extend countSourceProperties = coalesce(array_length(sourcePropertiesExtracted), 0)
, countTargetProperties = coalesce(array_length(targetPropertiesExtracted), 0)
| where (countSourceProperties > 0 or sourceProperties == “[“”]”) and (countTargetProperties > 0 or targetProperties == “[“”]”)
| project SourceNodeName, SourceNodeLabel, SourceNodeId, EdgeLabel, TargetNodeName, TargetNodeLabel, TargetNodeId
, sourcePropertiesExtracted, countSourceProperties, targetPropertiesExtracted, countTargetProperties
| sort by countSourceProperties desc, countTargetProperties desc
};
Sample usage – critical users that have access to containers or storage accounts that are either critical or have sensitive data:
XGraph_EdgesWithTypesAndProperties(
sourceTypes = pack_array(‘user’)
, sourceProperties = pack_array(‘criticalityLevel’)
, targetTypes = pack_array(‘container’, ‘microsoft.storage/storageaccounts’)
, targetProperties = pack_array(‘containsSensitiveData’, ‘criticalityLevel’))
This function can also be wrapped and used as is for common scenarios. For example, we can create the following function to cover the scenario above:
let XGraph_CriticalUsersToCriticalOrSensitiveStorage = () {
let sourceTypesList = pack_array(‘user’);
let sourcePropertiesList = pack_array(‘criticalityLevel’);
let targetTypesList = pack_array(‘container’, ‘microsoft.storage/storageaccounts’);
let targetPropertiesList = pack_array(‘containsSensitiveData’, ‘criticalityLevel’);
XGraph_EdgesWithTypesAndProperties(sourceTypes = sourceTypesList, sourceProperties = sourcePropertiesList
, targetTypes = targetTypesList, targetProperties = targetPropertiesList)
};
Usage –
FindCriticalUsersToCriticalOrSensitiveStorage()
Scenario 3: Paths between nodes with specific properties
Sometimes nodes can be connected in a non-direct way. For example, a virtual machine can have access to a keyvault using SSH key or managed identity. Alternatively, user can have permissions to a subscription containing storage accounts – thus gaining access to all of them.
A great way to explore such connections and find the multi-step paths is using Kusto graph capabilities – namely the make-graph and graph-match operators (you can learn more about Kusto graph semantics here). These operators allow to build paths between endpoints (source and target nodes) according to conditions on endpoints or any of the steps.
Example 3A: Users that have access to storage accounts with sensitive data
Query:
ExposureGraphEdges
| where EdgeLabel in (‘has role on’, ‘has permissions to’, ‘can authenticate to’, ‘can authenticate as’, ‘member of’, ‘contains’)
| make-graph SourceNodeId –> TargetNodeId with (ExposureGraphNodes | project NodeId, NodeName, NodeLabel, NodeProperties) on NodeId
// Look for existing paths between source nodes and target nodes with less than predefined number of hops
| graph-match (s)-[e*1..4]->(t)
where (s.NodeLabel == ‘user’
and t.NodeLabel == ‘microsoft.storage/storageaccounts’ and isnotnull(t.NodeProperties.rawData.containsSensitiveData.type))
project SourceName = s.NodeName
, SourceType = s.NodeLabel
, SourceId = s.NodeId
, SourceExposedToInternet = s.NodeProperties.rawData.exposedToInternet.type
, TargetName = t.NodeName
, TargetType = t.NodeLabel
, TargetId = t.NodeId
, TargetcontainsSensitiveData = t.NodeProperties.rawData.containsSensitiveData.type
, edgeIds = e.EdgeId
, edgeLabels = e.EdgeLabel
| extend pathLength = array_length(edgeIds) + 1
Output:
Example 3B: SQL servers or managed instances with basic authentication that have access to keyvaults
Query:
ExposureGraphEdges
| where EdgeLabel in (‘has role on’, ‘has permissions to’, ‘can authenticate to’, ‘can authenticate as’, ‘member of’, ‘contains’)
| make-graph SourceNodeId –> TargetNodeId with (ExposureGraphNodes | project NodeId, NodeName, NodeLabel, NodeProperties) on NodeId
// Look for existing paths between source nodes and target nodes with less than predefined number of hops
| graph-match (s)-[e*1..6]->(t)
where (s.NodeLabel in (‘microsoft.sql/servers’, ‘microsoft.sql/managedinstances’)
and isnotnull(s.NodeProperties.rawData.allowsBasicAuth)
and t.NodeLabel == ‘microsoft.keyvault/vaults’)
project SourceName = s.NodeName
, SourceType = s.NodeLabel
, SourceId = s.NodeId
, SourceExposedToInternet = s.NodeProperties.rawData.exposedToInternet.type
, TargetName = t.NodeName
, TargetType = t.NodeLabel
, TargetId = t.NodeId
, TargetcontainsSensitiveData = t.NodeProperties.rawData.containsSensitiveData.type
, edgeIds = e.EdgeId
, edgeLabels = e.EdgeLabel
| extend pathLength = array_length(edgeIds) + 1
Output:
We can wrap up this logic in a generic function XGraph_PathExploration that allows to find and explore all relevant paths between source and target nodes, filtered by relevant types and properties.
This is done by changing the following required parameters in array format: sourceTypes, sourceProperties, targetTypes, targetProperties.
The following parameters have default values and are optional: maxPathLength controls the maximum length of found paths (default value 6) and resultCountLimit controls that maximum number of output (default value 50000).
The function XGraph_PathExploration goes over edges defined in non-exposed edgeTypes parameter (which you can also change) and creates paths between relevant endpoint, from single hops up to length defined by maxPathLength parameter.
After creating the paths, the function exposes the endpoints and their properties, shows the full paths in FullPath field and adds the path length metric.
let XGraph_PathExploration = (sourceTypes:dynamic, sourceProperties:dynamic
, targetTypes:dynamic, targetProperties:dynamic
, maxPathLength:long = 6, resultCountLimit:long = 10000)
{
let edgeTypes = pack_array(‘has permissions to’, ‘contains’, ‘can authenticate as’, ‘can authenticate to’, ‘can remote interactive logon to’
, ‘can interactive logon to’, ‘can logon over the network to’, ‘contains’, ‘has role on’, ‘member of’);
let sourceNodePropertiesFormatted = strcat(‘(‘, strcat_array(sourceProperties, ‘|’), ‘)’);
let targetNodePropertiesFormatted = strcat(‘(‘, strcat_array(targetProperties, ‘|’), ‘)’);
let nodes = (
ExposureGraphNodes
| project NodeId, NodeName, NodeLabel
, SourcePropertiesExtracted = iff(sourceProperties != “[“”]”, extract_all(sourceNodePropertiesFormatted, tostring(NodeProperties)), pack_array(”))
, TargetPropertiesExtracted = iff(targetProperties != “[“”]”, extract_all(targetNodePropertiesFormatted, tostring(NodeProperties)), pack_array(”))
, criticalityLevel = toint(NodeProperties.rawData.criticalityLevel.criticalityLevel)
| mv-apply SourcePropertiesExtracted, TargetPropertiesExtracted on (
summarize SourcePropertiesExtracted = make_set_if(SourcePropertiesExtracted, isnotempty(SourcePropertiesExtracted))
, TargetPropertiesExtracted = make_set_if(TargetPropertiesExtracted, isnotempty(TargetPropertiesExtracted))
)
| extend CountSourceProperties = coalesce(array_length(SourcePropertiesExtracted), 0)
, CountTargetProperties = coalesce(array_length(TargetPropertiesExtracted), 0)
| extend SourceRelevancyByLabel = iff(NodeLabel in (sourceTypes) or sourceTypes == “[“”]”, 1, 0)
, TargetRelevancyByLabel = iff(NodeLabel in (targetTypes) or targetTypes == “[“”]”, 1, 0)
, SourceRelevancyByProperties = iff(CountSourceProperties > 0 or sourceProperties == “[“”]”, 1, 0)
, TargetRelevancyByProperties = iff(CountTargetProperties > 0 or targetProperties == “[“”]”, 1, 0)
| extend SourceRelevancy = iff(SourceRelevancyByLabel == 1 and SourceRelevancyByProperties == 1, 1, 0)
, TargetRelevancy = iff(TargetRelevancyByLabel == 1 and TargetRelevancyByProperties == 1, 1, 0)
);
let edges = (
ExposureGraphEdges
| where EdgeLabel in (edgeTypes)
| project EdgeId, EdgeLabel, SourceNodeId, SourceNodeName, SourceNodeLabel, TargetNodeId, TargetNodeName, TargetNodeLabel
);
let paths = (
edges
// Build the graph from all the nodes and edges and enrich it with node data (properties)
| make-graph SourceNodeId –> TargetNodeId with nodes on NodeId
// Look for existing paths between source nodes and target nodes with up to predefined number of hops
| graph-match (s)-[e*1..maxPathLength]->(t)
// Filter only by paths with relevant sources and targets – filtered by node types and properties
where (s.SourceRelevancy == 1 and t.TargetRelevancy == 1)
project SourceName = s.NodeName
, SourceType = s.NodeLabel
, SourceId = s.NodeId
, SourceProperties = s.SourcePropertiesExtracted
, CountSourceProperties = s.CountSourceProperties
, SourceRelevancy = s.SourceRelevancy
, TargetName = t.NodeName
, TargetType = t.NodeLabel
, TargetId = t.NodeId
, TargetProperties = t.TargetPropertiesExtracted
, CountTargetProperties = t.CountTargetProperties
, TargetRelevancy = t.TargetRelevancy
, EdgeLabels = e.EdgeLabel
, EdgeIds = e.EdgeId
, EdgeAllTargetIds = e.TargetNodeId
, EdgeAllTargetNames = e.TargetNodeId
, EdgeAllTargetTypes = e.TargetNodeLabel
| extend PathLength = array_length(EdgeIds) + 1
, PathId = hash_md5(strcat(SourceId, strcat(EdgeIds), TargetId))
);
let relevantPaths = (
paths
| extend NodesInPath = array_concat(pack_array(SourceId), EdgeAllTargetIds), NodeLabelsInPath = array_concat(pack_array(SourceType), EdgeAllTargetTypes)
| extend NodesInPathList = NodesInPath
// Wrap the path into meaningful format (can be tweaked as needed)
| mv-expand with_itemindex = SortIndex EdgeIds to typeof(string), EdgeLabels to typeof(string)
, NodesInPath to typeof(string), NodeLabelsInPath to typeof(string)
| sort by PathId, SortIndex asc
| extend step = strcat(
iff(isnotempty(NodesInPath), strcat(‘(‘, NodeLabelsInPath, ‘:’, NodesInPath, ‘)’), ”)
, iff(isnotempty(SourceProperties) and NodesInPath == SourceId, SourceProperties, ”)
, iff(isnotempty(TargetProperties) and NodesInPath == TargetId, TargetProperties, ”)
, iff(isnotempty(EdgeLabels), strcat(‘-‘, EdgeLabels, ‘->’), ”))
| summarize StepSequence = make_list(step), take_any(*) by PathId
// Project relevant fields
| project SourceName, SourceType, SourceId, SourceProperties, CountSourceProperties, SourceRelevancy
, TargetName, TargetType, TargetId, TargetProperties, CountTargetProperties, TargetRelevancy
, PathId, PathLength, Path = StepSequence
| top resultCountLimit by PathLength asc
);
relevantPaths
};
After defining this function, we can use it by providing the lists of relevant source types, source properties, target types and target properties as well as giving other values to optional parameters. If any of the required parameters is an empty array, no filtering will be applies.
For example, we can look for all paths between different compute resources that have various vulnerabilities or are exposed to the internet, to various storage assets that are either critical or contain sensitive data:
let sourceTypesList = pack_array(‘microsoft.compute/virtualmachines’, ‘compute.instances’, ‘ec2.instance’);
let sourcePropertiesList = pack_array(‘vulnerableToPrivilegeEscalation’, ‘vulnerableToRCE’, ‘hasHighSeverityVulnerabilities’, ‘exposedToInternet’);
let targetTypesList = pack_array(‘microsoft.sql/servers’, ‘s3.bucket’, ‘rds.db’, ‘storage.buckets’, ‘microsoft.storage/storageaccounts’, ‘rds.snapshot’, ‘microsoft.documentdb/databaseaccounts’);
let targetPropertiesList = pack_array(‘criticalityLevel’, ‘containsSensitiveData’);
XGraph_PathExploration(sourceTypes=sourceTypesList, sourceProperties=sourcePropertiesList
, targetTypes=targetTypesList, targetProperties=targetPropertiesList)
Output:
Note that the FullPath field contains the full description of the path, with node and edge types and properties, for example:
(microsoft.compute/virtualmachines:ffcbc)[exposedToInternet]-can authenticate as->(managedidentity:23e7)-has role on->(microsoft.sql/servers:3d5c)[criticalityLevel]
This shows how the endpoints are connected, and can be used to find the proper disruption method (e.g., removing Managed Identity connecting exposed VM and critical SQL server).
Alternatively, we can look for all assets that allow public access or exposed to Internet (without specifying source type) to all keyvaults (without specifying target properties):
let sourceTypesList = pack_array(”);
let sourcePropertiesList = pack_array(‘allowsPublicAccess’, ‘exposedToInternet’);
let targetTypesList = pack_array(‘microsoft.keyvault/vaults’);
let targetPropertiesList = pack_array(”);
XGraph_PathExploration(sourceTypes=sourceTypesList, sourceProperties=sourcePropertiesList
, targetTypes=targetTypesList, targetProperties=targetPropertiesList)
You can also wrap the XGraph_PathExploration function in a specific function with predefined parameters and use it directly for commonly used scenarios. For example, the first scenario in this section can be covered by the following function:
let XGraph_VulnerableOrExposedVMsToCriticalOrSensitiveStorage = ()
{
let sourceTypesList = pack_array(‘microsoft.compute/virtualmachines’, ‘compute.instances’, ‘ec2.instance’);
let sourcePropertiesList = pack_array(‘vulnerableToPrivilegeEscalation’, ‘vulnerableToRCE’, ‘hasHighSeverityVulnerabilities’, ‘exposedToInternet’);
let targetTypesList = pack_array(‘microsoft.sql/servers’, ‘s3.bucket’, ‘rds.db’, ‘storage.buckets’, ‘microsoft.storage/storageaccounts’, ‘rds.snapshot’, ‘microsoft.documentdb/databaseaccounts’);
let targetPropertiesList = pack_array(‘criticalityLevel’, ‘containsSensitiveData’);
XGraph_PathExploration(sourceTypes=sourceTypesList, sourceProperties=sourcePropertiesList
, targetTypes=targetTypesList, targetProperties=targetPropertiesList)
};
Usage –
vulnerableOrExposedVMsToCriticalOrSensitiveStorage()
Mastering Security Posture with Microsoft’s Advanced Exposure Management Tables
In this post, we delve into the core components of Microsoft Security Exposure Management – the tables ExposureGraphNodes and ExposureGraphEdges and the graph toolset for exploring them. We explain the schemas and illustrate how these tables improve the investigation of security posture by several real-world scenarios. We also present several generic queries that can be adapted to your usage by specifying the parameters.
This is more than just an introduction; it’s an invitation to master the fundamental elements of these tables. We hope this will be the first step in your ‘thinking in graphs’ transformation in the security domain.
If you are having trouble accessing Advanced Hunting, please start with this guide.
Note: For full Security Exposure Management access, user roles need access to all Defender for Endpoint device groups. Users who have access restricted to specific device groups can access the Security Exposure Management attack surface map and advanced hunting schemas (ExposureGraphNodes and ExposureGraphEdges) for the device groups to which they have access.
We hope you will start exploring your Security Exposure Management Graph and integrating it into your security practice. Stay tuned for more content, as in our upcoming posts will delve even deeper, uncovering more fascinating insights and applications.
Microsoft Tech Community – Latest Blogs –Read More
Lesson Learned #493: Monitoring Application Performance with Server Performance Counters
Today, I worked on a service request where our customer reported several performance issues in their application connecting to Azure SQL Database. After an in-depth analysis, we found that the issue could be related to the server running the application, including resources assigned, network issues, etc.,. Aside from other tools offered by Azure, following, I would like to share the lessons learned using logman that is part of performance monitor tool (perfmon).
Tools Overview
perfmon
The Performance Monitor (perfmon) is a Windows tool that provides a visual interface for monitoring system performance. It can track various performance metrics like CPU usage, memory usage, disk activity, and network activity in real-time.
logman
logman is a command-line tool in Windows that allows you to create and manage performance data collection sets. It can be used to automate the collection of performance data, making it an excellent tool for scheduled and long-term monitoring.
Step-by-Step Guide
Step 1: Create a Data Collector Set with logman
The following script shows how to create a data collector set using logman, configure it to collect various performance counters, and store the data in a CSV file.
Save this script as a Windows Command Batch file (.cmd) and execute it as Administrator:
logman create counter MyDataCollector -f csv -o “C:CountersMyDataCollector”
logman update MyDataCollector -c “MemoryAvailable MBytes”
logman update MyDataCollector -c “TCP(*)*”
logman update MyDataCollector -c “Network Interface(*)*”
logman update MyDataCollector -c “Process(*)*”
logman update MyDataCollector -c “Process(_Total)*”
logman update MyDataCollector -c “Processor Information(*)*”
logman update MyDataCollector -c “Processor(_Total)*”
logman update MyDataCollector -c “Processor(0)*”
logman update MyDataCollector -si 00:00:05
logman start MyDataCollector
timeout /t 30
logman stop MyDataCollector
logman delete MyDataCollector
Once the application finished, I checked the CSV file generated and found useful information saved in this file, such as network activity, process activity, and resource usage. In this case, we have generated the file C:CountersMyDataCollector_000001.csv
Step 2: Import Data into Power BI
Once the data is collected and saved in a CSV file, you can import it into Power BI for analysis.
Open Power BI Desktop.
Get Data:
Click on “Get Data” and select “Text/CSV”.
Browse to C:CountersMyDataCollector_000001.csv and import the file.
Transform Data:
Power BI will load a preview of the data. Click on “Transform Data” to clean and format the data if necessary.
You might want to rename columns, change data types, or filter out unnecessary data.
Create Visualizations:
Once the data is loaded, you can start creating visualizations. Use charts, graphs, and tables to analyze the performance data.
For example, you can create line charts to visualize memory usage over time, bar charts for network traffic, and pie charts for process usage.
Disclaimer
The use of this application and the provided scripts is intended for educational and informational purposes only. The scripts and methods demonstrated in this guide are provided “as is” without any warranties or guarantees. It is the user’s responsibility to ensure the accuracy, reliability, and suitability of these tools for their specific needs.
Microsoft Tech Community – Latest Blogs –Read More
Copilot for Microsoft 365 Integration with Service Now – HLS Copilot Snacks
The ServiceNow plugin for Copilot for Microsoft 365 allows users to easily create and track tickets for IT support within the Copilot app. Users can access the plugin from the Copilot toolbar and submit requests with relevant information, such as screenshots, device details, and error messages. The plugin also enables users to view the status of their tickets, communicate with IT agents, and provide feedback on the resolution. This integration can benefit users by simplifying the process of requesting and receiving IT support and can benefit IT support by reducing the need for manual data collection and improving customer satisfaction.
In this Copilot Snack I demonstrate the use of the Copilot/ServiceNow integration from within Microsoft Teams, Microsoft Word, and Microsoft PowerPoint.
*Special thanks to Microsoft’s Maria Kurian for enabling the integration that made this demo possible!
To see all HLS Copilot Snacks video click here.
Resources:
Connect Copilot for Service to ServiceNow – Copilot for Service | Microsoft Learn
Combining GenAI Capabilities with Microsoft – ServiceNow Press
Plugins for Microsoft 365 Copilot (Inside Microsoft Teams) – Microsoft Adoption
Prompts:
Why can’t I get my weather report? Are there any tickets in ServiceNow related to weather?
List the last 5 tickets in ServiceNow and provide a brief description of each
last 7 tickets in ServiceNow and describes each on a slide
To see all HLS Copilot Snacks video click here.
Thanks for visiting – Michael Gannotti LinkedIn
Microsoft Tech Community – Latest Blogs –Read More
Help on using Excel to show feedback for an individual
Hello! I don’t know if this is possible in excel and I am fairly new to using Excel. If anyone has any advice on how to accomplish this
What I want is to create a table that changes based on a dropdown menu. The dropdown would include names of employees in training, and I want my table to show assignments and results/feedback on how they did on those assignments. The dropdown can be changed to a specific reps name, and then I want the “feedback” column to update with feedback for that specific employee that I have on a different sheet containing all the feedback/data. It seemed like I would need to use the IF and VLookup function but I can’t seem to make that work since the IF function can only show two results and I have 6 people in my class.
Thank You!
Hello! I don’t know if this is possible in excel and I am fairly new to using Excel. If anyone has any advice on how to accomplish thisWhat I want is to create a table that changes based on a dropdown menu. The dropdown would include names of employees in training, and I want my table to show assignments and results/feedback on how they did on those assignments. The dropdown can be changed to a specific reps name, and then I want the “feedback” column to update with feedback for that specific employee that I have on a different sheet containing all the feedback/data. It seemed like I would need to use the IF and VLookup function but I can’t seem to make that work since the IF function can only show two results and I have 6 people in my class. Thank You! Read More
Excel formula help please
I need information on how to extract the exact state from the middle of the address using a formula in a separate column.
I need information on how to extract the exact state from the middle of the address using a formula in a separate column. Read More
Segmentation For Risky User/Risky Sign In Policy
I started for a company that runs primarily on an Azure and Microsoft Defender environment. They get tons and tons of alerts for Risky User activity. Recently I looked at their Risky Users policy and found that it was set to Who All Users, Severity All Low, High, and Critical alerts, Mitigation Block/Lockout. So basically, the company janitor with extremely limited access along with the CEO are all dumped into the same bucket. For this reason they get tons of these alerts with the users triggering the alerts getting locked out. The Risky User alerts/blocks is literally crippling their productivity. Is the best practice for this not to have users segmented and then assign different levels of the Risky User policy to them? How does one go about methodically and systematically setting up this segmentation? The company is the type that is made up of multiple smaller companies added from acquisitions. Read More