Skip to main content

Create a Policy with the API

This topic walks you through using the Lacework API and Postman to create a custom LQL-based policy that checks for unrestricted ingress to TCP port 445.

If you are new to the Lacework API, see Get Started.

Lacework Academy Course Available

If you want to learn more about Custom Policies and LQL, take the Fine Tuning & Customization module (part of Technical Foundations: Deploy) from the Lacework Academy.

Policy Query Definition

What Datasources Are Available

The easiest way to learn about Lacework Query Language (LQL) datasources is to discover the names of the datasources and then get details about the one you are interested in.

To list all datasources that you can write a query against, use this endpoint:

GET https://AccountName.lacework.net/api/v2/Datasources

What Fields Can I Use from a Datasource

The examples use the following datasources:

  • AWS datasource: LW_CFG_AWS_EC2_SECURITY_GROUPS
  • Google Cloud datasource (Google Cloud datasources are currently in beta): LW_CFG_GCP_COMPUTE_FIREWALL
  • Azure datasource (Azure datasources are currently in beta): LW_CFG_AZURE_NETWORK_NETWORKSECURITYGROUPS

Use the GET https://AccountName.lacework.net/api/v2/Datasources/{datasource} endpoint to examine the specified datasource's fields:

AWS example
GET https://AccountName.lacework.net/api/v2/Datasources/LW_CFG_AWS_EC2_SECURITY_GROUPS
Google Cloud example (currently in beta)
GET https://AccountName.lacework.net/api/v2/Datasources/LW_CFG_GCP_COMPUTE_FIREWALL
Azure example (currently in beta)
GET https://AccountName.lacework.net/api/v2/Datasources/LW_CFG_AZURE_NETWORK_NETWORKSECURITYGROUPS

Explore Datasources Using LQL

The POST https://AccountName.lacework.net/api/v2/Queries/execute endpoint executes a query on demand. On-demand execution differs from execution by ID in that the query you want to execute does not have to already exist in your Lacework instance. On-demand execution is useful for exploring datasources.

This example explores the LW_CFG_AWS_EC2_SECURITY_GROUPS datasource. Replace the datasource with LW_CFG_GCP_COMPUTE_FIREWALL or LW_CFG_AZURE_NETWORK_NETWORKSECURITYGROUPS respectively if using Google Cloud or Azure.

Example Query

The following is example queryText, which you will use with the endpoint:

Example query
{
source {
LW_CFG_AWS_EC2_SECURITY_GROUPS
}
return {
RESOURCE_CONFIG
}
}

Format the Query

To use the query with the endpoint, you must remove all line breaks.

Formatted for endpoint use
"queryText": "{source {LW_CFG_AWS_EC2_SECURITY_GROUPS} return {RESOURCE_CONFIG}}"

Execute the Query

To execute the query, use this endpoint:

POST https://AccountName.lacework.net/api/v2/Queries/execute

In the body input parameter, pass in the following:

  • queryText
  • LQL query arguments (StartTimeRange and EndTimeRange)

The request body would be similar to the following:

Example request body
{
"query": {
"queryText": "{source {LW_CFG_AWS_EC2_SECURITY_GROUPS} return {RESOURCE_CONFIG}}"
},
"arguments": [
{"name": "StartTimeRange", "value": "2022-07-20T00:00:00.000Z"},
{"name": "EndTimeRange", "value": "2022-07-21T00:00:00.000Z"}
]
}
Response
{
"RESOURCE_CONFIG": {
"Description": "default VPC security group",
"GroupId": "sg-000",
"GroupName": "default",
"IpPermissions": [
{
"IpProtocol": "-1",
"IpRanges": [],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": [
{
"GroupId": "sg-000",
"UserId": "111"
}
]
}
],
"IpPermissionsEgress": [
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": []
}
],
"OwnerId": "111",
"VpcId": "vpc-000"
}
}

Create a Query

This query checks security groups for unrestricted ingress to TCP port 445.

Example Query

Use the example queryText that corresponds to your cloud provider.

