Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions internal-enrichment/censys-enrichmentapis/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ignore Visual Studio Code settings and workspace files
.vscode
.claude
.venv


# folders to ignore
docs/
src/censys_enrichmentapis/__pycache__
src/censys_enrichmentapis/converters/__pycache__
tests/censys_enrichmentapis/__pycache__
tests/__pycache__
.pytest_cache/

# configuration file
config.yml
src/config.yml
Taskfile.yml
30 changes: 30 additions & 0 deletions internal-enrichment/censys-enrichmentapis/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-alpine AS base

# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1

# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1

# Install Python modules
# hadolint ignore=DL3003
RUN apk update && apk upgrade && \
apk --no-cache add git build-base libmagic libffi-dev libxml2-dev libxslt-dev

# Copy the connector without local configuration or generated files
COPY --exclude=config.yml \
--exclude=.DS_Store \
--exclude=**/.DS_Store \
--exclude=__pycache__ \
--exclude=**/__pycache__ \
src /opt/opencti-connector-censys-enrichmentapis
WORKDIR /opt/opencti-connector-censys-enrichmentapis

# Install Python dependencies and remove build dependencies
RUN pip3 install --no-cache-dir -r requirements.txt && \
apk del git build-base

# Expose and entrypoint
ENTRYPOINT ["python", "main.py"]
335 changes: 335 additions & 0 deletions internal-enrichment/censys-enrichmentapis/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Connector Configurations

Below is an exhaustive enumeration of all configurable parameters available, each accompanied by detailed explanations of their purposes, default behaviors, and usage guidelines to help you understand and utilize them effectively.

### Type: `object`

