Jul 9, 2023
Hugo
David
Today, in How to Automate, we will learn how a Google admin can fully automate one critical part of their daily job: monitoring access to the organization's resources to delete unauthorized permissions on Google Drive.
Accessing, viewing, and editing resources from anywhere is incredibly helpful for organizations, that is for sure. Employees can work from anywhere, documents can be easily shared within the organization, and everyone can work together. Besides drastically facilitating work and collaboration, cloud-based collaborative workspaces such as Google Workspace or Microsoft 365 enable direct external access to the organization's sometimes sensitive resources. An employee can have access to a document and share it with someone outside the organization.
Of course, it is usually very welcomed at work. Sharing a business case, templates, forms, or other resources is way easier than downloading the document and sharing it via email. However, it also means that some internal documents could go public.
An organization could withdraw the ability to share externally once and for all, but does it solve the issue? The employee could always download the document and share it. You would only force the employee to follow a less traceable path. Also, you would impact the balance between security and productivity, which is a balance that every security or IT folk receives admonition about!
So, for lack of a better answer, admins have to monitor Drive's logs to try and find ones that could relate to unauthorized external shares. Sometimes, they even create custom rules to be alerted when a share could indicate a data loss. As the organization grows, this task devours analysts' time with many logs to analyze, which is growing exponentially.
What's more, the remediation phase is tricky on Google Drive, as even Admins cannot access the entirety of files stored on Drive. To ensure a proper remediation capability, admins would have to be owners of every Drive document, notify owners of the external share and prey for them to answer quickly, or find a way to impersonate the owner. This mess is dramatically impeding your ability to remediate ongoing incidents.
This is where automation steps in. Through Mindflow, we will create a flow that automatically alerts the IT or Security team about an external share with first-hand details. We will also create an automated remediation capability that allows the incident assignee to delete the permission with one click.
This workflow will orchestrate five services: Google Admin Reports, Google IAM Service Accounts Credentials, Google OAuth, Google Drive, and Slack.
Automate monitoring and delete permissions on Google Drive - First steps
Before starting to build, let's make sure that the following API and credentials are correctly set:
Google Admin Reports
You will have to enable the Audit and reports API on Google and then add the following scope to your domain-wide delegation client:
https://www.googleapis.com/auth/admin.reports.audit.readonly.
Mindflow
Register the Google credentials in the Vault.
First, we must set up an initial Flow to watch the resources we want. To do so, create a Flow and name it "Schedule: Start watching Google Drive activities by filters." Then, choose your emoji and open the Flow.
Start by setting up the Scheduler. Click the calendar icon at the top left of the canvas, next to the Flow's title. Select At regular intervals, then Daily, and then any time frame you feel like. However, bear in mind that it has to be in relation to the expiration time we will set in the API call because the Watch action must be limited in time up to 6 hours.
In this example, we are setting this Flow to be triggered every 6 hours at 5, 11, 17, and 23 and 59 minutes am and pm. Click Save. Your Scheduler is ready!
Look for the operation reports.activities.watch
, or Watchsactivities
in the Google Admin Reports SDK API to create a new step.
Configure it as such:
User key *:
all
Application name * :
drive
Address: In the second part of this tutorial, you will fill in the Address field with the webhook URL from the Flow you will be creating.
Type:
web_hook
Expiration: Click
fx
, click Add a function, and look for Get Time. Set the Granularity * to Milliseconds (ms). Then, apply a new one by looking for Sum. Next to "previous value," add a space and "21600000." Set the Delimiter * to "Space." This will compute a 6-hour expiration time considering the current execution time.
Id: Give a name to the Channel the execution will create, such as
drive_change_user_access
Event name: We are going to look the
change_user_access
events.
Make sure you select the credentials in the SETTINGS panel.
Creating the Flow
This section is divided into two subsections, each representing a milestone. The first is about incident detection and notification to the targeted team. The second describes how you can set up the automated remediation process.
Before starting the dirty work, make sure the following credentials and scopes are adequately set and review the final Flow.
Google IAM
Create a JWT credential in the Vault with the scope https://www.googleapis.com/auth/iam
and configure the credentials, as shown in the picture below. Ensure you create this credential for an HTTP Request, not a Google service.
Slack
Make sure your bot has the scope channel:write
.
Monitor Google Drive and notify on incident
Go back to the Homepage and create your second Flow. Name it "Webhook: File shared to someone outside the organization in GDrive Alert", for instance. Choose your emoji! Then, click the gear icon and copy the second webhook URL from the bottom. Go back to the first Flow and paste it into the Address field.
We will first triage incoming events because the change_user_access
eventName
also contains permissions such as those generated when the file is created. We will triage the exact name of the event in the Google webhook payload. Hop on Drive to create permission on an existing file to generate a log that we will use to configure the Flow.
To do so, create a condition. Name it Action?. Create a first branch, named new permission, leading to another Condition named External Share?. In your Compare input, type "/" to open the Data Picker tool. Select APIs-Google in TRIGGERS and the last execution. Follow the path value/events/0 and Pick name
.
Select the operator "Is equal to" and type "edit" below. Then, create a second branch named else leading to Success. On the condition's branches panel, click the dots on the left of the branch Success to mark it as "Else". This condition will filter out events such as create
that we are not interested in for this Flow.
In External share? Create a first branch named Yes leading to a Transform data named Extracting docTitle. Open the Data Picker tool in the compare panel and navigate to value/events/2/parameters/3. Under the couple name/target_user, pick value. No worries, the value we are interested in will always be on this path.
Select the operator "Does not contain" and, below, type your organization's domain. Wait, that's not all. Click "Add a comparison". Select the operator "And". In the first field, open the Data Picker and navigate to value/events/2/parameters/5/multiValue/0. This is the type of permission given to the destinatory of the new permission. In this example, we are triaging to keep only external shares with edit rights. So, as the operator, select "Is equal to" and then type can_edit
.
Create a second branch leading to the already existing step Success. Mark it and name it as else. Triaging is done!
Now, what we want to do is to automate the extraction of the document's title. To do so, open Extracting docTitle setting panel and click "Add an item". Name this item docTitle
. Open the Data Picker to Pick the field parameters
in value/events/0. Then, click fx and apply a JSON path function. In Query *, type $.[?(@.name=='doc_title')].value
and turn off "Prevent eval *". This will inspect the JSON to extract the value of the object doc_title
. Apply a new function that is Find/Replace and, in Find * type " and leave Replace * empty.
Following Extracting docTitle, create a Slack step by fetching the operation Sends a message to a channel or chat_postMessage. Copy and Paste the desired Channel ID in Channel *. Then, click the processor icon to display all the available fields. Look for "Blocks". Turn the field into JSON and paste the following:
This will create an asynchronous step where the assigned user must either Close Ticketcket or Start the remediation process. We will ingest the user's input when they click either button and create a condition leading to two follow-ups.
To do so, create a condition named Decision?. Create two branches, one to a chat_postMessage step named Close. One to a TD named Prepare impersonation, named Start remediation. Hop on the first branch to configure it. Open the Data Picker to inspect the Slack resume execution. Inspect the payload to find payload/actions/0 and pick style. As the operator, select "Is not equal to" and then type danger.
Repeat the same process for the second branch, but select "Is equal to" this time.
Congrats on the first milestone achieved! Let's hop on the most interesting part of the Flow: the remediation process.
Automatically delete permissions on Google Drive when the incident is confirmed.
In this TD, we will prepare the impersonation process on Google Drive. Why? There is one issue with Drive's API. Although it's noticeable and appreciated that Drive doesn't allow "Super Admins" that can see every file stored in the company's Drive, even personal ones, it leaves a loophole for admins regarding monitoring. Through the API, you will make requests identified as a user, you, to be more specific. This means you won't be able to act on files you don't have access to. But Google also provides a workaround. We will use the IAM Service account credentials and OAuth APIs.
Of course, pay a good deal of carefulness since this workaround must be closely monitored and delimited to specific purposes. Here, we only want to create an impersonation to delete an unauthorized permission.
Let's go back to our TD. Inside, create 5 items that you will name: iat
, sub
, exp
, impersonated_claim_set
, and escape
. Configure them as such:
iat
(issued at): create a Get time function to generate the current Unix time in seconds.sub
(the impersonated user): Pick the email address of the actor in the Google webhook payload.exp
: Again, create a Get time function in seconds and apply a Sum function where you will add 3600 seconds to the previous value, which is the current Unix time. This will set the lifetime duration of the JSON Web Token that we will generate later.impersonated_claim_set
: paste and complete the following JSON:escape
: callimpersonated_claim_set
and apply an Escape string function configured as such: Escape level * Special chars, Escape quote * Double, JSON Compatible enabled.
You are ready to proceed forward! From there, we will have to create HTTP Requests by hand. I know, I know you are worried! But don't worry, it is easy!
Create the first request. Set Method * to POST. In URL * paste https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/[YOUR SERVICE ACCOUNT ADDRESS]:signJwt
. Open the Body section and mark it as JSON. Inside write
In the SETTINGS panel, make sure you have selected your JWT credential. Run it once to generate a JWT. Once done, create another HTTP Request. Select POST and paste https://oauth2.googleapis.com/token in URL *. In Body as URL-encoded, create grant_type
and paste urn:ietf:params:oauth:grant-type:jwt-bearer. Below, create assertion
and Pick signedJwt
from the first HTTP Request logs. Run it once to generate logs. At this point, the impersonation process is done. We will now configure steps to find and delete the unauthorized permission.
To do so, create another HTTP Request. Select GET for Method *, and paste https://www.googleapis.com/drive/v2/files/[Pick the file id in the webhook at value/events/0/parameters/4 ]/permissions. Open Headers and create Authorization
. Write "Bearer" and Pick access_token
from the second HTTP Request. This will retrieve the files' permissions and the last and litigious permission attributed.
On to the final HTTP Request! Set Method * to DELETE. Paste https://www.googleapis.com/drive/v2/files/[file id from the webhook]/permissions/[Pick id
from the last permission shown, that will be the object 0 in items
]. Then, again, create a Authorization
Header with the Bearer token.
The remediation process is done!
All that is left is to create Slack steps to notify that the remediation has been successfully performed. Create a chat_postMessage
and configure it: Channel *: pick Channelnnel from the first Slack step. Display the additional fields and find Thread ts. Find and pick ts
in the first Slack step logs. This will send the message as a reply to avoid flooding Channelnnel. Finally, as text, you can type "Permission has been deleted." or anything else you want.
Of course, don't forget the other branch, Close, which is much shorter! Create the same Slack step but, as text, write something liTicketcket closed. Reason: not an incident."
Et voilà! Congrats, you have automated the task to monitor and delete permissions on Google Drive!