API Custom Policies
This topic walks you through using the Lacework API and Postman to create a custom 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 Custom Policies/LQL course from the Lacework Academy.
Policy Query Definition
What Datasources Are Available
The easiest way to learn about the 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
- GCP datasource (GCP 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:
GET https://AccountName.lacework.net/api/v2/Datasources/LW_CFG_AWS_EC2_SECURITY_GROUPS
GET https://AccountName.lacework.net/api/v2/Datasources/LW_CFG_GCP_COMPUTE_FIREWALL
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 GCP or Azure.
Example Query
The following is example queryText
, which you will use with the endpoint:
{
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.
"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
andEndTimeRange
)
The request body would be similar to the following:
{
"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"}
]
}
{
"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.
{
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
}
}
{
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
}
}
{
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
.
{
"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"
}
{
"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"
}
{
"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.
{
"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"
}
{
"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"
}
{
"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
- Replace with your Lacework account name.
- Replace with the secret from API JSON.
- If the account is an org, set this if applying to the tenant. Deselect if not an org.
Body
{
"keyId": "AccessKeyID",
"expiryTime": 3600
}
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
- Replace with your Lacework account name.
- Select Bearer Token.
- Replace with the token returned from the request POST.
Headers
- Replace with your Lacework account name.
- Replace with the secret from API JSON.
- If the account is an org, set this if applying to the tenant. Deselect if not an org.
Endpoints
POST Queries
To add a query to your Lacework instance, use this endpoint.
https://AccountName.lacework.net/api/v2/Queries
Authorization
- Replace with your Lacework account name.
- Select Bearer Token.
- Replace with the token returned from the request POST.
Headers
- Replace with your Lacework account name.
- Replace with the secret from API JSON.
- If the account is an org, set this if applying to the tenant. Deselect if not an org.
Body
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
- Replace with your Lacework account name.
- Select Bearer Token.
- Replace with the token returned from the request POST.
Headers
- Replace with your Lacework account name.
- Replace with the secret from API JSON.
- If the account is an org, set this if applying to the tenant. Deselect if not an org.
Body
Paste your policy into the request body.