| Property | Type | Required | Possible values | Default | Description |
| -------- | ---- | -------- | --------------- | ------- | ----------- |
| OPENCTI_URL | `string` | ✅ | Format: [`uri`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | | The base URL of the OpenCTI instance. |
| OPENCTI_TOKEN | `string` | ✅ | Format: [`password`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | | The API token to connect to OpenCTI. |
| CENSYS_ENRICHMENT_ORGANISATION_ID | `string` | ✅ | Format: [`password`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | | Censys organisation ID. |
| CENSYS_ENRICHMENT_TOKEN | `string` | ✅ | Format: [`password`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | | Censys API token. |
| CONNECTOR_NAME | `string` | | string | `"Censys EnrichmentAPIs"` | The name of the connector. |
| CONNECTOR_SCOPE | `array` | | string | `["IPv4-Addr", "IPv6-Addr", "X509-Certificate", "Domain-Name"]` | The scope of the connector. Must be a subset of: ['Domain-Name', 'IPv4-Addr', 'IPv6-Addr', 'X509-Certificate']. |
| CONNECTOR_LOG_LEVEL | `string` | | `debug` `info` `warn` `warning` `error` | `"error"` | The minimum level of logs to display. |
| CONNECTOR_TYPE | `const` | | `INTERNAL_ENRICHMENT` | `"INTERNAL_ENRICHMENT"` | |
| CONNECTOR_AUTO | `boolean` | | boolean | `false` | Whether the connector should run automatically when an entity is created or updated. |
| CENSYS_ENRICHMENT_MAX_TLP | `string` | | `TLP:WHITE` `TLP:CLEAR` `TLP:GREEN` `TLP:AMBER` `TLP:AMBER+STRICT` `TLP:RED` | `"TLP:AMBER"` | The maximum TLP level allowed for enrichment. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.filigran.io/connectors/censys-enrichmentapis_config.schema.json",
"type": "object",
"properties": {
"OPENCTI_URL": {
"description": "The base URL of the OpenCTI instance.",
"format": "uri",
"maxLength": 2083,
"minLength": 1,
"type": "string"
},
"OPENCTI_TOKEN": {
"description": "The API token to connect to OpenCTI.",
"format": "password",
"type": "string",
"writeOnly": true
},
"CONNECTOR_NAME": {
"default": "Censys EnrichmentAPIs",
"description": "The name of the connector.",
"type": "string"
},
"CONNECTOR_SCOPE": {
"default": [
"IPv4-Addr",
"IPv6-Addr",
"X509-Certificate",
"Domain-Name"
],
"description": "The scope of the connector. Must be a subset of: ['Domain-Name', 'IPv4-Addr', 'IPv6-Addr', 'X509-Certificate'].",
"items": {
"type": "string"
},
"type": "array"
},
"CONNECTOR_LOG_LEVEL": {
"default": "error",
"description": "The minimum level of logs to display.",
"enum": [
"debug",
"info",
"warn",
"warning",
"error"
],
"type": "string"
},
"CONNECTOR_TYPE": {
"const": "INTERNAL_ENRICHMENT",
"default": "INTERNAL_ENRICHMENT",
"type": "string"
},
"CONNECTOR_AUTO": {
"default": false,
"description": "Whether the connector should run automatically when an entity is created or updated.",
"type": "boolean"
},
"CENSYS_ENRICHMENT_MAX_TLP": {
"default": "TLP:AMBER",
"description": "The maximum TLP level allowed for enrichment.",
"enum": [
"TLP:WHITE",
"TLP:CLEAR",
"TLP:GREEN",
"TLP:AMBER",
"TLP:AMBER+STRICT",
"TLP:RED"
],
"type": "string"
},
"CENSYS_ENRICHMENT_ORGANISATION_ID": {
"description": "Censys organisation ID.",
"format": "password",
"type": "string",
"writeOnly": true
},
"CENSYS_ENRICHMENT_TOKEN": {
"description": "Censys API token.",
"format": "password",
"type": "string",
"writeOnly": true
}
},
"required": [
"OPENCTI_URL",
"OPENCTI_TOKEN",
"CENSYS_ENRICHMENT_ORGANISATION_ID",
"CENSYS_ENRICHMENT_TOKEN"
],
"additionalProperties": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"title": "Censys EnrichmentAPIs",
"slug": "censys-enrichmentapis",
"description": "The Censys EnrichmentAPIs connector allows OpenCTI to enrich observables (such as domains, IP addresses, and certificates) using data from the Censys search and intelligence platform. It retrieves detailed information on hosts, certificates, services, and organizations to enhance context and visibility within investigations.",
"short_description": "Enriches domains, IP addresses, and certificates in OpenCTI with Censys data, including host services, open ports, and certificate details for infrastructure visibility.",
"logo": "internal-enrichment/censys-enrichmentapis/__metadata__/logo.png",
"use_cases": [
"Infrastructure & Attack Surface Visibility",
"Detection & Response Enablement"
],
"solution_categories": [
"Enrichment & Reputation"
],
"license_type": "Commercial",
"contact": null,
"verified": false,
"last_verified_date": "2026-09-12",
"playbook_supported": true,
"max_confidence_level": 50,
"support_version": ">=6.8.11",
"subscription_link": "https://platform.censys.io/",
"source_code": "https://github.com/OpenCTI-Platform/connectors/tree/master/internal-enrichment/censys-enrichmentapis",
"manager_supported": true,
"container_version": "rolling",
"container_image": "opencti/connector-censys-enrichmentapis",
"container_type": "INTERNAL_ENRICHMENT"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions internal-enrichment/censys-enrichmentapis/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '3'
services:
connector-censys-enrichmentapis:
build:
context: .
dockerfile: Dockerfile
image: connector-censys-enrichmentapis:latest
environment:
# OpenCTI configuration
- OPENCTI_URL=${OPENCTI_URL:-http://localhost:8080}
- OPENCTI_TOKEN=${OPENCTI_TOKEN}
# Common connector configuration
- CONNECTOR_ID=${CONNECTOR_ID}
- CONNECTOR_NAME=${CONNECTOR_NAME:-Censys EnrichmentAPIs}
- CONNECTOR_SCOPE=${CONNECTOR_SCOPE:-IPv4-Addr,IPv6-Addr,X509-Certificate,Domain-Name}
- CONNECTOR_LOG_LEVEL=${CONNECTOR_LOG_LEVEL:-error}
- CONNECTOR_AUTO=${CONNECTOR_AUTO:-false}
# Censys configuration
- CENSYS_ENRICHMENT_ORGANISATION_ID=${CENSYS_ENRICHMENT_ORGANISATION_ID}
- CENSYS_ENRICHMENT_TOKEN=${CENSYS_ENRICHMENT_TOKEN}
- CENSYS_ENRICHMENT_MAX_TLP=${CENSYS_ENRICHMENT_MAX_TLP:-TLP:AMBER}
restart: always
5 changes: 5 additions & 0 deletions internal-enrichment/censys-enrichmentapis/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from censys_enrichmentapis.settings import ConfigLoader

__all__ = [
"ConfigLoader",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from censys_enrichmentapis.builders import (
CertificateStixBuilder,
GeographyStixBuilder,
NetworkStixBuilder,
ServiceStixBuilder,
)
from censys_enrichmentapis.builders.base import StixBuildContext
from connectors_sdk.models import BaseObject, OrganizationAuthor, TLPMarking


class CensysStixBuilder:
"""Coordinate area-specific STIX builders over one shared bundle."""

def __init__(self) -> None:
self._context = StixBuildContext()
self.geography = GeographyStixBuilder(self._context)
self.network = NetworkStixBuilder(self._context)
self.certificates = CertificateStixBuilder(self._context)
self.services = ServiceStixBuilder(self._context)

@property
def author(self) -> OrganizationAuthor:
return self._context.author

@property
def marking(self) -> TLPMarking:
return self._context.marking

@property
def bundle(self) -> list[BaseObject]:
return self._context.bundle

def reset(self) -> None:
self._context.reset()
self.services.reset()

def add_author_and_marking(self) -> None:
self._context.add_author_and_marking()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from censys_enrichmentapis.builders.certificate import CertificateStixBuilder
from censys_enrichmentapis.builders.geography import GeographyStixBuilder
from censys_enrichmentapis.builders.network import NetworkStixBuilder
from censys_enrichmentapis.builders.service import ServiceStixBuilder

__all__ = [
"CertificateStixBuilder",
"GeographyStixBuilder",
"NetworkStixBuilder",
"ServiceStixBuilder",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from connectors_sdk.models import (
BaseObject,
OrganizationAuthor,
Reference,
Relationship,
TLPMarking,
)
from connectors_sdk.models.enums import RelationshipType, TLPLevel


class StixBuildContext:
"""Shared bundle state and metadata used by all area builders."""

def __init__(self) -> None:
self.author = OrganizationAuthor(name="Censys EnrichmentAPIs Connector")
self.marking = TLPMarking(level=TLPLevel.CLEAR)
self.common_props = {"author": self.author, "markings": [self.marking]}
Comment on lines +16 to +17
self.bundle: list[BaseObject] = []

def reset(self) -> None:
# Replace rather than clear so bundles already returned to callers remain stable.
self.bundle = []

def add_author_and_marking(self) -> None:
self.bundle.extend([self.author, self.marking])
Comment on lines +24 to +25

def add_relationship(
self,
source: Reference,
target: Reference,
relationship_type: RelationshipType,
) -> None:
self.bundle.append(
Relationship(
source=source,
target=target,
type=relationship_type,
**self.common_props,
)
)


class AreaStixBuilder:
"""Base class providing area builders access to shared build state."""

def __init__(self, context: StixBuildContext) -> None:
self._context = context

@property
def bundle(self) -> list[BaseObject]:
return self._context.bundle

@property
def common_props(self) -> dict[str, object]:
return self._context.common_props

def add_relationship(
self,
source: Reference,
target: Reference,
relationship_type: RelationshipType,
) -> None:
self._context.add_relationship(source, target, relationship_type)
Loading