Custom Rules Using Netskope Governance Language

Custom Rules Using Netskope Governance Language

In SaaS Security Posture Management, Netskope Governance Language (NGL) makes it easy to build, check, and deploy sophisticated custom rules. Create custom rules under Policies > Security Posture > SaaS > Rules > New Rule using NGL for the security posture of SaaS app resources.

The following syntax diagram represents the general rule to write a NGL statement. An NGL rule will have the following format:

NGL-Syntax-Diagram.png

For example,

microsoft365 remotedomain should-have autoforwardenabled = false
Salesforce ConnectedApp should-not-have oauthConfig with-attribute { scopes with-any-element [ scope = "Full" ] }
SaaS Security Posture Management‘s Atlassian Jira and Confluence apps does not currently support Netskope Governance Language (NGL).

Grammar

An example of a security rule description in plain English is as follows:

Microsoft 365 should have a remote domain resource-type with attribute auto-forward enabled as false.

As you see, a security rule typically has a set of attributes (Microsoft 365, remote domain, auto-forward), a set of operators (should have, with attribute) and a value (false). As is clear from that breakdown of the rule description, the attributes are specific to the SaaS app under consideration (Microsoft 365 remote domain in the above example). However, the operators are generic and can be applied to any attributes belonging to any SaaS app. Values can either be the same or different between different SaaS applications, or even between different instances of the same SaaS application.

The following table provides examples of using a condition. The formats in this table are applicable to all attributes.

NGLDescription
microsoft365 adminauditlogconfig should-have id existsMicrosoft 365 should have adminauditlogconfig resource-type with id.
microsoft365 remotedomain should-have autoforwardenabled = falseMicrosoft 365 should have a remote domain resource-type with attribute auto-forward enabled as false.
microsoft365 transportrule should-not-have setscl = -1 and len(senderdomainis) > 0Microsoft 365 should not have a transport rule resource-type with attribute set SCL value as -1 and the length of the list attribute sender domain is > 0.
microsoft365 securescore should-have  controlscores with-any-element [    controlname = "pwagepolicynew" and    scoreinpercentage = 100 and    isapplicable = true  ]Passwords are not set to expire.
salesforce securitysettings should-have sessionsettings with-attribute { enableclickjacksetup = true }Enable click-jack protection for setup pages.
github organization should-have two_factor_requirement_enabled = trueMulti-factor authentication (MFA) should be enabled for all organizations in GitHub.

App-Suite

An app-suite refers to the application suite on which you write the rule. It can be a SaaS app. For example,

  • salesforce sessionsettings should-have enablelightninglogin = true

    In the above example, salesforce is the app-suite.

  • microsoft365 sharepointtenant should-have isunmanagedsyncclientfortenantrestricted = true

    In the above example, microsoft365 is the app-suite.

Resource-Type

A resource-type is the type of configuration or resource in the SaaS app. These represent the objects returned by the API and their corresponding schemas. For example,

  • salesforce sessionsettings should-have enablelightninglogin = true

    In the above example, sessionsettings is the resource-type.

  • microsoft365 sharepointtenant should-have isunmanagedsyncclientfortenantrestricted = true

    In the above example, sharepointtenant is the resource-type.

There can be one or more resources of a given resource-type. In an NGL rule, resource-type specifies the type of resources against which the rule should be evaluated. An NGL rule must have a resource-type specified after the app-suite. If required, an NGL rule can refer to more resource-types subsequently be part of the condition section of the rule.

There are few resource- types in certain app-suites, which do not have any metadata on it. For example, DefenderForOffice365, Users, or Groups in Microsoft Entra ID. These are place-holder resource-types, as present in the app-suite under consideration. Such place-holder resources help prevent namespace conflicts as multiple services tend to use similar names for their resources in different ways. When used, this makes NGL explicit and clear on its purpose. For example, in this NGL which makes sure that there is at least one anti-phishing policy configured in Microsoft 365, microsoft365 defenderforoffice365 should-have antiphishpolicy exists. In graphical representation, defenderforoffice365 resource-type is a namespace node which is linked to antiphishpolicy resource-type node with properties. The rule evaluates to true only when there is at least a node for antiphishpolicy linked to the (namespace node) defenderforoffice365. The graphical relationship is as follows:

resource-type-relationship.png

List of DOMs

A user can make use of the resource-type hierarchy information to aid in rule-writing. Detailed information on the hierarchy of the resource-types and how they are linked can be found at:

Expression

An expression refers to whether the condition should be matched or not against the resource types used in the rule. Keywords for this are should-have and should-not-have. For example,

  • salesforce sessionsettingssessionsettings should-have enablelightninglogin = true

    In the above example, should-have is the expression.

  • microsoft365 sharepointtenant should-not-have isunmanagedsyncclientfortenantrestricted = false

    In the above example, should-not-have is the expression.

Condition