AWS query
{
source {
LW_CFG_AWS_EC2_SECURITY_GROUPS a,
array_to_rows(a.RESOURCE_CONFIG:IpPermissions) as (ip_permissions),
array_to_rows(ip_permissions:IpRanges) as (ip_ranges)
}
filter {
ip_permissions:IpProtocol = 'tcp'
and ip_permissions:FromPort = 445
and ip_permissions:ToPort = 445
and ip_ranges:CidrIp = '0.0.0.0/0'
}
return distinct {
ACCOUNT_ALIAS,
ACCOUNT_ID,
ARN as RESOURCE_KEY,
RESOURCE_REGION,
RESOURCE_TYPE,
SERVICE
}
}
Google Cloud query (currently in beta)
{
source {
LW_CFG_GCP_COMPUTE_FIREWALL firewall,
array_to_rows(firewall.RESOURCE_CONFIG:allowed) as (allowed),
array_to_rows(allowed:ports) as (ports),
array_to_rows(firewall.RESOURCE_CONFIG:sourceRanges) as (ranges)
}
filter {
RESOURCE_CONFIG:direction = 'INGRESS'
and allowed:IPProtocol = 'tcp'
and ports = '445'
and ranges = '0.0.0.0/0'
}
return distinct {
ORGANIZATION_ID,
PROJECT_NUMBER,
PROJECT_ID,
FOLDER_IDS,
URN as RESOURCE_KEY,
RESOURCE_REGION,
RESOURCE_TYPE,
SERVICE
}
}
Azure query (currently in beta)
{
source {
LW_CFG_AZURE_NETWORK_NETWORKSECURITYGROUPS a,
array_to_rows(a.RESOURCE_CONFIG:securityRules) as (rules)
}
filter {
rules:"properties".access = 'Allow'
and rules:"properties".direction = 'Inbound'
and rules:"properties".protocol = 'Tcp'
and rules:"properties".destinationPortRange = '445'
and rules:"properties".sourceAddressPrefix = '*'
}
return distinct {
TENANT_ID,
TENANT_NAME,
SUBSCRIPTION_ID,
SUBSCRIPTION_NAME,
URN as RESOURCE_KEY,
RESOURCE_REGION,
RESOURCE_TYPE
}
}

Format the Query

To use the query with the endpoint, you must remove all line breaks. Use the example that corresponds to your cloud provider.

Add this custom queryId for the example: LW_Custom_UnrestrictedIngressToTCP445.

AWS query formatted for endpoint use
{
"queryText": "{source {LW_CFG_AWS_EC2_SECURITY_GROUPS a, array_to_rows(a.RESOURCE_CONFIG:IpPermissions) as (ip_permissions), array_to_rows(ip_permissions:IpRanges) as (ip_ranges)} filter {ip_permissions:IpProtocol = 'tcp' and ip_permissions:FromPort = 445 and ip_permissions:ToPort = 445 and ip_ranges:CidrIp = '0.0.0.0/0'} return distinct {ACCOUNT_ALIAS, ACCOUNT_ID, ARN as RESOURCE_KEY, RESOURCE_REGION, RESOURCE_TYPE, SERVICE}}",
"queryId": "LW_Custom_UnrestrictedIngressToTCP445"
}
Google Cloud query (currently in beta) formatted for endpoint use
{
"queryText": "{source {LW_CFG_GCP_COMPUTE_FIREWALL firewall, array_to_rows(firewall.RESOURCE_CONFIG:allowed) as (allowed), array_to_rows(allowed:ports) as (ports), array_to_rows(firewall.RESOURCE_CONFIG:sourceRanges) as (ranges)} filter {RESOURCE_CONFIG:direction = 'INGRESS' and allowed:IPProtocol = 'tcp' and ports = '445' and ranges = '0.0.0.0/0'} return distinct {ORGANIZATION_ID, PROJECT_NUMBER, PROJECT_ID, FOLDER_IDS, URN as RESOURCE_KEY, RESOURCE_REGION, RESOURCE_TYPE, SERVICE}}",
"queryId": "LW_Custom_UnrestrictedIngressToTCP445"
}
Azure query (currently in beta) formatted for endpoint use
{
"queryText": "{source {LW_CFG_AZURE_NETWORK_NETWORKSECURITYGROUPS a, array_to_rows(a.RESOURCE_CONFIG:securityRules) as (rules)} filter {rules:"properties".access = 'Allow' and rules:"properties".direction = 'Inbound' and rules:"properties".protocol = 'Tcp' and rules:"properties".destinationPortRange = '445' and rules:"properties".sourceAddressPrefix = '*'} return distinct {TENANT_ID, TENANT_NAME, SUBSCRIPTION_ID, SUBSCRIPTION_NAME, URN as RESOURCE_KEY, RESOURCE_REGION, RESOURCE_TYPE}}",
"queryId": "LW_Custom_UnrestrictedIngressToTCP445"
}

Use your query with the POST https://AccountName.lacework.net/api/v2/Queries endpoint as discussed in POST Queries.

