Namespaces
How namespaces isolate identity resolution across cloud accounts and network boundaries
Namespaces
Namespaces solve a fundamental problem in multi-account cloud environments: overlapping private IP addresses. When you ingest logs from multiple AWS accounts, GCP projects, or Azure tenants, the same private IP (e.g., 10.0.1.5) can refer to completely different machines in different accounts. Without namespaces, identity resolution and correlation would incorrectly merge these into the same entity.
How It Works
Every log event in nano has a namespace field (a UDM column stored in ClickHouse). The format is:
{provider}:{account_or_project_id}For example:
aws:123456789012gcp:my-production-projectazure:a1b2c3d4-tenant-id
When nano correlates entities (IPs, hostnames, users), it scopes the correlation within the namespace. An IP address 10.0.1.5 in aws:123456789012 is treated as a different entity from 10.0.1.5 in aws:987654321098.
When Namespaces Matter
Namespaces are primarily useful for cloud infrastructure sources where multiple accounts, projects, or tenants share the same log pipeline:
| Source Type | Namespace | Account Field |
|---|---|---|
| AWS CloudTrail | aws:{accountId} | userIdentity.accountId |
| AWS VPC Flow Logs | aws:{accountId}:{vpcId} | Account + VPC from flow log fields |
| GCP Cloud Audit | gcp:{projectId} | resource.labels.project_id |
| Azure Activity | azure:{tenantId} | tenantId |
Identity sources don't need namespaces. Sources like Okta or Microsoft Entra ID are identity providers — they don't have overlapping network addresses. Leave namespace as default for these.
Why Account ID Is Usually Enough
In AWS, accounts are the fundamental isolation boundary — equivalent to GCP projects. Most enterprises operate dozens to hundreds of accounts via AWS Organizations (e.g., prod-workloads, staging, security-tooling, log-archive). Each account has its own VPCs, IAM policies, and resources.
For API-level logs like CloudTrail, aws:{accountId} provides sufficient isolation because the source IP is typically the caller's public IP or an AWS service endpoint, not a private VPC address.
For network-level logs like VPC Flow Logs, you may want finer granularity (aws:{accountId}:{vpcId}) since these logs contain private IPs that can overlap across VPCs — even within the same account.
How Namespace Gets Set
Namespace flows through the pipeline at two levels:
1. Static Default
When you create a log source in nano, you can set a default namespace (e.g., aws:). This provides a fallback if the parser can't extract a specific account ID from the log data.
2. Dynamic Per-Event (Parser)
The parser extracts the account/project ID from each log event and sets the namespace dynamically. This is the preferred approach since a single log feed (like an AWS Organization CloudTrail trail) can contain events from many accounts.
Example VRL in a CloudTrail parser:
# Extract account ID from CloudTrail userIdentity
if exists(parsed.userIdentity.accountId) {
.udm.cloud_account_id = string!(parsed.userIdentity.accountId)
.udm.namespace = "aws:" + string!(parsed.userIdentity.accountId)
} else {
.udm.namespace = "aws:"
}The AI parser editor understands namespace conventions and can add this extraction automatically when you ask it to set up namespace for a cloud source.
3. Pipeline Injection
The output transform injects the namespace into the event before it reaches ClickHouse. If the parser doesn't set a namespace via .udm.namespace, the static default from the log source configuration is used. If neither is set, the event gets namespace = "default".
Querying with Namespaces
You can filter by namespace in search queries:
namespace="aws:123456789012" src_ip="10.0.1.5"
| stats count by action, userOr compare activity across accounts:
action="AssumeRole"
| stats count by namespace
| sort -count