A condition is a standard that the rule uses to check against a resource type in an app suite to narrow down the result. It uses a set of operators to achieve it. For example,

  • salesforce sessionsettings should-have enablelightninglogin = true

    In the above example, = is the condition/operator.

  • microsoft365 sharepointtenant should-have isunmanagedsyncclientfortenantrestricted = true

    In the above example, = is the condition/operator.

List of Operators

A list of operators are as follows:

OperatorTypeDescriptionExample
andLogicaland operator performs a logical and operation of the attributes/statements immediately before and after it.attribute1 = value1 and attribute2 = value2
orLogicalor operator performs a logical or operation of the attributes/statements immediately before and after it.attribute1 = value1 or attribute2 = value2
notLogicalnot operator performs a logical not operation of the attributes/statements immediately before and after it.not(attribute1 = value)
+Arithmetic+ operator performs addition of values immediately before and after it.len(list1) + len(list2) > 0
-Arithmetic- operator performs subtraction of values immediately before and after it.len(list1) - len(list2) > 0
*Arithmetic* operator performs multiplication of values immediately before and after it.attribute1 * 2 > 10
/Arithmetic/ operator performs division of values immediately before and after it.attribute1 / 4 > 0
%Arithmetic% operator returns the remainder of the division of value immediately before and after it.attribute1 % 4 = 0
=Relational= operator compares the attribute/statement/value before it with attribute/statement/value after it, and returns a boolean result.attribute1 = attribute2
!=Relational!= operator performs a negative comparison of the attribute/statement/value before it with attribute/statement/value after it, and returns a boolean result.attribute1 != attribute2
>Relational> operator performs a greater than comparison of the attribute/statement/value before it with attribute/statement/value after it, and returns a boolean result.attribute1 > attribute2
>=Relational>= operator performs a greater than or equal comparison of the attribute/statement/value before it with attribute/statement/value after it, and returns a boolean result.attribute1 >= attribute2
<Relational< operator performs a lesser-than comparison of the attribute/statement/value before it with attribute/statement/value after it, and returns a boolean result.attribute1 < attribute2
<=Relational<= operator performs a lesser-than or equal comparison of the attribute/statement/value before it with attribute/statement/value after it, and returns a boolean result.attribute1 <= attribute2
lenFunctionallen is a function which calculates the length of a list attribute or a string attribute, and returns it as an integer value.len(list_attribute1)
ageFunctionalage is a function which calculates the time difference of a time attribute till the current time. It takes two parameters, the time attribute name and unit of time as a string, and returns an integer representing the time difference of that time attribute measured in the units provided to the function. The value of the attribute should be an integer representing an Epoch (Unix) time.age(time_attribute1, “hours”)

age(time_attribute_1hour_earlier, "hours") results in 1

age(time_attribute_1hour_later, "hours") results in -1

textmatchFunctionaltextmatch is a function which evaluates the specified regular expression against a given string attribute. It returns true or false.textmatch(string_attribute, regex_pattern)
with-attributeHierarchicalwith-attribute keyword is used to specify a hierarchical (or parent-child) relationship between its preceding and succeeding attributes, where the parent attribute is a struct and child attribute is a member.attribute1 with-attribute { attribute2 = value2}
with-elementHierarchicalwith-element keyword is used to specify a hierarchical (or parent-child) relationship between its preceding and succeeding attributes, where the parent attribute is a list and child attribute is a member.attribute1 with-element [ attribute2 = value2 ]
with-any-elementHierarchicalwith-any-element keyword is used to specify a condition where any of the parent list attributes’ members matches the condition following it.attribute1 with-any-element [ ip = “0.0.0.0” ]
with-path-toHierarchicalwith-path-to keyword is used to specify a traversal path from the preceding attribute to the succeeding attribute.attribute1 with-path-to [ attribute2 ]
existsHierarchicalexists keyword checks the presence of an attribute.attribute1 exists
not-existsHierarchicalnot-exists keyword checks the absence of an attribute.attribute1 not-exists
any....asUtilityany keyword is used for a resource-type which has a relationship to the resource-type mentioned prior to should-have/should-not-have.

as keyword is used for specifying an alias for the resource-type whose value can be later used in a conditional statement. Aliases are occasionally required when a value is derived in an earlier part of the rule, and referenced in a later part of the rule. In such conditions, the latter part of the rule refers to the derived value using an alias. It is equivalent to storing a value in a variable. It is used along with any which compares all the available resources assigned by the alias to match the condition. If one of the conditions matches, true is returned.

any resource as a with-attribute {a.attribute1 = “value“}

Note

The letter a is an alias here.

###Utility### keyword is used to indicate that subsequent text between two ### is a comment string, and will be ignored by the system.### This is a comment.
()Utility() is used to capture a functions’ input parameters, or to order boolean expressions.func1(arg1), (boolean1 or boolean2) and (boolean3 or boolean4)
[]Utility[] is used to access an element of a list.list_attribute [element1]
{}Utility{} is used to depict a structure.struct_attribute {member_attribute}