Create a Policy

Create a policy that uses your new query. Use the example that corresponds to your cloud provider.

AWS policy
{
"title": "Security Groups Should Not Allow Unrestricted Ingress to TCP Port 445",
"enabled": true,
"policyType": "Violation",
"alertEnabled": true,
"alertProfile": "LW_CFG_AWS_DEFAULT_PROFILE.CFG_AWS_Violation",
"evalFrequency": "Daily",
"queryId": "LW_Custom_UnrestrictedIngressToTCP445",
"severity": "high",
"description": "Security groups should not allow unrestricted ingress to TCP port 445",
"remediation": "Policy remediation"
}
Google Cloud policy (currently in beta)
{
"title": "Security Groups Should Not Allow Unrestricted Ingress to TCP Port 445",
"enabled": true,
"policyType": "Violation",
"alertEnabled": true,
"alertProfile": "LW_CFG_GCP_DEFAULT_PROFILE.Violation",
"evalFrequency": "Daily",
"queryId": "LW_Custom_UnrestrictedIngressToTCP445",
"severity": "high",
"description": "Security groups should not allow unrestricted ingress to TCP port 445",
"remediation": "Policy remediation"
}
Azure policy (currently in beta)
{
"title": "Network Security Groups Should Not Allow Unrestricted Ingress to TCP Port 445",
"enabled": true,
"policyType": "Violation",
"alertEnabled": true,
"alertProfile": "LW_CFG_AZURE_DEFAULT_PROFILE.Violation",
"evalFrequency": "Daily",
"queryId": "LW_Custom_UnrestrictedIngressToTCP445",
"severity": "high",
"description": "Network security groups should not allow unrestricted ingress to TCP port 445",
"remediation": "Policy remediation"
}

Use your policy with the POST https://AccountName.lacework.net/api/v2/Policies endpoint as discussed in POST Policies.

Postman Configuration

Request a Bearer Token Using POST

Headers

https://AccountName.lacework.net/api/v2/access/tokens

tokens_headers.png

  1. Replace with your Lacework account name.
  2. Replace with the secret from API JSON.
  3. If the account is an org, set this if applying to the tenant. Deselect if not an org.

Body

{
"keyId": "AccessKeyID",
"expiryTime": 3600
}

tokens_body.png

Replace with the access key from the API JSON.

Set a Token Variable

Optionally, you can use Postman's scripting capabilities to update the authentication token variable automatically after generating a bearer token. Your script should retrieve the JSON response body and parse out the required JSON object value and pass it to the collection variable.

If you do not configure Postman to automatically update the authentication token variable, you can update the token manually for each endpoint.

GET Datasources

To list all AWS datasources, use this endpoint:

https://AccountName.lacework.net/api/v2/Datasources

This example uses the LW_CFG_AWS_EC2_SECURITY_GROUPS datasource. To examine its details only, use this endpoint:

https://AccountName.lacework.net/api/v2/Datasources/LW_CFG_AWS_EC2_SECURITY_GROUPS

Authorization

datasources_authorization.png

  1. Replace with your Lacework account name.
  2. Select Bearer Token.
  3. Replace with the token returned from the request POST.

Headers

datasources_headers.png

  1. Replace with your Lacework account name.
  2. Replace with the secret from API JSON.
  3. If the account is an org, set this if applying to the tenant. Deselect if not an org.

Endpoints

datasources_body.png

datasources_body_id.png

POST Queries

To add a query to your Lacework instance, use this endpoint.

https://AccountName.lacework.net/api/v2/Queries

Authorization

queries_authorization.png

  1. Replace with your Lacework account name.
  2. Select Bearer Token.
  3. Replace with the token returned from the request POST.

Headers

queries_headers.png

  1. Replace with your Lacework account name.
  2. Replace with the secret from API JSON.
  3. If the account is an org, set this if applying to the tenant. Deselect if not an org.

Body

queries_body.png

Paste your query into the request body.

POST Policies

To add a policy to your Lacework instance, use this endpoint.

https://AccountName.lacework.net/api/v2/Policies

Authorization

policies_authorization.png

  1. Replace with your Lacework account name.
  2. Select Bearer Token.
  3. Replace with the token returned from the request POST.

Headers

policies_headers.png

  1. Replace with your Lacework account name.
  2. Replace with the secret from API JSON.
  3. If the account is an org, set this if applying to the tenant. Deselect if not an org.

Body

policies_body.png

Paste your policy into the request body.