Getting Started with DSQL
Welcome to DSQL, a powerful query language designed specifically for DNS operations, security monitoring, and automation. This tutorial will guide you through the basics and advanced features.
Installation
CLI Installation
# Install DSQL CLI
pip install dnsscience-dsql
# Configure database connection
export DATABASE_URL="postgresql://user:pass@localhost/dnsscience"
# Verify installation
dsql version
API Access
curl -X POST https://dnsscience.io/api/dsl/execute \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "FIND domains WHERE spf.status = \"missing\""}'
Your First Query
Let's start with a simple query to find all domains in your portfolio:
FIND domains
Note: Results are limited to 10,000 rows by default for safety.
Basic Queries
Find Domains
FIND domains LIMIT 10
Show Subdomains
SHOW subdomains OF example.com
Check Domain Configuration
CHECK example.com FOR
ssl.expires_in < 30.days OR
spf.status = "missing"
Count Domains
COUNT domains WHERE spf.valid = true
Filtering and Conditions
Basic Filtering
FIND domains WHERE spf.status = "missing"
Multiple Conditions
FIND domains WHERE
spf.status = "missing" AND
dmarc.policy != "reject"
Comparison Operators
-- Less than
FIND domains WHERE ssl.expires_in < 30.days
-- Greater than or equal to
FIND domains WHERE ssl.expires_in >= 60.days
Pattern Matching
-- Contains pattern
FIND domains WHERE name LIKE "%example%"
-- Starts with
FIND domains WHERE name STARTS WITH "www"
-- Regular expression
FIND domains WHERE name MATCHES "^[a-z]+\.com$"
Monitoring and Alerts
MONITOR example.com EVERY 1.hour {
ALERT ON ssl.expires_in < 30.days {
severity: "high"
notify: ["ops@example.com"]
}
}
Automation with FOR EACH
FOR EACH domain IN FIND domains WHERE ssl.expires_in < 30.days {
SEND email TO domain.owner WITH {
template: "cert_renewal_reminder",
domain: domain.name,
expires_in: domain.ssl.expires_in
}
}
Security Policies
POLICY email_security_basic {
REQUIRE spf.record EXISTS
REQUIRE dmarc.policy IN ["quarantine", "reject"]
REQUIRE dkim.enabled = true
ON VIOLATION {
severity: "high"
remediation: "Configure SPF, DMARC, and DKIM"
}
}
APPLY POLICY email_security_basic TO portfolio
Interactive Query Editor
Try DSQL in your browser:
Best Practices
- Always Use LIMIT - Add LIMIT to queries that might return many rows
- Use Indexes - Filter on indexed columns for better performance
- Test First - Test queries manually before using in automation
- Be Specific - Use specific conditions to avoid false positives
- Comment Your Code - Document complex queries
DSQL Language Reference
Core Data Types
| Type | Description | Example |
|---|---|---|
string |
Text values | "example.com" |
number |
Integer or decimal | 30, 7.5 |
boolean |
True/false values | true, false |
duration |
Time intervals | 30.days, 1.hour |
Domain Object Properties
Basic Properties
domain.name- Domain name stringdomain.tld- Top-level domaindomain.sld- Second-level domaindomain.created_at- First discovered datedomain.last_checked- Last scan timestamp
Email Security
spf.status- "valid", "invalid", "missing"spf.valid- Validation status (boolean)dmarc.policy- "none", "quarantine", "reject"dmarc.pct- Percentage (0-100)dkim.enabled- DKIM enabled (boolean)
SSL/TLS
ssl.valid- Valid certificate (boolean)ssl.issuer- Certificate issuerssl.expires_in- Days until expiryssl.not_after- Expiry datessl.fingerprint- SHA256 fingerprint
DNSSEC
dnssec.enabled- DNSSEC enabled (boolean)dnssec.valid- DNSSEC valid (boolean)dnssec.status- "valid", "invalid", "missing"
Statements
FIND Statement
FIND domains WHERE condition [LIMIT n] [OFFSET n]
SHOW Statement
SHOW subdomains OF example.com WHERE condition
CHECK Statement
CHECK example.com FOR conditions
COUNT Statement
COUNT domains WHERE condition [GROUP BY attribute]
LIST Statement
LIST name, ssl.expires_in FROM domains WHERE condition
Operators
| Operator | Description | Example |
|---|---|---|
= |
Equal to | spf.status = "valid" |
!= |
Not equal to | dmarc.policy != "reject" |
< |
Less than | ssl.expires_in < 30.days |
>= |
Greater than or equal | risk_score >= 50 |
AND |
Logical AND | A AND B |
OR |
Logical OR | A OR B |
IN |
Value in list | tld IN ["com", "org"] |
LIKE |
Pattern match | name LIKE "%example%" |
IS NULL |
Value is null | spf.record IS NULL |
Built-in Functions
Aggregation Functions
count(items)- Count itemssum(values)- Sum of valuesavg(values)- Average of valuesmin(values)- Minimum valuemax(values)- Maximum value
String Functions
upper(str)- Convert to uppercaselower(str)- Convert to lowercasetrim(str)- Remove whitespaceconcat(str1, str2)- Concatenate strings
Date/Time Functions
now()- Current date/timetoday()- Current date at midnightdays_between(date1, date2)- Days between dates
Real-World DSQL Examples
Email Security Audits
Find Domains Without SPF
FIND domains WHERE spf.record IS NULL
ORDER BY last_checked DESC
LIMIT 100
Comprehensive Email Security Audit
LIST
name,
spf.status,
dmarc.policy,
dkim.enabled,
mx.provider
FROM domains
WHERE
spf.status != "valid" OR
dmarc.policy NOT IN ["quarantine", "reject"] OR
dkim.enabled = false
ORDER BY name
SSL Certificate Management
Certificates Expiring This Month
LIST
name,
ssl.issuer,
ssl.expires_in,
ssl.not_after
FROM domains
WHERE
ssl.expires_in <= 30.days AND
ssl.expires_in > 0
ORDER BY ssl.expires_in ASC
Self-Signed Certificates
FIND domains WHERE
ssl.issuer = "self-signed" OR
ssl.subject_cn = ssl.issuer_cn
Security Monitoring
Monitor Production Domains
MONITOR portfolio WHERE tags CONTAINS "production" EVERY 1.hour {
-- Critical: SSL expiring soon
ALERT ON ssl.expires_in < 7.days {
severity: "critical"
notify: ["ops@example.com", "pagerduty://oncall"]
message: "CRITICAL: SSL for ${domain.name} expires in ${ssl.expires_in} days"
}
-- High: DNSSEC issues
ALERT ON dnssec.valid = false {
severity: "high"
notify: ["dns-team@example.com"]
message: "DNSSEC validation failed for ${domain.name}"
}
-- Warning: MX record changes
ALERT ON mx.changed {
severity: "warning"
notify: ["security@example.com"]
message: "MX records changed for ${domain.name}"
}
}
Automated Remediation
Auto-Renew Certificate Reminders
FOR EACH domain IN FIND domains WHERE
ssl.expires_in < 30.days AND
ssl.expires_in > 0 {
-- Email domain owner
SEND email TO domain.owner WITH {
template: "cert_renewal_reminder",
domain: domain.name,
expires_in: domain.ssl.expires_in,
expires_on: domain.ssl.not_after
}
-- Create ticket
CREATE ticket IN "SSL Renewals" WITH {
title: "Renew SSL for ${domain.name}",
priority: domain.ssl.expires_in < 7.days ? "critical" : "high",
assignee: domain.owner,
labels: ["ssl", "security", "renewal"]
}
-- Tag domain
UPDATE domain SET tags = ADD("ssl-expiring")
}
Compliance Reporting
SOC 2 Security Controls Report
REPORT soc2_security_controls {
TITLE "SOC 2 Security Controls - Q${quarter} ${year}"
SECTION "SSL/TLS Encryption" {
METRIC "Domains with Valid SSL" {
value: COUNT domains WHERE ssl.valid = true
}
TABLE {
title: "SSL Issues"
data: LIST name, ssl.issuer, ssl.expires_in
FROM domains
WHERE ssl.valid = false OR ssl.expires_in < 30.days
}
}
SECTION "Email Security" {
METRIC "DMARC Reject Policy" {
value: COUNT domains WHERE dmarc.policy = "reject"
}
TABLE {
title: "Email Security Gaps"
data: LIST name, spf.status, dmarc.policy
FROM domains
WHERE spf.status != "valid" OR dmarc.policy != "reject"
}
}
EXPORT TO pdf, email("compliance@example.com")
}
Threat Detection
High-Risk Domain Report
LIST
name,
risk_score,
threat_indicators,
last_checked
FROM domains
WHERE risk_score > 75
ORDER BY risk_score DESC
LIMIT 100
Domains on Threat Intelligence Feeds
FIND domains WHERE
threat_intel.blocklisted = true OR
threat_intel.malware_detected = true OR
threat_intel.phishing_detected = true
DSQL Quick Reference Card
Core Statements
FIND domains [WHERE condition] [LIMIT n] [OFFSET n]
SHOW attribute OF domain [WHERE condition]
CHECK domain FOR conditions
COUNT domains [WHERE condition] [GROUP BY attrs]
LIST attrs FROM domains [WHERE condition] [ORDER BY attr] [LIMIT n]
Monitoring
MONITOR target EVERY interval {
ALERT ON condition {
severity: "critical|high|warning|info"
notify: ["email@example.com", "slack://channel"]
message: "Alert message with ${variables}"
}
}
Automation
FOR EACH domain IN source WHERE condition {
SEND type TO recipient WITH {params}
CREATE type IN project WITH {params}
UPDATE domain SET attr = value
EXPORT domains TO format FILE "path"
}
Policies
POLICY name {
REQUIRE condition
ON VIOLATION {
severity: "critical"
remediation: "Description"
}
}
APPLY POLICY name TO target
Common Attributes
| Category | Attributes |
|---|---|
| Domain | domain.name, domain.tld, domain.sld |
| SPF | spf.status, spf.valid, spf.record |
| DMARC | dmarc.policy, dmarc.valid, dmarc.pct |
| DKIM | dkim.enabled, dkim.valid, dkim.selectors |
| SSL | ssl.expires_in, ssl.valid, ssl.issuer, ssl.not_after |
| DNSSEC | dnssec.enabled, dnssec.valid, dnssec.status |
| MX | mx.provider, mx.servers |
Operators
=, !=, >, <, >=, <= -- Comparison
AND, OR, NOT -- Logical
IN, CONTAINS, HAS -- Collections
MATCHES, LIKE -- Pattern matching
STARTS WITH, ENDS WITH -- String matching
IS NULL, IS NOT NULL -- Null checks
EXISTS, NOT EXISTS -- Existence
Duration Literals
30.days, 1.hour, 5.minutes, 2.weeks, 1.year
CLI Commands
# Execute query
dsql execute 'FIND domains WHERE spf.status = "missing"'
# From file
dsql execute --file query.dsql
# Format output
dsql execute --format json 'COUNT domains'
# Interactive mode
dsql repl
API Endpoints
POST /api/dsl/execute # Execute query
POST /api/dsl/validate # Validate query
GET /api/dsl/queries # List saved queries
POST /api/dsl/queries # Save query
GET /api/dsl/monitors # List monitors
GET /api/dsl/history # Query history
Quick Tips
- Always use LIMIT for large result sets
- Query indexed columns (spf.valid, ssl.expires_in)
- Test queries before automation
- Use comments for complex queries
- Start monitors with low severity
- Use variables for repeated queries