Update (November 3): The App governance add-on is out of preview and generally available.
In mid-July, Microsoft introduced the preview of an app governance add-on for Microsoft Defender for Cloud Apps (MCAS), describing the new capability as a “security and policy management capability designed for OAuth-enabled apps that access Microsoft 365 data through Microsoft Graph APIs.”
There’s no doubt that tenants can accumulate a collection of Graph-enabled apps over time. The apps come from Microsoft, ISVs, and line of business apps. Indeed, any PowerShell script you write to interact with the Graph APIs gains its permissions through consent granted to an app registered with Azure AD. The net result is that you can end up with hundreds of registered apps, all with Graph permissions, some of which you might not know much about. App governance aims to deliver a structured management framework for those apps, leveraging information taken from Azure AD and MCAS.
Microsoft research clearly shows that attackers use illicit consent grants for Graph-based apps to extract and abuse data. Given the likelihood that organizations will have more Graph-based apps to manage over time, it’s important that administrators understand app usage in their tenant. Unfortunately, the need to review and analyze app usage often falls down task lists, which is the hole the app governance add-on attempts to close.
The Need for MCAS
MCAS isn’t included in any Office 365 plan. Office 365 E5 includes Office 365 Cloud App Security (OCAS), a cut-down version of the full-blown MCAS. Both operate on the same basis of data gathered from user and app activity, but MCAS delivers more functionality and covers more apps. For this pleasure, tenants need to pay more to license MCAS, unless they’ve already invested in Microsoft 365 E5, Enterprise Mobility and Security E5, or one of the other licenses which cover MCAS. You need MCAS to use the new add-on, which doesn’t work with OCAS.
Fortunately, Microsoft offers organizations the chance to run a 30-day trial for MCAS by signing up through the Purchase services section of the Microsoft 365 admin center. After starting the MCAS trial and assigning some licenses to accounts with suitable administrator roles, you can go ahead and start a trial of the add-on. Curiously, the add-on allows a 130-day trial, which might be due to its desire to capture and analyze usage data for apps over a reasonable period. Of course, if you sign up for both trials, MCAS expires after 30 days, and you won’t be able to use the add-on afterwards.
Using App Governance
App governance runs within the Microsoft 365 admin center. If your account isn’t licensed or doesn’t hold one of the necessary compliance roles, you’ll be told this unhappy news if you attempt to access the page. Licensed administrators see a preview of the app situation in the tenant (Figure 1).
Figure 1: App Governance overview
I had recently been through an audit of apps based on grabbing app data from Azure AD and reviewing the data through Microsoft Lists, so there are fewer apps present in my tenant than existed previously. As I reviewed the data set, I found a couple of additional apps that I could disable or remove. You can disable an app by viewing its properties through App governance; to remove it, you need to use the Azure AD admin center. Disabling is a good first step to removing a potentially problematic app as you can easily enable the app if someone reports that a business case exists for its use.
In my tenant, app governance detected 33 high privileged apps and 13 overprivileged. Microsoft’s definitions for these categories are:
High privilege: Consent has been granted to the app for Graph permissions that allow the app to access data or change key settings in the organization.
Overprivileged: Consent has been granted to the app for Graph permissions the app doesn’t use.
To examine details of an app to understand why it falls into a certain category, click Apps, and peruse the list of apps to select and view the app properties (Figure 2).
Figure 2: Browsing the set of Graph-enabled apps
As you can see, the portal includes several filters to limit the set of displayed apps. The set of available filters misses one to show disabled apps. This means that if you need to find a disabled app, perhaps to reenable it if the app had been disabled in error, you either need to know the name of the disabled app or do a lot of checking to find the right app.
Probing Permissions
Mmany apps fall into the high privilege category because they read user information. For example, the app used by Microsoft Ignite conference attendees to register has permission to see the user’s email and profile. Apps created by ISVs to read and report tenant data need access to the directory, and that is flagged as a high privilege permission because attacker apps also use the permission to find targets. Even Microsoft’s own Information Barriers app is flagged as high privilege because it has the Directory.Rewrite.All and Groups.Rewrite.All permissions. As always, understanding the context of what an app does is necessary to understand why it needs permissions.
App governance allows tenant administrators to automate checks by creating policies to monitor the creation of overprivileged or high privilege apps. This functionality works like the other alert policies available in the Microsoft 365 compliance center with the exception that the input data focuses on apps rather than actions. As you can see in Figure 1, policies quickly flag new apps which violate criteria. But as pointed out above, you then need to check the app to figure out if a problem really exists.
Permission Glitches
The add-on is a preview, so glitches are expected. For example, app governance flagged an app written to support adding organizational contacts to new user mailboxes as overprivileged. When I examined details of the app (Figure 3), the unused permission is Contacts.ReadWrite. This is odd because that’s the exact permission needed to write a new contact record into a mailbox.
Figure 3: Details of an app marked as overprivileged
Apart from app details and permissions, App Governance promises to show data about usage and users. Taking users first, I thought this information to be quite useless. The information shown on Figure 4 tells me that 237 consented users exist (Azure AD accounts with data the consents granted to the app covers). This figure includes both tenant and guest accounts and results because an administrator granted consent to the app for the entire organization (if consent is given for individual accounts, they are listed here). The five priority users are those marked as priority accounts. None of the priority accounts (including my own) had any trace of data uploaded or downloaded using the app. Given the app is Microsoft’s Graph Explorer, which I use to test Graph API queries almost daily, this was surprising.
Figure 4: User data reported for an app
After being disappointed with the data available for users, I didn’t hold out much hope for the Usage (beta) tab. And my expectations were met as precisely nothing showed up here. Instead, App governance informed me that no data was present. Oh well, it’s a preview.
DIY App Governance
As mentioned above, it is relatively simple to perform a DIY audit of Microsoft 365 Graph-enabled apps. Home-grown knowledge of apps used in a tenant is an advantage MCAS can’t deliver, but to exploit that knowledge, some work is necessary to acquire, refine, and understand the app inventory – and to keep on checking on a systematic basis.
App governance extends simple auditing by including policy-based management, categorizing apps based on the permissions they hold, and delivering some insights into app usage. Although still just a preview with all that implies, if your organization has MCAS, the add-on is a useful enhancement. If not, although the need to monitor the granting and usage of permissions in Graph-enabled apps is a real need, you might be able to construct your own method to achieve the goal.
Stay updated with developments across the Microsoft 365 ecosystem by subscribing to the Office 365 for IT Pros eBook. We do the research to make sure that our readers understand the technology.
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
2 Replies to “Microsoft Launches Preview of App Governance for Cloud App Security”