diff --git a/Dockerfile b/Dockerfile index e512251..6ddf720 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/axoflow/axoflow-otel-collector/axoflow-otel-collector:0.129.0-axoflow.kafkareceiver AS axo-otelcol +FROM ghcr.io/axoflow/axoflow-otel-collector/axoflow-otel-collector:0.129.0-axoflow.4 AS axo-otelcol FROM alpine:3.21 AS base diff --git a/README.md b/README.md index 68d045b..4c33c61 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,41 @@ You can find guides per connector: | `KAFKA_TLS_KEY_FILE` | No | - | Path to client key file | | `KAFKA_TLS_INSECURE_SKIP_VERIFY` | No | `false` | Skip TLS certificate verification | +### Crowdstrike Provider + + +### Crowdstrike Provider + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `CROWDSTRIKE_ACCESS_TOKEN` | No* | - | OAuth2 access token. Required **if not using client_id/client_secret**. | +| `CROWDSTRIKE_CLIENT_ID` | No* | - | Client ID for Crowdstrike API authentication. Required **if not using access_token**. | +| `CROWDSTRIKE_CLIENT_SECRET` | No* | - | Client Secret for Crowdstrike API authentication. Required **if not using access_token**. | +| `CROWDSTRIKE_MEMBER_CID` | No | - | Member CID for MSSP (for cases when OAuth2 authenticates multiple CIDs). | +| `CROWDSTRIKE_CLOUD` | No | - | Cloud region (e.g., `us-1`, `us-2`, `eu-1`, `us-gov-1`). | +| `CROWDSTRIKE_HOST_OVERRIDE` | No | - | Optional override for API hostname. | +| `CROWDSTRIKE_BASE_PATH_OVERRIDE` | No | - | Optional override for API base path. | +| `CROWDSTRIKE_POLL_INTERVAL` | No | - | Poll interval for pulling logs/events. | +| `CROWDSTRIKE_DEBUG` | No | `false` | Enables verbose Crowdstrike API debugging. | + +#### TLS Settings + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `CROWDSTRIKE_TLS_INSECURE` | No | `false` | Disable TLS security (insecure). | +| `CROWDSTRIKE_TLS_INSECURE_SKIP_VERIFY` | No | `false` | Skip TLS certificate verification. | +| `CROWDSTRIKE_TLS_SERVER_NAME_OVERRIDE` | No | - | Optional TLS server name override. | +| `CROWDSTRIKE_TLS_CA_FILE` | No | - | Path to a CA certificate file. | +| `CROWDSTRIKE_TLS_CA_PEM` | No | - | PEM-encoded CA certificate. | +| `CROWDSTRIKE_TLS_CERT_FILE` | No | - | Path to a client certificate file. | +| `CROWDSTRIKE_TLS_CERT_PEM` | No | - | PEM-encoded client certificate. | +| `CROWDSTRIKE_TLS_KEY_FILE` | No | - | Path to a client private key file. | +| `CROWDSTRIKE_TLS_KEY_PEM` | No | - | PEM-encoded client private key. | +| `CROWDSTRIKE_TLS_MIN_VERSION` | No | `1.2` | Minimum TLS version to use. | +| `CROWDSTRIKE_TLS_MAX_VERSION` | No | - | Maximum TLS version to use. | +| `CROWDSTRIKE_TLS_INCLUDE_SYSTEM_CA_CERTS_POOL` | No | `false` | Include system CA certs along with provided CA. | + + ## Usage ### Local Development with Docker diff --git a/connectors/crowdstrike/README.md b/connectors/crowdstrike/README.md new file mode 100644 index 0000000..1b025cd --- /dev/null +++ b/connectors/crowdstrike/README.md @@ -0,0 +1,110 @@ + +# CrowdStrike Falcon Receiver + +This directory contains the Axoflow CrowdStrike Falcon receiver which helps collecting alerts from the CrowdStrike Falcon platform. + +## Quickstart + +### Authentication with ClientID / ClientSecret + +Make sure the required environment variables are set before running the receiver. + +```bash +UUID_FULL=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || python3 -c "import uuid; print(uuid.uuid4())") +AXOCLOUDCONNECTOR_DEVICE_ID=$(echo "$UUID_FULL" | cut -d'-' -f1) + +docker run \ + --rm \ + -v "${STORAGE_DIRECTORY}":"${STORAGE_DIRECTORY}" \ + -e CROWDSTRIKE_CLIENT_ID="${CROWDSTRIKE_CLIENT_ID}" \ + -e CROWDSTRIKE_CLIENT_SECRET="${CROWDSTRIKE_CLIENT_SECRET}" \ + -e CROWDSTRIKE_CLOUD="${CROWDSTRIKE_CLOUD}" \ + -e AXOROUTER_ENDPOINT="${AXOROUTER_ENDPOINT}" \ + -e STORAGE_DIRECTORY="${STORAGE_DIRECTORY}" \ + -e AXOCLOUDCONNECTOR_DEVICE_ID="${AXOCLOUDCONNECTOR_DEVICE_ID}" \ + ghcr.io/axoflow/axocloudconnectors:latest +``` + +### Authentication with Access Token + +Make sure the required environment variables are set before running the receiver. + +```bash +UUID_FULL=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || python3 -c "import uuid; print(uuid.uuid4())") +AXOCLOUDCONNECTOR_DEVICE_ID=$(echo "$UUID_FULL" | cut -d'-' -f1) + +docker run \ + --rm \ + -v "${STORAGE_DIRECTORY}":"${STORAGE_DIRECTORY}" \ + -e CROWDSTRIKE_ACCESS_TOKEN="${CROWDSTRIKE_ACCESS_TOKEN}" \ + -e CROWDSTRIKE_CLOUD="${CROWDSTRIKE_CLOUD}" \ + -e AXOROUTER_ENDPOINT="${AXOROUTER_ENDPOINT}" \ + -e STORAGE_DIRECTORY="${STORAGE_DIRECTORY}" \ + -e AXOCLOUDCONNECTOR_DEVICE_ID="${AXOCLOUDCONNECTOR_DEVICE_ID}" \ + ghcr.io/axoflow/axocloudconnectors:latest +``` + + +## Deploy with Helm-chart (ClientID / ClientSecret) + +```bash +make minikube-cluster +make docker-build +make minikube-load-image + +kubectl create namespace cloudconnectors +kubectl create secret generic crowdstrike-falcon \ + --from-literal=client-id="" \ + --from-literal=client-secret="" \ + --from-literal=cloud="" \ + --namespace cloudconnectors \ + --dry-run=client -o yaml | kubectl apply -f - + +UUID_FULL=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || python3 -c "import uuid; print(uuid.uuid4())") +AXOCLOUDCONNECTOR_DEVICE_ID=$(echo "$UUID_FULL" | cut -d'-' -f1) + +helm upgrade --install --wait --namespace cloudconnectors cloudconnectors ./charts/cloudconnectors \ + --set image.repository="axocloudconnectors" \ + --set image.tag="dev" \ + --set 'env[0].name=AXOROUTER_ENDPOINT' \ + --set 'env[0].value=axorouter.axoflow-local.svc.cluster.local:4317' \ + --set 'env[1].name=AXOCLOUDCONNECTOR_DEVICE_ID' \ + --set "env[1].value=${AXOCLOUDCONNECTOR_DEVICE_ID}" \ + --set 'env[2].name=CROWDSTRIKE_CLIENT_ID' \ + --set 'env[2].valueFrom.secretKeyRef.name=crowdstrike-falcon' \ + --set 'env[2].valueFrom.secretKeyRef.key=client-id' \ + --set 'env[3].name=CROWDSTRIKE_CLIENT_SECRET' \ + --set 'env[3].valueFrom.secretKeyRef.name=crowdstrike-falcon' \ + --set 'env[3].valueFrom.secretKeyRef.key=client-secret' \ + --set 'env[4].name=CROWDSTRIKE_CLOUD' \ + --set 'env[4].valueFrom.secretKeyRef.name=crowdstrike-falcon' \ + --set 'env[4].valueFrom.secretKeyRef.key=cloud' +``` + +## Deploy with Helm-chart (Access Token) + +```bash +kubectl create secret generic crowdstrike-falcon \ + --from-literal=access-token="" \ + --from-literal=cloud="" \ + --namespace cloudconnectors \ + --dry-run=client -o yaml | kubectl apply -f - + +UUID_FULL=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || python3 -c "import uuid; print(uuid.uuid4())") +AXOCLOUDCONNECTOR_DEVICE_ID=$(echo "$UUID_FULL" | cut -d'-' -f1) + +helm upgrade --install --wait --namespace cloudconnectors cloudconnectors ./charts/cloudconnectors \ + --set image.repository="axocloudconnectors" \ + --set image.tag="dev" \ + --set 'env[0].name=AXOROUTER_ENDPOINT' \ + --set 'env[0].value=axorouter.axoflow-local.svc.cluster.local:4317' \ + --set 'env[1].name=AXOCLOUDCONNECTOR_DEVICE_ID' \ + --set "env[1].value=${AXOCLOUDCONNECTOR_DEVICE_ID}" \ + --set 'env[2].name=CROWDSTRIKE_ACCESS_TOKEN' \ + --set 'env[2].valueFrom.secretKeyRef.name=crowdstrike-falcon' \ + --set 'env[2].valueFrom.secretKeyRef.key=access-token' \ + --set 'env[3].name=CROWDSTRIKE_CLOUD' \ + --set 'env[3].valueFrom.secretKeyRef.name=crowdstrike-falcon' \ + --set 'env[3].valueFrom.secretKeyRef.key=cloud' +``` + diff --git a/connectors/crowdstrike/config.yaml b/connectors/crowdstrike/config.yaml new file mode 100644 index 0000000..09b12f1 --- /dev/null +++ b/connectors/crowdstrike/config.yaml @@ -0,0 +1,90 @@ +exporters: + otlp/axorouter: + endpoint: ${env:AXOROUTER_ENDPOINT} + retry_on_failure: + enabled: true + max_elapsed_time: 0 + sending_queue: + enabled: true + storage: file_storage + tls: + insecure: ${env:AXOROUTER_TLS_INSECURE:-false} + ca_file: ${env:AXOROUTER_TLS_CA_FILE} + ca_pem: ${env:AXOROUTER_TLS_CA_PEM} + cert_file: ${env:AXOROUTER_TLS_CERT_FILE} + cert_pem: ${env:AXOROUTER_TLS_CERT_PEM} + key_file: ${env:AXOROUTER_TLS_KEY_FILE} + key_pem: ${env:AXOROUTER_TLS_KEY_PEM} + min_version: ${env:AXOROUTER_TLS_MIN_VERSION:-1.2} + max_version: ${env:AXOROUTER_TLS_MAX_VERSION} + include_system_ca_certs_pool: ${env:AXOROUTER_TLS_INCLUDE_SYSTEM_CA_CERTS_POOL:-false} + insecure_skip_verify: ${env:AXOROUTER_TLS_INSECURE_SKIP_VERIFY:-false} + +processors: + resource/axoflow_device_id: + attributes: + - key: "com.axoflow.device_id" + action: insert + value: "${env:AXOCLOUDCONNECTOR_DEVICE_ID}" + + resourcedetection/system: + detectors: ["system", "env"] + system: + hostname_sources: ["dns", "os", "cname", "lookup"] + resource_attributes: + host.name: + enabled: true + host.ip: + enabled: true + host.id: + enabled: true + + resource/axoflow: # Provider specific! + attributes: + - key: "com.axoflow.vendor" + action: insert + value: "crowdstrike" + - key: "com.axoflow.product" + action: insert + value: "falcon" + +receivers: # Provider specific! + crowdstrike: + access_token: ${env:CROWDSTRIKE_ACCESS_TOKEN} + client_id: ${env:CROWDSTRIKE_CLIENT_ID} + client_secret: ${env:CROWDSTRIKE_CLIENT_SECRET} + member_cid: ${env:CROWDSTRIKE_MEMBER_CID} + cloud: ${env:CROWDSTRIKE_CLOUD} + host_override: ${env:CROWDSTRIKE_HOST_OVERRIDE} + base_path_override: ${env:CROWDSTRIKE_BASE_PATH_OVERRIDE} + poll_interval: ${env:CROWDSTRIKE_POLL_INTERVAL} + debug: ${env:CROWDSTRIKE_DEBUG:-false} + tls: + insecure: ${env:CROWDSTRIKE_TLS_INSECURE:-false} + insecure_skip_verify: ${env:CROWDSTRIKE_TLS_INSECURE_SKIP_VERIFY:-false} + server_name_override: ${env:CROWDSTRIKE_TLS_SERVER_NAME_OVERRIDE} + ca_file: ${env:CROWDSTRIKE_TLS_CA_FILE} + ca_pem: ${env:CROWDSTRIKE_TLS_CA_PEM} + cert_file: ${env:CROWDSTRIKE_TLS_CERT_FILE} + cert_pem: ${env:CROWDSTRIKE_TLS_CERT_PEM} + key_file: ${env:CROWDSTRIKE_TLS_KEY_FILE} + key_pem: ${env:CROWDSTRIKE_TLS_KEY_PEM} + min_version: ${env:CROWDSTRIKE_TLS_MIN_VERSION:-1.2} + max_version: ${env:CROWDSTRIKE_TLS_MAX_VERSION} + include_system_ca_certs_pool: ${env:CROWDSTRIKE_TLS_INCLUDE_SYSTEM_CA_CERTS_POOL:-false} + +extensions: + health_check: + endpoint: ${env:POD_IP}:13133 + file_storage: + directory: ${env:STORAGE_DIRECTORY} + create_directory: true + +service: + extensions: [health_check, file_storage] + pipelines: + logs: + receivers: [crowdstrike] + processors: + [resource/axoflow_device_id, resourcedetection/system, resource/axoflow] + exporters: [otlp/axorouter] diff --git a/entrypoint.sh b/entrypoint.sh index d51c690..56248b0 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,6 +11,7 @@ detect_provider() { env | grep -q "^AZURE_" && provider="$provider azure" && count=$((count + 1)) env | grep -q "^AWS_" && provider="$provider aws" && count=$((count + 1)) env | grep -q "^KAFKA_" && provider="$provider kafka" && count=$((count + 1)) + env | grep -q "^CROWDSTRIKE_" && provider="$provider crowdstrike" && count=$((count + 1)) # env | grep -q "^GCP_" && provider="$provider gcp" && count=$((count + 1)) if [ "$count" -gt 1 ]; then @@ -31,5 +32,6 @@ echo "No cloud provider configuration detected. Please set environment variables echo " - Azure (AZURE_*)" echo " - AWS (AWS_*)" echo " - Kafka (KAFKA_*)" +echo " - Crowdstrike (CROWDSTRIKE_*)" # echo " - GCP (GCP_*)" exit 1