Operators supported in NGL follow the precedence order below:

CategoryOperatorAssociativity
Postfix() [] {}Left to right
Unary+ -Not applicable
Multiplicative* / %Left to right
Additive+ -Left to right
Relational< <= > >=Not applicable
Equality= !=Not applicable
Logical ANDandLeft to right
Logical ORorLeft to right

Function

Use functions in rules to identify specific information about resource types. Functions use the following syntax:

<function>(<argument>) For example:

  • microsoft365 transportrule should-not-have len(senderdomainis) > 0
  • github repository should-have age(created_at , "days") > 1
  • azuread oauth2permissiongrant should-not-have textmatch(scope, "AppRoleAssignment.ReadWrite.All") = true

NGL with Multiple Resource Types

Resource types which are linked to each other can be used in NGL to validate a configuration. This helps to assess how secure are the multiple resource types working in unison. Additional information to the resources can be found here: List of DOMs. There are two variations of such NGLs with multiple resource types:

Type 1

When all the linked resources should match a condition. For example, NGL to match all conditionalaccesspolicy linked to conditionalaccess resource with state = “enabled” is written as:

azuread conditionalaccess should-have conditionalaccesspolicy with-attribute { state = "enabled" }.

This NGL will evaluate to true for the ConditionalAccess resource as all the linked ConditionalAccessPolicy are having an attribute state =”enabled”.

Note

To view the ConditionalAccess resource, access the Microsoft Entra ID DOM, then expand IdentityAndSignIn > ConditionalAccess. To view the ConditionalAccessPolicy resource, access the same Microsoft Entra ID DOM, then expand IdentityAndSignIn > ConditionalAccess > ConditionalAccessPolicy

Type-1.png

The truth table for the evaluations results of the rule will be as follows:

cp2 – state = enabledcp2 -state = disabled
cp1 – state = enabledSuccessFail
cp1 – state = disabledFailFail

Type 2a

When any of the linked resources should match a condition.  The links exist due to a hierarchical relationship between the resource types. For example, NGL to match any one conditionalaccesspolicy linked to conditionalaccess resource with state = “enabled” is written as:

azuread conditionalaccess should-have  any conditionalaccesspolicy as c with-attribute { c.state = "enabled" }

This NGL will evaluate to true for the ConditionalAccess resource as one of the linked ConditionalAccessPolicy satisfies the condition.

Note

To view the ConditionalAccess resource, access the Microsoft Entra ID DOM, then expand IdentityAndSignIn > ConditionalAccess. To view the ConditionalAccessPolicy resource, access the same Microsoft Entra ID DOM, then expand IdentityAndSignIn > ConditionalAccess > ConditionalAccessPolicy

Type-2a.png

The truth table for the evaluations results of the rule will be as follows:

cp2 – state = enabledcp2 – state = disabled
cp1 – state = enabledSuccessSuccess
cp1 – state = disabledSuccessFailed

Type 2b

The resources can also be linked using the refers-to relationship. An example from the Salesforce app suite is to get DelegateGroup (access the Salesforce DOM, then expand Metadata > DelegateGroups > DelegateGroup) which is linked to DelegateGroupMember (access the Salesforce DOM, then expand Tooling > DelegateGroupMembers > DelegateGroupMember) which is also linked to User (access the Salesforce DOM, then expand SObjects > Users > User)

The link between DelegateGroup and DelegateGroupMember exists through the DelegateGroupId attribute in DelegateGroupMember which  refers toDelegateGroup. The link between DelegateGroupMember and User exists through the UserOrGroupId attribute in the DelegateGroupMember resource type which refers toUser.

With these three resource types in action, NGL to find DelegateGroup if any one of the linked User has a name “demo user1” is written as:

salesforce DelegateGroup should-have DelegateGroupMember with-attribute {any user as u with-attribute { u.Name = "demo user1" }}

Type-2b.png

The truth table for the evaluations results of the rule will be as follows:

user  – name = demo user1user  – name = demo user2
user  – name = demo user1SuccessSuccess
user  – name = demo user2SuccessFail

Predefined Categories

Netskope provides a list of predefined rules bundled together in a category to check your SaaS environments’ security posture compliance. For a complete list of predefined rules, log in to your Netskope tenant and navigate to Policies > Security Posture, then click the SaaS tab followed by Rules. The Rules table lists the various categories like compliance standard, domain, MITRE ATT&CK, Netskope Best Practices and corresponding predefined rules. You can filter the result based on a specific category.

NGL Best Practices

  • Though NGL is not case-sensitive, lower case is preferred.
  • It is recommended to clone a predefined rule and create a new custom rule along the similar lines.
Share this Doc

Custom Rules Using Netskope Governance Language

Or copy link

In this topic ...