Policy Code Triggers
Introduction
What is a trigger?
In Skyhigh Policy Code, a trigger is an event that initiates an execution of the policy engine. This document will explain the various triggers and some of the nuances of using each trigger.
How do I use triggers in Policy Code?
When defining your policy in a Skyhigh product, you may want to scope certain portions of the policy to only apply to certain triggers. For example, you may want to block certain media types from being uploaded through Skyhigh SWG, but in this case you would want to check the media type only on the HTTP request which would be the Web.Request trigger. This scoping can be done in two ways which are explained below.
Scoping routines for specific triggers
First, you can scope an entire routine to apply only to certain triggers in its declaration statement. Here is an example routine declaration:
ROUTINE My_Routine1 ON ANY {
// This code will execute when any trigger occurs
}
In this example, the keyword ANY indicates that this routine should be executed on all triggers that occur. However, this can be replaced by a comma-separated list of triggers enclosed in parentheses. For example:
ROUTINE My_Routine2 ON (Web.Request, EmbeddedObject) {
// This code will only execute on Web.Request and EmbeddedObject triggers
}
This list can also be empty such that the routine will not execute during any trigger unless it's explicitly called using the CALL command. For example:
ROUTINE My_Routine3 ON () {
// This code will only execute if My_Routine3 is explicitly called using CALL
}
Using triggers in IF statements
Rather than scoping an entire ROUTINE to execute only on a certain subset of triggers, you can use a simple IF statement to cause a block of code to only execute during certain triggers. For example:
IF Trigger == "Web.Response" OR (Trigger == "EmbeddedObject" AND InitialTrigger == "Web.Response") THEN {
IF MediaType.FromHeader.ToString == "application/executable" THEN {
MWG.Block ("Blocked download of executable")
}
}
In this example, the first, outer IF statement is used scope the second, inner IF statement so it is only evaluated on Web.Response triggers or EmbeddedObject triggers that were initiated as part of a Web.Response. This way it will only block executable files in web responses, which includes only downloads.
Web Triggers
Web.Request
The Web.Request trigger, as the name implies, refers to an HTTP request from a web client such as a web browser. Generally, this trigger is where you will apply the following types of controls which typically do not require waiting for a response from the web server and can be applied on the client's request alone:
- Domain or URL blocking
- Category filtering
- Activity control (e.g., uploads, logins, etc.)
- Media type filtering or size limitations on uploads
- Data Loss Prevention
- Tenant restrictions
If the connection is unencrypted, then there should only be a single trigger per HTTP request (although, multiple requests can occur within a single TCP connection). However, there are often multiple Web.Request triggers for a single request if it is an encrypted HTTPS connection. In the following sections we will explain the purpose for each Web.Request trigger the occurs for a single request in an HTTPS connection.
Web.Request - CONNECT command
When the initial connection is made via HTTPS, there is a Web.Request trigger for the CONNECT command. At this point the client has established a TCP connection to the proxy is attempting to connect to a website. Regardless of whether this is an explicit proxy request using the CONNECT command (e.g., CONNECT www.google.com) or a transparent proxy request, the command will always be CONNECT at this point, and the proxy will know the fully-qualified domain name (FQDN) of the URL being requested. In the case of a transparent connection, the FQDN is discerned from the Server Name Indication (SNI) field in the TLS client hello packet. It's important to understand what is not known at this point in the request:
- The full URL is not known including...
- URL path
- URL parameters
- HTTP request headers are not known including cookies
- The HTTP method (e.g., GET, POST, etc.) is not known.
MWG.CommandNamewill return"CONNECT"during this trigger. - The request body has not been sent, and the size of the request is unknown
Web.Request - CERTVERIFY command
If HTTPS inspection is enabled, then this will generate a Web.Request trigger in which MWG.CommandName will return"CERTVERIFY" . At this point, the proxy has connected to the web server and established a TLS connection. The purpose of the CERTVERIFY command is to pass through the policy one time for the purpose of verifying the certificate presented by the web server. At this point, the same things that were unknown in the Web.Request trigger for the CERTVERIFY command are still unknown. The only additional information the proxy has is the details of the web server's certificate.
Web.Request - HTTP command
After the Web.Request trigger for CERTVERIFY is complete, then the initialization of HTTPS inspection is complete, and a normal Web.Request occurs with the full context of the request. At this point, the entire web request from the client is available to the proxy including all of the following:
- Full URL including path and parameters
- Request headers
- HTTP method
- Full request body
Web.Response
The Web.Responsetrigger will handle the response from the web server back to the client. At this point everything from the Web.Request is known and still available, but the web server's response had been added. This gives the following additional context:
- HTTP status code (e.g., 200 OK, 302 Found, 403 Forbidden, etc.)
- Response headers (e.g., Content-Type, Set-Cookie, etc.)
- Full response body
The Web.Response is most commonly used for the following types of filtering:
- Anti-malware scanning
- Media type filtering or size limitations on downloads
- Dynamic content classification
EmbeddedObject
An EmbeddedObjecttrigger may occur during the processing of another trigger. This can happen in multiple ways. Here are a few scenarios that will cause EmbeddedObject triggers:
- When the Composite Opener is enabled, this will extract and evaluate many different file types and may initiate
EmbeddedObjecttriggers for each. For example, if a client downloads an archive such as a zip file, the Composite Opener will extract the files in the archive and cause anEmbeddedObjecttrigger to evaluate each extracted file. - If a web server response is of type
multipart/form-data, then each part will be evaluated by anEmbeddedObjecttrigger - If the HTML Opener is enabled and a web server responds with HTML, then each HTML tag evaluated by the opener will cause an
EmbeddedObjecttrigger
Since EmbeddedObject triggers can occur during both Web.Request and Web.Response triggers, you may need to scope your code to apply to EmbeddedObject triggers that occurred during a particular parent trigger. This can be done using InitialTriggerwhich will always return the parent trigger name. See the following example:
ROUTINE Block_Executable_Downloads ON (Web.Response, EmbeddedObject) {
IF Trigger == "Web.Response" OR (Trigger == "EmbeddedObject" AND InitialTrigger == "Web.Response") THEN {
IF MediaType.FromHeader.ToString == "application/executable" THEN {
MWG.Block ("Blocked download of executable")
}
}
}
Notice that in the ROUTINE declaration, the Web.Response and EmbeddedObject triggers are listed. However, this does not mean that it will not evaluate an EmbeddedObject trigger that occurred as a part of a Web.Response. Therefore, within the routine the IF statement scopes the code to only apply to EmbeddedObject triggers where the InitialTrigger == "Web.Response".
