From 0f5eee0bccdd307f1abba25fe18b52eadbcdcc61 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Tue, 18 Aug 2026 16:49:48 +0200 Subject: [PATCH 1/9] feat(group-ib): normalize config files for manager-supported migration (#7282) --- external-import/group-ib/.env.sample | 1 - external-import/group-ib/src/config.yml.sample | 1 - external-import/group-ib/src/requirements.txt | 4 +++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/external-import/group-ib/.env.sample b/external-import/group-ib/.env.sample index cf465044777..10e44027004 100644 --- a/external-import/group-ib/.env.sample +++ b/external-import/group-ib/.env.sample @@ -9,7 +9,6 @@ OPENCTI_TOKEN= CONNECTOR_DOCKER_CONTAINER_NAME=gib_connector # Generate one with uuidgen (https://www.uuidgenerator.net/version4) CONNECTOR_ID= -CONNECTOR_TYPE=EXTERNAL_IMPORT CONNECTOR_NAME=Group-IB Connector CONNECTOR_SCOPE=stix2,ipv4-addr,ipv6-addr,vulnerability,domain,url,StixFile # One of the following: debug, info, warning, error diff --git a/external-import/group-ib/src/config.yml.sample b/external-import/group-ib/src/config.yml.sample index 3dded6ee1ba..cc75c10dc7d 100644 --- a/external-import/group-ib/src/config.yml.sample +++ b/external-import/group-ib/src/config.yml.sample @@ -5,7 +5,6 @@ opencti: token: "" connector: - type: 'EXTERNAL_IMPORT' # Generate one with uuidgen (https://www.uuidgenerator.net/version4) id: "" name: "Group-IB Connector" diff --git a/external-import/group-ib/src/requirements.txt b/external-import/group-ib/src/requirements.txt index eec13f15eb8..7d6290762f6 100644 --- a/external-import/group-ib/src/requirements.txt +++ b/external-import/group-ib/src/requirements.txt @@ -2,4 +2,6 @@ cyberintegrations==0.14.1 pycti==7.260817.0 python-dotenv==1.2.2 stix2==3.0.1 -isodate==0.7.2 \ No newline at end of file +isodate==0.7.2 +pydantic >=2.8.2, <3 +connectors-sdk @ git+https://github.com/OpenCTI-Platform/connectors.git@master#subdirectory=connectors-sdk From c1484474e3740afe383aac7bb36115dcccc802d4 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Tue, 18 Aug 2026 16:54:32 +0200 Subject: [PATCH 2/9] feat(group-ib): add Pydantic settings for manager-supported mode (#7282) --- external-import/group-ib/.env.sample | 397 +++++----- external-import/group-ib/src/__init__.py | 5 + .../group-ib/src/config.yml.sample | 583 +++++---------- external-import/group-ib/src/settings.py | 675 ++++++++++++++++++ 4 files changed, 1057 insertions(+), 603 deletions(-) create mode 100644 external-import/group-ib/src/__init__.py create mode 100644 external-import/group-ib/src/settings.py diff --git a/external-import/group-ib/.env.sample b/external-import/group-ib/.env.sample index 10e44027004..e0ed1fdada5 100644 --- a/external-import/group-ib/.env.sample +++ b/external-import/group-ib/.env.sample @@ -2,215 +2,198 @@ # http://opencti:8080 - for docker deployment, http://localhost:8080 - for manual deployment OPENCTI_URL=http://opencti:8080 # Use one as provided by the OpenCTI platform -OPENCTI_TOKEN= +OPENCTI_TOKEN=ChangeMe # === OpenCTI Connector === -# Docker container name -CONNECTOR_DOCKER_CONTAINER_NAME=gib_connector # Generate one with uuidgen (https://www.uuidgenerator.net/version4) -CONNECTOR_ID= -CONNECTOR_NAME=Group-IB Connector -CONNECTOR_SCOPE=stix2,ipv4-addr,ipv6-addr,vulnerability,domain,url,StixFile -# One of the following: debug, info, warning, error -CONNECTOR_LOG_LEVEL="info" -# Specifies the time interval in ISO 8601 format (Duration): -# Format: P[n]Y[n]M[n]DT[n]H[n]M[n]S -# - P: indicates the beginning of the period (Period). -# - T: separates date and time, used before time components. -# - n: a number representing a quantity (e.g. 3 for 3 minutes). -# -# Examples: -# - PT3M: an interval of 3 minutes. -# - PT5S: an interval of 5 seconds. -# - P1DT2H: an interval of 1 day and 2 hours. -CONNECTOR_DURATION_PERIOD=PT4H -CONNECTOR_UPDATE_EXISTING_DATA=true - -# === RabbitMQ Server used for integration manual run === -CONNECTOR_MQ_HOST=localhost -CONNECTOR_MQ_PORT=5672 -CONNECTOR_MQ_VHOST=/ -CONNECTOR_MQ_USE_SSL=false -CONNECTOR_MQ_USER=guest -CONNECTOR_MQ_PASS=guest +CONNECTOR_ID=696ac767-c12a-452b-9b77-993e1007eed6 +# Optional connector settings (defaults defined in src/settings.py) +# CONNECTOR_NAME=Group-IB Connector +# CONNECTOR_SCOPE=stix2,ipv4-addr,ipv6-addr,vulnerability,domain,url,StixFile +# One of the following: debug, info, warn, warning, error +# CONNECTOR_LOG_LEVEL=info +# Interval between two runs in ISO-8601 duration format (e.g. PT4H, PT3M, P1D) +# CONNECTOR_DURATION_PERIOD=PT4H +# CONNECTOR_UPDATE_EXISTING_DATA=true # === Threat Intelligence API Server === -# Connector specific parameters. All params are mandatory. -TI_API__URL=https://tap.group-ib.com/api/v2/ -TI_API__USERNAME= -TI_API__TOKEN= - -# === Threat Intelligence API Proxy === -# Proxy specifc parameters. You can leave them blank. -TI_API__PROXY__IP= -TI_API__PROXY__PORT= -TI_API__PROXY__PROTOCOL= -TI_API__PROXY__USERNAME= -TI_API__PROXY__PASSWORD= - -# Threat Intelligence Collections settings -TI_API__EXTRA_SETTINGS__IGNORE_NON_INDICATOR_THREAT_REPORTS=false -TI_API__EXTRA_SETTINGS__IGNORE_NON_INDICATOR_THREATS=false -TI_API__EXTRA_SETTINGS__IGNORE_NON_MALWARE_DDOS=true -TI_API__EXTRA_SETTINGS__INTRUSION_SET_INSTEAD_OF_THREAT_ACTOR=false -TI_API__EXTRA_SETTINGS__SCHEDULE_TIME=00:00 -TI_API__EXTRA_SETTINGS__TIME_OUTPUT_FORMAT='%Y-%m-%d %H:%M:%S' -TI_API__EXTRA_SETTINGS__ENABLE_STATEMENT_MARKING=false - -# Collections -TI_API__COLLECTIONS__APT_THREAT__DEFAULT_DATE= -TI_API__COLLECTIONS__APT_THREAT__ENABLE=false -TI_API__COLLECTIONS__APT_THREAT__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__APT_THREAT__TTL=1460 -TI_API__COLLECTIONS__APT_THREAT__USE_HUNTING_RULES=false - -TI_API__COLLECTIONS__APT_THREAT_ACTOR__DEFAULT_DATE= -TI_API__COLLECTIONS__APT_THREAT_ACTOR__ENABLE=false -TI_API__COLLECTIONS__APT_THREAT_ACTOR__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__APT_THREAT_ACTOR__TTL=1460 - -TI_API__COLLECTIONS__ATTACKS_DDOS__DEFAULT_DATE= -TI_API__COLLECTIONS__ATTACKS_DDOS__ENABLE=false -TI_API__COLLECTIONS__ATTACKS_DDOS__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__ATTACKS_DDOS__TTL=10 - -TI_API__COLLECTIONS__ATTACKS_DEFACE__DEFAULT_DATE= -TI_API__COLLECTIONS__ATTACKS_DEFACE__ENABLE=false -TI_API__COLLECTIONS__ATTACKS_DEFACE__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__ATTACKS_DEFACE__TTL=10 - -TI_API__COLLECTIONS__ATTACKS_PHISHING_GROUP__DEFAULT_DATE= -TI_API__COLLECTIONS__ATTACKS_PHISHING_GROUP__ENABLE=false -TI_API__COLLECTIONS__ATTACKS_PHISHING_GROUP__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__ATTACKS_PHISHING_GROUP__TTL=5 - -TI_API__COLLECTIONS__ATTACKS_PHISHING_KIT__DEFAULT_DATE= -TI_API__COLLECTIONS__ATTACKS_PHISHING_KIT__ENABLE=false -TI_API__COLLECTIONS__ATTACKS_PHISHING_KIT__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__ATTACKS_PHISHING_KIT__TTL=30 - -TI_API__COLLECTIONS__COMPROMISED_ACCESS__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_ACCESS__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_ACCESS__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_ACCESS__TTL=1460 - -TI_API__COLLECTIONS__COMPROMISED_ACCOUNT_GROUP__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_ACCOUNT_GROUP__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_ACCOUNT_GROUP__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_ACCOUNT_GROUP__TTL=1460 - -TI_API__COLLECTIONS__COMPROMISED_BANK_CARD_GROUP__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_BANK_CARD_GROUP__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_BANK_CARD_GROUP__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_BANK_CARD_GROUP__TTL=730 - -TI_API__COLLECTIONS__COMPROMISED_DISCORD__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_DISCORD__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_DISCORD__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_DISCORD__TTL=30 - -TI_API__COLLECTIONS__COMPROMISED_IMEI__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_IMEI__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_IMEI__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_IMEI__TTL=30 - -TI_API__COLLECTIONS__COMPROMISED_MASKED_CARD__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_MASKED_CARD__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_MASKED_CARD__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_MASKED_CARD__TTL=90 - -TI_API__COLLECTIONS__COMPROMISED_MESSENGER__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_MESSENGER__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_MESSENGER__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_MESSENGER__TTL=30 - -TI_API__COLLECTIONS__COMPROMISED_MULE__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__COMPROMISED_MULE__ENABLE=false -TI_API__COLLECTIONS__COMPROMISED_MULE__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__COMPROMISED_MULE__TTL=30 - -TI_API__COLLECTIONS__HI_OPEN_THREATS__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__HI_OPEN_THREATS__ENABLE=false -TI_API__COLLECTIONS__HI_OPEN_THREATS__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__HI_OPEN_THREATS__TTL= - -TI_API__COLLECTIONS__HI_THREAT__DEFAULT_DATE= -TI_API__COLLECTIONS__HI_THREAT__ENABLE=false -TI_API__COLLECTIONS__HI_THREAT__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__HI_THREAT__TTL=1460 -TI_API__COLLECTIONS__HI_THREAT__USE_HUNTING_RULES=false - -TI_API__COLLECTIONS__HI_THREAT_ACTOR__DEFAULT_DATE= -TI_API__COLLECTIONS__HI_THREAT_ACTOR__ENABLE=false -TI_API__COLLECTIONS__HI_THREAT_ACTOR__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__HI_THREAT_ACTOR__TTL=1460 - -TI_API__COLLECTIONS__IOC_COMMON__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__IOC_COMMON__ENABLE=false -TI_API__COLLECTIONS__IOC_COMMON__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__IOC_COMMON__TTL=90 - -TI_API__COLLECTIONS__MALWARE_CNC__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__MALWARE_CNC__ENABLE=false -TI_API__COLLECTIONS__MALWARE_CNC__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__MALWARE_CNC__TTL=90 - -TI_API__COLLECTIONS__MALWARE_CONFIG__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__MALWARE_CONFIG__ENABLE=false -TI_API__COLLECTIONS__MALWARE_CONFIG__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__MALWARE_CONFIG__TTL=90 - -TI_API__COLLECTIONS__MALWARE_MALWARE__DEFAULT_DATE= -TI_API__COLLECTIONS__MALWARE_MALWARE__ENABLE=false -TI_API__COLLECTIONS__MALWARE_MALWARE__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__MALWARE_MALWARE__TTL=1460 - -TI_API__COLLECTIONS__MALWARE_SIGNATURE__DEFAULT_DATE= -TI_API__COLLECTIONS__MALWARE_SIGNATURE__ENABLE=false -TI_API__COLLECTIONS__MALWARE_SIGNATURE__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__MALWARE_SIGNATURE__TTL=30 - -TI_API__COLLECTIONS__MALWARE_YARA__DEFAULT_DATE= -TI_API__COLLECTIONS__MALWARE_YARA__ENABLE=false -TI_API__COLLECTIONS__MALWARE_YARA__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__MALWARE_YARA__TTL=30 - -TI_API__COLLECTIONS__OSI_GIT_REPOSITORY__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__OSI_GIT_REPOSITORY__ENABLE=false -TI_API__COLLECTIONS__OSI_GIT_REPOSITORY__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__OSI_GIT_REPOSITORY__TTL=30 - -TI_API__COLLECTIONS__OSI_PUBLIC_LEAK__DEFAULT_DATE="Warning! Collection is not implemented in the current version" -TI_API__COLLECTIONS__OSI_PUBLIC_LEAK__ENABLE=false -TI_API__COLLECTIONS__OSI_PUBLIC_LEAK__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__OSI_PUBLIC_LEAK__TTL=15 - -TI_API__COLLECTIONS__OSI_VULNERABILITY__DEFAULT_DATE= -TI_API__COLLECTIONS__OSI_VULNERABILITY__ENABLE=false -TI_API__COLLECTIONS__OSI_VULNERABILITY__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__OSI_VULNERABILITY__TTL=90 - -TI_API__COLLECTIONS__SUSPICIOUS_IP_OPEN_PROXY__DEFAULT_DATE= -TI_API__COLLECTIONS__SUSPICIOUS_IP_OPEN_PROXY__ENABLE=false -TI_API__COLLECTIONS__SUSPICIOUS_IP_OPEN_PROXY__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__SUSPICIOUS_IP_OPEN_PROXY__TTL=5 - -TI_API__COLLECTIONS__SUSPICIOUS_IP_SCANNER__DEFAULT_DATE= -TI_API__COLLECTIONS__SUSPICIOUS_IP_SCANNER__ENABLE=false -TI_API__COLLECTIONS__SUSPICIOUS_IP_SCANNER__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__SUSPICIOUS_IP_SCANNER__TTL=5 - -TI_API__COLLECTIONS__SUSPICIOUS_IP_SOCKS_PROXY__DEFAULT_DATE= -TI_API__COLLECTIONS__SUSPICIOUS_IP_SOCKS_PROXY__ENABLE=false -TI_API__COLLECTIONS__SUSPICIOUS_IP_SOCKS_PROXY__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__SUSPICIOUS_IP_SOCKS_PROXY__TTL=5 - -TI_API__COLLECTIONS__SUSPICIOUS_IP_TOR_NODE__DEFAULT_DATE= -TI_API__COLLECTIONS__SUSPICIOUS_IP_TOR_NODE__ENABLE=false -TI_API__COLLECTIONS__SUSPICIOUS_IP_TOR_NODE__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__SUSPICIOUS_IP_TOR_NODE__TTL=5 - -TI_API__COLLECTIONS__SUSPICIOUS_IP_VPN__DEFAULT_DATE= -TI_API__COLLECTIONS__SUSPICIOUS_IP_VPN__ENABLE=false -TI_API__COLLECTIONS__SUSPICIOUS_IP_VPN__LOCAL_CUSTOM_TAG=null -TI_API__COLLECTIONS__SUSPICIOUS_IP_VPN__TTL=5 \ No newline at end of file +# Mandatory connector-specific credentials. +TI_API_USERNAME=ChangeMe +TI_API_TOKEN=ChangeMe +# TI_API_URL=https://tap.group-ib.com/api/v2/ + +# === Threat Intelligence API Proxy (optional) === +# TI_API_PROXY_IP= +# TI_API_PROXY_PORT= +# TI_API_PROXY_PROTOCOL= +# TI_API_PROXY_USERNAME= +# TI_API_PROXY_PASSWORD= + +# === Threat Intelligence Extra settings === +# TI_API_EXTRA_SETTINGS_IGNORE_NON_INDICATOR_THREAT_REPORTS=false +# TI_API_EXTRA_SETTINGS_IGNORE_NON_INDICATOR_THREATS=false +# TI_API_EXTRA_SETTINGS_IGNORE_NON_MALWARE_DDOS=true +# TI_API_EXTRA_SETTINGS_INTRUSION_SET_INSTEAD_OF_THREAT_ACTOR=false +# TI_API_EXTRA_SETTINGS_SCHEDULE_TIME=00:00 +# TI_API_EXTRA_SETTINGS_TIME_OUTPUT_FORMAT=%Y-%m-%d %H:%M:%S +# TI_API_EXTRA_SETTINGS_ENABLE_STATEMENT_MARKING=false + +# === Threat Intelligence Collections === +# All collections are disabled by default; enable and tune the ones you need. +# --- apt/threat --- +# TI_API_COLLECTIONS_APT_THREAT_DEFAULT_DATE= +# TI_API_COLLECTIONS_APT_THREAT_ENABLE=false +# TI_API_COLLECTIONS_APT_THREAT_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_APT_THREAT_TTL=90 +# TI_API_COLLECTIONS_APT_THREAT_USE_HUNTING_RULES=false +# --- apt/threat_actor --- +# TI_API_COLLECTIONS_APT_THREAT_ACTOR_DEFAULT_DATE= +# TI_API_COLLECTIONS_APT_THREAT_ACTOR_ENABLE=false +# TI_API_COLLECTIONS_APT_THREAT_ACTOR_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_APT_THREAT_ACTOR_TTL=90 +# --- attacks/ddos --- +# TI_API_COLLECTIONS_ATTACKS_DDOS_DEFAULT_DATE= +# TI_API_COLLECTIONS_ATTACKS_DDOS_ENABLE=false +# TI_API_COLLECTIONS_ATTACKS_DDOS_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_ATTACKS_DDOS_TTL=30 +# --- attacks/deface --- +# TI_API_COLLECTIONS_ATTACKS_DEFACE_DEFAULT_DATE= +# TI_API_COLLECTIONS_ATTACKS_DEFACE_ENABLE=false +# TI_API_COLLECTIONS_ATTACKS_DEFACE_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_ATTACKS_DEFACE_TTL=30 +# --- attacks/phishing_group --- +# TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_DEFAULT_DATE= +# TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_ENABLE=false +# TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_TTL=30 +# --- attacks/phishing_kit --- +# TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_DEFAULT_DATE= +# TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_ENABLE=false +# TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_TTL=30 +# --- compromised/access --- +# TI_API_COLLECTIONS_COMPROMISED_ACCESS_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_ACCESS_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_ACCESS_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_ACCESS_TTL=90 +# --- compromised/account_group --- +# TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_TTL=90 +# --- compromised/bank_card_group --- +# TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_TTL=90 +# --- compromised/discord --- +# TI_API_COLLECTIONS_COMPROMISED_DISCORD_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_DISCORD_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_DISCORD_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_DISCORD_TTL= +# --- compromised/imei --- +# TI_API_COLLECTIONS_COMPROMISED_IMEI_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_IMEI_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_IMEI_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_IMEI_TTL=30 +# --- compromised/masked_card --- +# TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_TTL=90 +# --- compromised/messenger --- +# TI_API_COLLECTIONS_COMPROMISED_MESSENGER_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_MESSENGER_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_MESSENGER_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_MESSENGER_TTL= +# --- compromised/mule --- +# TI_API_COLLECTIONS_COMPROMISED_MULE_DEFAULT_DATE= +# TI_API_COLLECTIONS_COMPROMISED_MULE_ENABLE=false +# TI_API_COLLECTIONS_COMPROMISED_MULE_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_COMPROMISED_MULE_TTL=30 +# --- hi/open_threats --- +# TI_API_COLLECTIONS_HI_OPEN_THREATS_DEFAULT_DATE= +# TI_API_COLLECTIONS_HI_OPEN_THREATS_ENABLE=false +# TI_API_COLLECTIONS_HI_OPEN_THREATS_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_HI_OPEN_THREATS_TTL= +# --- hi/threat --- +# TI_API_COLLECTIONS_HI_THREAT_DEFAULT_DATE= +# TI_API_COLLECTIONS_HI_THREAT_ENABLE=false +# TI_API_COLLECTIONS_HI_THREAT_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_HI_THREAT_TTL=90 +# TI_API_COLLECTIONS_HI_THREAT_USE_HUNTING_RULES=false +# --- hi/threat_actor --- +# TI_API_COLLECTIONS_HI_THREAT_ACTOR_DEFAULT_DATE= +# TI_API_COLLECTIONS_HI_THREAT_ACTOR_ENABLE=false +# TI_API_COLLECTIONS_HI_THREAT_ACTOR_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_HI_THREAT_ACTOR_TTL=90 +# --- ioc/common --- +# TI_API_COLLECTIONS_IOC_COMMON_DEFAULT_DATE= +# TI_API_COLLECTIONS_IOC_COMMON_ENABLE=false +# TI_API_COLLECTIONS_IOC_COMMON_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_IOC_COMMON_TTL=90 +# --- malware/cnc --- +# TI_API_COLLECTIONS_MALWARE_CNC_DEFAULT_DATE= +# TI_API_COLLECTIONS_MALWARE_CNC_ENABLE=false +# TI_API_COLLECTIONS_MALWARE_CNC_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_MALWARE_CNC_TTL=90 +# --- malware/config --- +# TI_API_COLLECTIONS_MALWARE_CONFIG_DEFAULT_DATE= +# TI_API_COLLECTIONS_MALWARE_CONFIG_ENABLE=false +# TI_API_COLLECTIONS_MALWARE_CONFIG_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_MALWARE_CONFIG_TTL=30 +# --- malware/malware --- +# TI_API_COLLECTIONS_MALWARE_MALWARE_DEFAULT_DATE= +# TI_API_COLLECTIONS_MALWARE_MALWARE_ENABLE=false +# TI_API_COLLECTIONS_MALWARE_MALWARE_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_MALWARE_MALWARE_TTL= +# --- malware/signature --- +# TI_API_COLLECTIONS_MALWARE_SIGNATURE_DEFAULT_DATE= +# TI_API_COLLECTIONS_MALWARE_SIGNATURE_ENABLE=false +# TI_API_COLLECTIONS_MALWARE_SIGNATURE_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_MALWARE_SIGNATURE_TTL= +# --- malware/yara --- +# TI_API_COLLECTIONS_MALWARE_YARA_DEFAULT_DATE= +# TI_API_COLLECTIONS_MALWARE_YARA_ENABLE=false +# TI_API_COLLECTIONS_MALWARE_YARA_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_MALWARE_YARA_TTL= +# --- osi/git_repository --- +# TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_DEFAULT_DATE= +# TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_ENABLE=false +# TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_TTL=30 +# --- osi/public_leak --- +# TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_DEFAULT_DATE= +# TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_ENABLE=false +# TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_TTL=30 +# --- osi/vulnerability --- +# TI_API_COLLECTIONS_OSI_VULNERABILITY_DEFAULT_DATE= +# TI_API_COLLECTIONS_OSI_VULNERABILITY_ENABLE=false +# TI_API_COLLECTIONS_OSI_VULNERABILITY_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_OSI_VULNERABILITY_TTL=30 +# --- suspicious_ip/open_proxy --- +# TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_DEFAULT_DATE= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_ENABLE=false +# TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_TTL=15 +# --- suspicious_ip/scanner --- +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_DEFAULT_DATE= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_ENABLE=false +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_TTL=15 +# --- suspicious_ip/socks_proxy --- +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_DEFAULT_DATE= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_ENABLE=false +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_TTL=2 +# --- suspicious_ip/tor_node --- +# TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_DEFAULT_DATE= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_ENABLE=false +# TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_TTL=30 +# --- suspicious_ip/vpn --- +# TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_DEFAULT_DATE= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_ENABLE=false +# TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_LOCAL_CUSTOM_TAG= +# TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_TTL=30 diff --git a/external-import/group-ib/src/__init__.py b/external-import/group-ib/src/__init__.py new file mode 100644 index 00000000000..7d463d50a99 --- /dev/null +++ b/external-import/group-ib/src/__init__.py @@ -0,0 +1,5 @@ +"""Expose ``ConnectorSettings`` at the package level for config-schema generation.""" + +from settings import ConnectorSettings + +__all__ = ["ConnectorSettings"] diff --git a/external-import/group-ib/src/config.yml.sample b/external-import/group-ib/src/config.yml.sample index cc75c10dc7d..3783ca994dd 100644 --- a/external-import/group-ib/src/config.yml.sample +++ b/external-import/group-ib/src/config.yml.sample @@ -1,408 +1,199 @@ opencti: # http://opencti:8080 - for docker deployment, http://localhost:8080 - for manual deployment - url: 'http://localhost' + url: 'http://localhost:8080' # Use one as provided by the OpenCTI platform - token: "" + token: 'ChangeMe' +# Optional connector settings (defaults defined in src/settings.py) connector: # Generate one with uuidgen (https://www.uuidgenerator.net/version4) - id: "" - name: "Group-IB Connector" - scope: "stix2,ipv4-addr,ipv6-addr,vulnerability,domain,url,StixFile" - docker_container_name: "gib_connector" - # One of the following: debug, info, warning, error - log_level: "debug" - # Specifies the time interval in ISO 8601 format (Duration): - # Format: P[n]Y[n]M[n]DT[n]H[n]M[n]S - # - P: indicates the beginning of the period (Period). - # - T: separates date and time, used before time components. - # - n: a number representing a quantity (e.g. 3 for 3 minutes). - # - # Examples: - # - PT3M: an interval of 3 minutes. - # - PT5S: an interval of 5 seconds. - # - P1DT2H: an interval of 1 day and 2 hours. - duration_period: "PT3M" - # From 0 (Unknown) to 100 (Fully trusted) - confidence_level: 100 - update_existing_data: true - # === RabbitMQ Server used for integration manual run === - mq_host: localhost - mq_port: 5672 - mq_vhost: "/" - mq_use_ssl: false - mq_user: "guest" - mq_pass: "guest" + id: '696ac767-c12a-452b-9b77-993e1007eed6' + # name: 'Group-IB Connector' + # scope: 'stix2,ipv4-addr,ipv6-addr,vulnerability,domain,url,StixFile' + # One of the following: debug, info, warn, warning, error + # log_level: 'info' + # Interval between two runs in ISO-8601 duration format (e.g. PT4H, PT3M, P1D) + # duration_period: 'PT4H' + # update_existing_data: true # === Threat Intelligence API Server === -# Connector specific parameters. All params are mandatory. ti_api: - url: "https://tap.group-ib.com/api/v2/" - username: "" - token: "" - # === Threat Intelligence API Proxy === - # Proxy specifc parameters. You can leave them blank. - proxy: - ip: - port: - protocol: - username: - password: + # Mandatory connector-specific credentials. + username: 'ChangeMe' + token: 'ChangeMe' + # url: 'https://tap.group-ib.com/api/v2/' - # === Threat Intelligence Collections settings - # Collections specifc parameters. All params are mandatory. - - extra_settings: - ignore_non_indicator_threat_reports: false - ignore_non_indicator_threats: false - ignore_non_malware_ddos: true - intrusion_set_instead_of_threat_actor: false - schedule_time: 00:00 - time_output_format: '%Y-%m-%d %H:%M:%S' - enable_statement_marking: true + # === Proxy (optional) === + # proxy_ip: + # proxy_port: + # proxy_protocol: + # proxy_username: + # proxy_password: - collections: - - apt/threat: - description: - A collection of Indicators and MITRE ATT&CK matrix. It contains HASH - sums of malicious files that were generated by hackers, IP addresses, domains, - CVE and the group's activities, motives, and goals to understand what tools - and tactics they use according to the MITRE ATT&CK matrix. - default_date: '' # Example: 2025-01-01 - enable: false - local_custom_tag: null - ttl: 90 - use_hunting_rules: false - - apt/threat_actor: - description: - Cybercriminal groups including nation-state (state-sponsored hacker - groups) and organized threat groups that target various industries and countries. - default_date: '' - enable: false - local_custom_tag: null - ttl: 90 - - attacks/ddos: - description: - An attack that creates a load on the server and is executed simultaneously - from a large number of computers (often a network of infected zombie computers - is used) in order to create an artificial increase in requests to a resource - and thereby disable it. - default_date: '' - enable: false - local_custom_tag: null - ttl: 30 - - attacks/deface: - description: - Defacement attacks are often conducted by web-hooligans (a form of - vandalism) or hacktivists (politically or religiously motivated actors) whose - aim is to draw attention to something. After a successful attack, the threat - actors publish information on special sites dedicated to defacement, social - media, or their personal sites. - default_date: '' - enable: false - local_custom_tag: null - ttl: 30 - - attacks/phishing_group: - description: - The Phishing displays information about various phishing resources - (including sites masqueraded as Google, Microsoft, etc.). Group-IB collects - this data with the help of Passive-DNS analysis performed by Managed XDR (Managed - Extended Detection and Response) systems, alerts received by CERT-GIB, tracked - SPAM messages, malicious contextual advertising, new domain names, and other - valuable data. - default_date: null - enable: false - local_custom_tag: null - ttl: 30 - - attacks/phishing_kit: - description: - A Phishing kit is a collection of pages, scripts, and images that - keep a phishing website up and running. In other words, it is a ready-made phishing - website with a relevant settings file that specifies the parameters of how the - page needs to be displayed. - default_date: null - enable: false - local_custom_tag: null - ttl: 30 - - compromised/access: - description: - This collection displays the freshest information about compromised - data from various darkweb marketplaces (which sell illegal or restricted data - and services, according to the laws of a particular country). Most often it - is malware, hacked databases of social networks and so on. The information obtained - from this collection can help detect relevant threats that compromise company - employees, customers or systems on the internal network. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 90 + # === Extra settings === + # extra_settings_ignore_non_indicator_threat_reports: false + # extra_settings_ignore_non_indicator_threats: false + # extra_settings_ignore_non_malware_ddos: true + # extra_settings_intrusion_set_instead_of_threat_actor: false + # extra_settings_schedule_time: '00:00' + # extra_settings_time_output_format: '%Y-%m-%d %H:%M:%S' + # extra_settings_enable_statement_marking: false - compromised/account_group: - description: - Hackers use phishing websites and malware for PC and Android to steal - logins and passwords. These can be credentials for the internal corporate systems - or external services for clients, such as Internet banking details. Malicious - programs transfer the intercepted data to attacker-controlled remote servers. - This server is the central data collection point for intercepted passwords and - other information that malware gathers. All data is distributed into the following - groups service, host, login and password. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 90 - - compromised/bank_card_group: - description: - Bank Cards Group collection contains information about compromised - bank cards and masked cards. This includes data collected from card shops, specialized - forums, and public sources. All data collected is grouped by card number. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 90 - - compromised/discord: - description: - The Discord collection contains data that was received by the TI - system from Discord. The Threat Intelligence system analyzes every chat and - channel (even private ones). Here detailed information about Discord servers, - channels and users can be extracted. You can also find data from the channels - which were added manually to the TI system. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: null - - compromised/imei: - description: - Android Trojans are designed to steal money from bank accounts, spy - on account holders, and extort money. They can intercept SMS messages, recover - passwords from cloud storage services, upload photo and video files, transmit - the device geolocation and lists of installed applications from a mobile device - to the threat actor, and automatically transfer funds. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 30 - - compromised/masked_card: - description: - Masked Card collection contains information about compromised masked - cards. This includes data collected from card shops, specialized forums, and - public sources. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 90 - - compromised/messenger: - description: - In this collection information from the Telegram chats and channels - can be found. The transferred or plan to transfer stolen money to. Man-in-the-Browser - (MITB) attacks, mobile Trojans, and phishing kits allow fraudsters to make money - transfers automatically. Analyzing bank-targeted botnets helps extract this - data from malware configuration files. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: null - - compromised/mule: - description: - This collection contains data about bank accounts threat actors have - transferred or plan to transfer stolen money to. Man-in-the-Browser (MITB) attacks, - mobile Trojans, and phishing kits allow fraudsters to make money transfers automatically. - Analyzing bank-targeted botnets helps extract this data from malware configuration - files. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 30 - - hi/open_threats: - description: - The Open Threats collection consolidates public reports from various - cybersecurity vendors and researchers globally. All detected events are classified - by criteria such as threat actor, malware or country and tagged with common - identifiers. This makes it easier to understand the content at a glance and - apply intelligent filtering based on specific tags. The indicators from this - feed are automatically parsed, making it easy to integrate them into your security - measures. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: null - - hi/threat: - description: - A collection of Indicators and MITRE ATT&CK matrix. It contains HASH - sums of malicious files that were generated by hackers, IP addresses, domains, - CVE and group's activities, motives, and goals to understand what tools and - tactics they use according to the MITRE ATT&CK matrix. - default_date: null - enable: false - local_custom_tag: null - ttl: 90 - use_hunting_rules: false - - hi/threat_actor: - description: - Cybercriminal groups including nation-state (state-sponsored hacker - groups) and organized threat groups that target various industries and countries. - default_date: null - enable: false - local_custom_tag: null - ttl: 90 - - ioc/common: - description: - The Common IoCs collection can help identify malicious activity or - security threats. Indicators of Compromise are clues and evidence of a data - breach, usually observed during a cybersecurity attack. Identified IoCs provide - the organization with a window into the techniques and methodologies of the - attackers who target them. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 90 - - malware/cnc: - description: - Command and control. CNC collection contains information on the control - center where malware related to targeted attacks use to store stolen data or - download commands from. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 90 - - malware/config: - description: - Malicious files come from Malware control center. Contains HASH sums - of malicious files that were generated by hackers, IP addresses, and domains. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 30 - - malware/malware: - description: - The Malware collection contains detailed information about specific - malware detected through analyzing Threat Actors activity. Can contain malware - names, related attacker names and additionally legitimate tools used by attackers - during an attack. - default_date: null - enable: false - local_custom_tag: null - ttl: null - - malware/signature: - description: - This collection contains malware signatures that can be used to enrich - malware security feeds, detect potentially confidential information and identify - specific malware promptly. Here the signature name, class and raw data can be - found (if detected). - default_date: null - enable: false - local_custom_tag: null - ttl: null - - malware/yara: - description: - This collection includes data related to YARA rules and containing - information about specific malware families. Here YARA rule name, class and - raw data can be displayed (if detected). - default_date: null - enable: false - local_custom_tag: null - ttl: null - - osi/git_repository: - description: - Open-source repositories such as GitHub contain codes that anyone - can search for. They are often used by threat actors planning to attack a specific - company. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 30 - - osi/public_leak: - description: - There are specialized websites for exchanging textual information - (such as Pastebin and analogous resources). They can be used to upload texts - and send anyone a link to them. Both legitimate IT specialists and hackers actively - use such resources. IT professionals may underestimate the risks and load configuration - files for network equipment, export tables from databases, code fragments containing - access credentials, and much more. Hackers mainly post lists of usernames, passwords, - bank card details, Trojan configuration files, attack outcomes, and various - logs. - default_date: "Warning! Collection is not implemented in the current version" - enable: false - local_custom_tag: null - ttl: 30 - osi/vulnerability: - description: - The Vulnerability collection displays information about vulnerabilities - detected in the software by version. In addition to general information, the - subsection also contains data on existing exploits, with the option to view - links to PoC (Proof-of-Concept) and additional information, or to download the - exploit. - default_date: null - enable: false - local_custom_tag: null - ttl: 30 - suspicious_ip/open_proxy: - description: - The Open proxy collection shows information about lists of proxy - servers that are publicly available on various Internet resources related to - anonymity. In addition, proxy servers may be configured as open proxies intentionally - or as a result of misconfiguration or breaches. - default_date: null - enable: false - local_custom_tag: null - ttl: 15 - suspicious_ip/scanner: - description: - This collection contains data about public and private IP-addresses - that were identified by the TI system. These records can be used to identify - or block connections between the corporate network and servers detected. - default_date: null - enable: false - local_custom_tag: null - ttl: 15 - suspicious_ip/socks_proxy: - description: - The Socks proxy collection shows information about addresses where - malware that turns infected computers into SOCKS proxies has been installed. - Such computers (bots) are rented out and used in various attacks to ensure the - attacker as much anonymity as possible. - default_date: null - enable: false - local_custom_tag: null - ttl: 2 - suspicious_ip/tor_node: - description: - The Tor collection displays data about Tor exit nodes, which are - the final Tor relays in the circuit. The nodes act as an intermediary between - a Tor client and public Internet. - default_date: null - enable: false - local_custom_tag: null - ttl: 30 - suspicious_ip/vpn: - description: - This collection contains information about public and private VPNs - servers that were identified by the TI system. These records can be used to - identify or block connections between the corporate network and servers detected. - default_date: null - enable: false - local_custom_tag: null - ttl: 30 + # === Collections (all disabled by default) === + # --- apt/threat --- + # collections_apt_threat_default_date: + # collections_apt_threat_enable: false + # collections_apt_threat_local_custom_tag: + # collections_apt_threat_ttl: 90 + # collections_apt_threat_use_hunting_rules: false + # --- apt/threat_actor --- + # collections_apt_threat_actor_default_date: + # collections_apt_threat_actor_enable: false + # collections_apt_threat_actor_local_custom_tag: + # collections_apt_threat_actor_ttl: 90 + # --- attacks/ddos --- + # collections_attacks_ddos_default_date: + # collections_attacks_ddos_enable: false + # collections_attacks_ddos_local_custom_tag: + # collections_attacks_ddos_ttl: 30 + # --- attacks/deface --- + # collections_attacks_deface_default_date: + # collections_attacks_deface_enable: false + # collections_attacks_deface_local_custom_tag: + # collections_attacks_deface_ttl: 30 + # --- attacks/phishing_group --- + # collections_attacks_phishing_group_default_date: + # collections_attacks_phishing_group_enable: false + # collections_attacks_phishing_group_local_custom_tag: + # collections_attacks_phishing_group_ttl: 30 + # --- attacks/phishing_kit --- + # collections_attacks_phishing_kit_default_date: + # collections_attacks_phishing_kit_enable: false + # collections_attacks_phishing_kit_local_custom_tag: + # collections_attacks_phishing_kit_ttl: 30 + # --- compromised/access --- + # collections_compromised_access_default_date: + # collections_compromised_access_enable: false + # collections_compromised_access_local_custom_tag: + # collections_compromised_access_ttl: 90 + # --- compromised/account_group --- + # collections_compromised_account_group_default_date: + # collections_compromised_account_group_enable: false + # collections_compromised_account_group_local_custom_tag: + # collections_compromised_account_group_ttl: 90 + # --- compromised/bank_card_group --- + # collections_compromised_bank_card_group_default_date: + # collections_compromised_bank_card_group_enable: false + # collections_compromised_bank_card_group_local_custom_tag: + # collections_compromised_bank_card_group_ttl: 90 + # --- compromised/discord --- + # collections_compromised_discord_default_date: + # collections_compromised_discord_enable: false + # collections_compromised_discord_local_custom_tag: + # collections_compromised_discord_ttl: + # --- compromised/imei --- + # collections_compromised_imei_default_date: + # collections_compromised_imei_enable: false + # collections_compromised_imei_local_custom_tag: + # collections_compromised_imei_ttl: 30 + # --- compromised/masked_card --- + # collections_compromised_masked_card_default_date: + # collections_compromised_masked_card_enable: false + # collections_compromised_masked_card_local_custom_tag: + # collections_compromised_masked_card_ttl: 90 + # --- compromised/messenger --- + # collections_compromised_messenger_default_date: + # collections_compromised_messenger_enable: false + # collections_compromised_messenger_local_custom_tag: + # collections_compromised_messenger_ttl: + # --- compromised/mule --- + # collections_compromised_mule_default_date: + # collections_compromised_mule_enable: false + # collections_compromised_mule_local_custom_tag: + # collections_compromised_mule_ttl: 30 + # --- hi/open_threats --- + # collections_hi_open_threats_default_date: + # collections_hi_open_threats_enable: false + # collections_hi_open_threats_local_custom_tag: + # collections_hi_open_threats_ttl: + # --- hi/threat --- + # collections_hi_threat_default_date: + # collections_hi_threat_enable: false + # collections_hi_threat_local_custom_tag: + # collections_hi_threat_ttl: 90 + # collections_hi_threat_use_hunting_rules: false + # --- hi/threat_actor --- + # collections_hi_threat_actor_default_date: + # collections_hi_threat_actor_enable: false + # collections_hi_threat_actor_local_custom_tag: + # collections_hi_threat_actor_ttl: 90 + # --- ioc/common --- + # collections_ioc_common_default_date: + # collections_ioc_common_enable: false + # collections_ioc_common_local_custom_tag: + # collections_ioc_common_ttl: 90 + # --- malware/cnc --- + # collections_malware_cnc_default_date: + # collections_malware_cnc_enable: false + # collections_malware_cnc_local_custom_tag: + # collections_malware_cnc_ttl: 90 + # --- malware/config --- + # collections_malware_config_default_date: + # collections_malware_config_enable: false + # collections_malware_config_local_custom_tag: + # collections_malware_config_ttl: 30 + # --- malware/malware --- + # collections_malware_malware_default_date: + # collections_malware_malware_enable: false + # collections_malware_malware_local_custom_tag: + # collections_malware_malware_ttl: + # --- malware/signature --- + # collections_malware_signature_default_date: + # collections_malware_signature_enable: false + # collections_malware_signature_local_custom_tag: + # collections_malware_signature_ttl: + # --- malware/yara --- + # collections_malware_yara_default_date: + # collections_malware_yara_enable: false + # collections_malware_yara_local_custom_tag: + # collections_malware_yara_ttl: + # --- osi/git_repository --- + # collections_osi_git_repository_default_date: + # collections_osi_git_repository_enable: false + # collections_osi_git_repository_local_custom_tag: + # collections_osi_git_repository_ttl: 30 + # --- osi/public_leak --- + # collections_osi_public_leak_default_date: + # collections_osi_public_leak_enable: false + # collections_osi_public_leak_local_custom_tag: + # collections_osi_public_leak_ttl: 30 + # --- osi/vulnerability --- + # collections_osi_vulnerability_default_date: + # collections_osi_vulnerability_enable: false + # collections_osi_vulnerability_local_custom_tag: + # collections_osi_vulnerability_ttl: 30 + # --- suspicious_ip/open_proxy --- + # collections_suspicious_ip_open_proxy_default_date: + # collections_suspicious_ip_open_proxy_enable: false + # collections_suspicious_ip_open_proxy_local_custom_tag: + # collections_suspicious_ip_open_proxy_ttl: 15 + # --- suspicious_ip/scanner --- + # collections_suspicious_ip_scanner_default_date: + # collections_suspicious_ip_scanner_enable: false + # collections_suspicious_ip_scanner_local_custom_tag: + # collections_suspicious_ip_scanner_ttl: 15 + # --- suspicious_ip/socks_proxy --- + # collections_suspicious_ip_socks_proxy_default_date: + # collections_suspicious_ip_socks_proxy_enable: false + # collections_suspicious_ip_socks_proxy_local_custom_tag: + # collections_suspicious_ip_socks_proxy_ttl: 2 + # --- suspicious_ip/tor_node --- + # collections_suspicious_ip_tor_node_default_date: + # collections_suspicious_ip_tor_node_enable: false + # collections_suspicious_ip_tor_node_local_custom_tag: + # collections_suspicious_ip_tor_node_ttl: 30 + # --- suspicious_ip/vpn --- + # collections_suspicious_ip_vpn_default_date: + # collections_suspicious_ip_vpn_enable: false + # collections_suspicious_ip_vpn_local_custom_tag: + # collections_suspicious_ip_vpn_ttl: 30 diff --git a/external-import/group-ib/src/settings.py b/external-import/group-ib/src/settings.py new file mode 100644 index 00000000000..f360abb660c --- /dev/null +++ b/external-import/group-ib/src/settings.py @@ -0,0 +1,675 @@ +"""Pydantic settings for the Group-IB connector (manager-supported mode). + +This module mirrors the connector's existing configuration variables as validated +Pydantic settings so the connector becomes manager-supported. The deeply nested +``ti_api`` configuration is represented as flat fields on a single section because +the connectors-sdk settings loader only resolves two-level ``SECTION_FIELD`` env +vars; the original attribute names are preserved (e.g. ``ti_api_collections_ +apt_threat_enable``) so the rest of the connector keeps working unchanged. +""" + +from datetime import timedelta +from typing import Literal + +from connectors_sdk import ( + BaseConfigModel, + BaseConnectorSettings, + BaseExternalImportConnectorConfig, + ListFromString, +) +from pydantic import Field, SecretStr + + +class GroupIBConnectorConfig(BaseExternalImportConnectorConfig): + """Connector section configuration (mirror of the existing ``CONNECTOR_*`` vars).""" + + id: str = Field( + description="A UUID v4 to identify the connector in OpenCTI.", + default="696ac767-c12a-452b-9b77-993e1007eed6", + ) + name: str = Field( + description="The name of the connector.", + default="Group-IB Connector", + ) + scope: ListFromString = Field( + description="The scope of the connector.", + default=[ + "stix2", + "ipv4-addr", + "ipv6-addr", + "vulnerability", + "domain", + "url", + "StixFile", + ], + ) + log_level: Literal["debug", "info", "warn", "warning", "error"] = Field( + description="The minimum level of logs to display.", + default="info", + ) + duration_period: timedelta = Field( + description="The period of time to await between two runs of the connector " + "(ISO-8601 duration format).", + default=timedelta(hours=4), # PT4H + ) + update_existing_data: bool = Field( + description="Whether to update data already ingested into the platform.", + default=True, + ) + + +class GroupIBTIApiConfig(BaseConfigModel): + """Group-IB Threat Intelligence API configuration (mirror of the existing ``TI_API__*`` vars). + + The originally nested ``proxy``, ``extra_settings`` and ``collections`` sub-sections + are flattened into prefixed fields so each value maps to a single env var. + """ + + url: str = Field( + description="Base URL of the Group-IB Threat Intelligence API.", + default="https://tap.group-ib.com/api/v2/", + ) + username: str = Field( + description="Username used to authenticate against the Group-IB TI API.", + ) + token: SecretStr = Field( + description="API token used to authenticate against the Group-IB TI API.", + ) + + # --- Proxy (optional; leave unset to disable) --- + proxy_ip: str | None = Field( + description="Optional proxy ip used to reach the Group-IB TI API.", + default=None, + ) + proxy_port: str | None = Field( + description="Optional proxy port used to reach the Group-IB TI API.", + default=None, + ) + proxy_protocol: str | None = Field( + description="Optional proxy protocol used to reach the Group-IB TI API.", + default=None, + ) + proxy_username: str | None = Field( + description="Optional proxy username used to reach the Group-IB TI API.", + default=None, + ) + proxy_password: SecretStr | None = Field( + description="Optional proxy password used to reach the Group-IB TI API.", + default=None, + ) + + # --- Extra settings --- + extra_settings_ignore_non_indicator_threat_reports: bool = Field( + description="Extra setting 'ignore_non_indicator_threat_reports'.", + default=False, + ) + extra_settings_ignore_non_indicator_threats: bool = Field( + description="Extra setting 'ignore_non_indicator_threats'.", + default=False, + ) + extra_settings_ignore_non_malware_ddos: bool = Field( + description="Extra setting 'ignore_non_malware_ddos'.", + default=True, + ) + extra_settings_intrusion_set_instead_of_threat_actor: bool = Field( + description="Extra setting 'intrusion_set_instead_of_threat_actor'.", + default=False, + ) + extra_settings_schedule_time: str = Field( + description="Extra setting 'schedule_time'.", + default="00:00", + ) + extra_settings_time_output_format: str = Field( + description="Extra setting 'time_output_format'.", + default="%Y-%m-%d %H:%M:%S", + ) + extra_settings_enable_statement_marking: bool = Field( + description="Extra setting 'enable_statement_marking'.", + default=False, + ) + + # --- Collections --- + # apt/threat + collections_apt_threat_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'apt/threat' collection; empty means last 3 days.", + default=None, + ) + collections_apt_threat_enable: bool = Field( + description="Enable ingestion of the 'apt/threat' collection.", + default=False, + ) + collections_apt_threat_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'apt/threat' collection.", + default=None, + ) + collections_apt_threat_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'apt/threat' collection.", + default=90, + ) + collections_apt_threat_use_hunting_rules: bool = Field( + description="Apply Group-IB hunting rules when importing the 'apt/threat' collection.", + default=False, + ) + # apt/threat_actor + collections_apt_threat_actor_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'apt/threat_actor' collection; empty means last 3 days.", + default=None, + ) + collections_apt_threat_actor_enable: bool = Field( + description="Enable ingestion of the 'apt/threat_actor' collection.", + default=False, + ) + collections_apt_threat_actor_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'apt/threat_actor' collection.", + default=None, + ) + collections_apt_threat_actor_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'apt/threat_actor' collection.", + default=90, + ) + # attacks/ddos + collections_attacks_ddos_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'attacks/ddos' collection; empty means last 3 days.", + default=None, + ) + collections_attacks_ddos_enable: bool = Field( + description="Enable ingestion of the 'attacks/ddos' collection.", + default=False, + ) + collections_attacks_ddos_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'attacks/ddos' collection.", + default=None, + ) + collections_attacks_ddos_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'attacks/ddos' collection.", + default=30, + ) + # attacks/deface + collections_attacks_deface_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'attacks/deface' collection; empty means last 3 days.", + default=None, + ) + collections_attacks_deface_enable: bool = Field( + description="Enable ingestion of the 'attacks/deface' collection.", + default=False, + ) + collections_attacks_deface_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'attacks/deface' collection.", + default=None, + ) + collections_attacks_deface_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'attacks/deface' collection.", + default=30, + ) + # attacks/phishing_group + collections_attacks_phishing_group_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'attacks/phishing_group' collection; empty means last 3 days.", + default=None, + ) + collections_attacks_phishing_group_enable: bool = Field( + description="Enable ingestion of the 'attacks/phishing_group' collection.", + default=False, + ) + collections_attacks_phishing_group_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'attacks/phishing_group' collection.", + default=None, + ) + collections_attacks_phishing_group_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'attacks/phishing_group' collection.", + default=30, + ) + # attacks/phishing_kit + collections_attacks_phishing_kit_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'attacks/phishing_kit' collection; empty means last 3 days.", + default=None, + ) + collections_attacks_phishing_kit_enable: bool = Field( + description="Enable ingestion of the 'attacks/phishing_kit' collection.", + default=False, + ) + collections_attacks_phishing_kit_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'attacks/phishing_kit' collection.", + default=None, + ) + collections_attacks_phishing_kit_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'attacks/phishing_kit' collection.", + default=30, + ) + # compromised/access + collections_compromised_access_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/access' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_access_enable: bool = Field( + description="Enable ingestion of the 'compromised/access' collection.", + default=False, + ) + collections_compromised_access_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/access' collection.", + default=None, + ) + collections_compromised_access_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/access' collection.", + default=90, + ) + # compromised/account_group + collections_compromised_account_group_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/account_group' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_account_group_enable: bool = Field( + description="Enable ingestion of the 'compromised/account_group' collection.", + default=False, + ) + collections_compromised_account_group_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/account_group' collection.", + default=None, + ) + collections_compromised_account_group_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/account_group' collection.", + default=90, + ) + # compromised/bank_card_group + collections_compromised_bank_card_group_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/bank_card_group' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_bank_card_group_enable: bool = Field( + description="Enable ingestion of the 'compromised/bank_card_group' collection.", + default=False, + ) + collections_compromised_bank_card_group_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/bank_card_group' collection.", + default=None, + ) + collections_compromised_bank_card_group_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/bank_card_group' collection.", + default=90, + ) + # compromised/discord + collections_compromised_discord_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/discord' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_discord_enable: bool = Field( + description="Enable ingestion of the 'compromised/discord' collection.", + default=False, + ) + collections_compromised_discord_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/discord' collection.", + default=None, + ) + collections_compromised_discord_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/discord' collection.", + default=None, + ) + # compromised/imei + collections_compromised_imei_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/imei' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_imei_enable: bool = Field( + description="Enable ingestion of the 'compromised/imei' collection.", + default=False, + ) + collections_compromised_imei_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/imei' collection.", + default=None, + ) + collections_compromised_imei_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/imei' collection.", + default=30, + ) + # compromised/masked_card + collections_compromised_masked_card_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/masked_card' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_masked_card_enable: bool = Field( + description="Enable ingestion of the 'compromised/masked_card' collection.", + default=False, + ) + collections_compromised_masked_card_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/masked_card' collection.", + default=None, + ) + collections_compromised_masked_card_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/masked_card' collection.", + default=90, + ) + # compromised/messenger + collections_compromised_messenger_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/messenger' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_messenger_enable: bool = Field( + description="Enable ingestion of the 'compromised/messenger' collection.", + default=False, + ) + collections_compromised_messenger_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/messenger' collection.", + default=None, + ) + collections_compromised_messenger_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/messenger' collection.", + default=None, + ) + # compromised/mule + collections_compromised_mule_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'compromised/mule' collection; empty means last 3 days.", + default=None, + ) + collections_compromised_mule_enable: bool = Field( + description="Enable ingestion of the 'compromised/mule' collection.", + default=False, + ) + collections_compromised_mule_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'compromised/mule' collection.", + default=None, + ) + collections_compromised_mule_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'compromised/mule' collection.", + default=30, + ) + # hi/open_threats + collections_hi_open_threats_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'hi/open_threats' collection; empty means last 3 days.", + default=None, + ) + collections_hi_open_threats_enable: bool = Field( + description="Enable ingestion of the 'hi/open_threats' collection.", + default=False, + ) + collections_hi_open_threats_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'hi/open_threats' collection.", + default=None, + ) + collections_hi_open_threats_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'hi/open_threats' collection.", + default=None, + ) + # hi/threat + collections_hi_threat_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'hi/threat' collection; empty means last 3 days.", + default=None, + ) + collections_hi_threat_enable: bool = Field( + description="Enable ingestion of the 'hi/threat' collection.", + default=False, + ) + collections_hi_threat_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'hi/threat' collection.", + default=None, + ) + collections_hi_threat_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'hi/threat' collection.", + default=90, + ) + collections_hi_threat_use_hunting_rules: bool = Field( + description="Apply Group-IB hunting rules when importing the 'hi/threat' collection.", + default=False, + ) + # hi/threat_actor + collections_hi_threat_actor_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'hi/threat_actor' collection; empty means last 3 days.", + default=None, + ) + collections_hi_threat_actor_enable: bool = Field( + description="Enable ingestion of the 'hi/threat_actor' collection.", + default=False, + ) + collections_hi_threat_actor_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'hi/threat_actor' collection.", + default=None, + ) + collections_hi_threat_actor_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'hi/threat_actor' collection.", + default=90, + ) + # ioc/common + collections_ioc_common_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'ioc/common' collection; empty means last 3 days.", + default=None, + ) + collections_ioc_common_enable: bool = Field( + description="Enable ingestion of the 'ioc/common' collection.", + default=False, + ) + collections_ioc_common_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'ioc/common' collection.", + default=None, + ) + collections_ioc_common_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'ioc/common' collection.", + default=90, + ) + # malware/cnc + collections_malware_cnc_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'malware/cnc' collection; empty means last 3 days.", + default=None, + ) + collections_malware_cnc_enable: bool = Field( + description="Enable ingestion of the 'malware/cnc' collection.", + default=False, + ) + collections_malware_cnc_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'malware/cnc' collection.", + default=None, + ) + collections_malware_cnc_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'malware/cnc' collection.", + default=90, + ) + # malware/config + collections_malware_config_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'malware/config' collection; empty means last 3 days.", + default=None, + ) + collections_malware_config_enable: bool = Field( + description="Enable ingestion of the 'malware/config' collection.", + default=False, + ) + collections_malware_config_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'malware/config' collection.", + default=None, + ) + collections_malware_config_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'malware/config' collection.", + default=30, + ) + # malware/malware + collections_malware_malware_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'malware/malware' collection; empty means last 3 days.", + default=None, + ) + collections_malware_malware_enable: bool = Field( + description="Enable ingestion of the 'malware/malware' collection.", + default=False, + ) + collections_malware_malware_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'malware/malware' collection.", + default=None, + ) + collections_malware_malware_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'malware/malware' collection.", + default=None, + ) + # malware/signature + collections_malware_signature_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'malware/signature' collection; empty means last 3 days.", + default=None, + ) + collections_malware_signature_enable: bool = Field( + description="Enable ingestion of the 'malware/signature' collection.", + default=False, + ) + collections_malware_signature_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'malware/signature' collection.", + default=None, + ) + collections_malware_signature_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'malware/signature' collection.", + default=None, + ) + # malware/yara + collections_malware_yara_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'malware/yara' collection; empty means last 3 days.", + default=None, + ) + collections_malware_yara_enable: bool = Field( + description="Enable ingestion of the 'malware/yara' collection.", + default=False, + ) + collections_malware_yara_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'malware/yara' collection.", + default=None, + ) + collections_malware_yara_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'malware/yara' collection.", + default=None, + ) + # osi/git_repository + collections_osi_git_repository_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'osi/git_repository' collection; empty means last 3 days.", + default=None, + ) + collections_osi_git_repository_enable: bool = Field( + description="Enable ingestion of the 'osi/git_repository' collection.", + default=False, + ) + collections_osi_git_repository_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'osi/git_repository' collection.", + default=None, + ) + collections_osi_git_repository_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'osi/git_repository' collection.", + default=30, + ) + # osi/public_leak + collections_osi_public_leak_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'osi/public_leak' collection; empty means last 3 days.", + default=None, + ) + collections_osi_public_leak_enable: bool = Field( + description="Enable ingestion of the 'osi/public_leak' collection.", + default=False, + ) + collections_osi_public_leak_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'osi/public_leak' collection.", + default=None, + ) + collections_osi_public_leak_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'osi/public_leak' collection.", + default=30, + ) + # osi/vulnerability + collections_osi_vulnerability_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'osi/vulnerability' collection; empty means last 3 days.", + default=None, + ) + collections_osi_vulnerability_enable: bool = Field( + description="Enable ingestion of the 'osi/vulnerability' collection.", + default=False, + ) + collections_osi_vulnerability_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'osi/vulnerability' collection.", + default=None, + ) + collections_osi_vulnerability_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'osi/vulnerability' collection.", + default=30, + ) + # suspicious_ip/open_proxy + collections_suspicious_ip_open_proxy_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/open_proxy' collection; empty means last 3 days.", + default=None, + ) + collections_suspicious_ip_open_proxy_enable: bool = Field( + description="Enable ingestion of the 'suspicious_ip/open_proxy' collection.", + default=False, + ) + collections_suspicious_ip_open_proxy_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'suspicious_ip/open_proxy' collection.", + default=None, + ) + collections_suspicious_ip_open_proxy_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'suspicious_ip/open_proxy' collection.", + default=15, + ) + # suspicious_ip/scanner + collections_suspicious_ip_scanner_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/scanner' collection; empty means last 3 days.", + default=None, + ) + collections_suspicious_ip_scanner_enable: bool = Field( + description="Enable ingestion of the 'suspicious_ip/scanner' collection.", + default=False, + ) + collections_suspicious_ip_scanner_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'suspicious_ip/scanner' collection.", + default=None, + ) + collections_suspicious_ip_scanner_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'suspicious_ip/scanner' collection.", + default=15, + ) + # suspicious_ip/socks_proxy + collections_suspicious_ip_socks_proxy_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/socks_proxy' collection; empty means last 3 days.", + default=None, + ) + collections_suspicious_ip_socks_proxy_enable: bool = Field( + description="Enable ingestion of the 'suspicious_ip/socks_proxy' collection.", + default=False, + ) + collections_suspicious_ip_socks_proxy_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'suspicious_ip/socks_proxy' collection.", + default=None, + ) + collections_suspicious_ip_socks_proxy_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'suspicious_ip/socks_proxy' collection.", + default=2, + ) + # suspicious_ip/tor_node + collections_suspicious_ip_tor_node_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/tor_node' collection; empty means last 3 days.", + default=None, + ) + collections_suspicious_ip_tor_node_enable: bool = Field( + description="Enable ingestion of the 'suspicious_ip/tor_node' collection.", + default=False, + ) + collections_suspicious_ip_tor_node_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'suspicious_ip/tor_node' collection.", + default=None, + ) + collections_suspicious_ip_tor_node_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'suspicious_ip/tor_node' collection.", + default=30, + ) + # suspicious_ip/vpn + collections_suspicious_ip_vpn_default_date: str | None = Field( + description="Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/vpn' collection; empty means last 3 days.", + default=None, + ) + collections_suspicious_ip_vpn_enable: bool = Field( + description="Enable ingestion of the 'suspicious_ip/vpn' collection.", + default=False, + ) + collections_suspicious_ip_vpn_local_custom_tag: str | None = Field( + description="Optional custom label added to objects from the 'suspicious_ip/vpn' collection.", + default=None, + ) + collections_suspicious_ip_vpn_ttl: int | None = Field( + description="Time-to-live (in days) for indicators from the 'suspicious_ip/vpn' collection.", + default=30, + ) + + +class ConnectorSettings(BaseConnectorSettings): + """Global settings for the Group-IB connector.""" + + connector: GroupIBConnectorConfig = Field( + default_factory=GroupIBConnectorConfig, + ) + ti_api: GroupIBTIApiConfig = Field(default_factory=GroupIBTIApiConfig) From 3261bb4aeeb42b4b4ef4915889b4339788b0c515 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Tue, 18 Aug 2026 16:57:04 +0200 Subject: [PATCH 3/9] feat(group-ib): use Pydantic settings in existing connector code (#7282) --- external-import/group-ib/src/config.py | 125 ++++++------------ .../group-ib/src/lib/external_import.py | 2 +- 2 files changed, 43 insertions(+), 84 deletions(-) diff --git a/external-import/group-ib/src/config.py b/external-import/group-ib/src/config.py index 38170933271..85f70414792 100644 --- a/external-import/group-ib/src/config.py +++ b/external-import/group-ib/src/config.py @@ -1,108 +1,67 @@ import os -from pathlib import Path from typing import Any +import isodate import pycti -import yaml from cyberintegrations.utils import FileHandler -from dotenv import load_dotenv -from pycti import get_config_variable +from pydantic import SecretStr +from settings import ConnectorSettings from stix2 import TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, MarkingDefinition from stix2.v21.vocab import MALWARE_TYPE class ConfigConnector: - def __init__(self): """ - Initialize the connector with necessary configurations + Initialize the connector with necessary configurations. + + Configuration is loaded and validated through the Pydantic + ``ConnectorSettings`` model. The validated values are then exposed using + the connector's historical flat attribute names (e.g. + ``ti_api_collections_apt_threat_enable``, ``connector_duration_period``) + so the rest of the connector keeps working unchanged. """ - self.load = self._load_config() - self.env_keys = self._load_env_keys() - self._initialize_configurations() + self.settings = ConnectorSettings() + self._expose_settings_as_attributes() self.collection_mapping_config = FileHandler().read_json_config( self.CONFIG_JSON ) - def _load_config(self) -> dict: - """ - Loads the configuration from `config.yml`. If `config.yml` does not exist, returns an empty dictionary. - """ - config_dir = Path(__file__).parents[1].joinpath("src") - config_file_path = config_dir.joinpath("config.yml") - - if config_file_path.is_file(): - with open(config_file_path, "r", encoding="utf-8") as file: - return yaml.load(file, Loader=yaml.FullLoader) - - return {} - - def _load_env_keys(self) -> list[str]: - load_dotenv() - return os.environ.keys() + @staticmethod + def _unwrap(value: Any) -> Any: + """Return the plain value of a ``SecretStr`` (or the value unchanged).""" + if isinstance(value, SecretStr): + return value.get_secret_value() + return value - def _extract_config_keys(self, data, parent_keys=None): - if parent_keys is None: - parent_keys = [] - - keys_list = [] - if isinstance(data, dict): - for key, value in data.items(): - new_keys = parent_keys + [key] - if isinstance(value, dict): - keys_list.extend(self._extract_config_keys(value, new_keys)) - else: - keys_list.append(new_keys) - return keys_list - - def _converting_keys_to_environment_keys(self, key): - if not key or not isinstance(key, list): - return None - - key = [str(k).upper().replace("-", "_") for k in key] + def _expose_settings_as_attributes(self) -> None: + """ + Expose validated settings using the connector's historical attribute names. - if key[0] in ["OPENCTI", "CONNECTOR"]: - return "_".join(key) + The rest of the connector reads flat attributes such as + ``ti_api_proxy_ip`` or ``connector_duration_period``; they are derived + here from the nested Pydantic settings so no downstream code needs to + change. + """ + for field_name in type(self.settings.opencti).model_fields: + value = self._unwrap(getattr(self.settings.opencti, field_name)) + setattr(self, f"opencti_{field_name}", value) - if key[0] == "TI_API": - if len(key) > 1 and key[1] == "COLLECTIONS": - modified_key = key[2:] - modified_key = [part.replace("/", "_") for part in modified_key] - return ( - f"{key[0]}__{key[1]}__{'__'.join(modified_key)}" - if modified_key - else f"{key[0]}__{key[1]}" - ) - return "__".join(key) + for field_name in type(self.settings.connector).model_fields: + value = getattr(self.settings.connector, field_name) + if field_name == "duration_period": + # Preserve the historical ISO-8601 string form used by the + # scheduler / interval validation helper. + value = isodate.duration_isoformat(value) + setattr(self, f"connector_{field_name}", self._unwrap(value)) - return "_".join(key) + for field_name in type(self.settings.ti_api).model_fields: + value = self._unwrap(getattr(self.settings.ti_api, field_name)) + setattr(self, f"ti_api_{field_name}", value) - def _initialize_configurations(self) -> None: - """ - Connector configuration variables - :return: None - """ - if self.load: - for key in self._extract_config_keys(self.load): - if len(key) > 2 and key[1] == "collections": - key[2] = key[2].replace("/", "_") - env_var = self._converting_keys_to_environment_keys(key) - attr_name = "__".join(key).lower().replace("__", "_") - attr_value = get_config_variable( - env_var=env_var, - yaml_path=key, - config=self.load, - ) - setattr(self, attr_name, attr_value) - else: - for env_key in self.env_keys: - attr_name = env_key.lower().replace("__", "_") - attr_value = get_config_variable( - env_var=env_key, - yaml_path=None, - config=None, - ) - setattr(self, attr_name, attr_value) + def to_helper_config(self) -> dict: + """Return a config dict suitable for ``pycti.OpenCTIConnectorHelper``.""" + return self.settings.to_helper_config() def get_collection_settings(self, collection, setting_name) -> Any: collection_attr_name = f"ti_api_collections_{collection}_{setting_name}" diff --git a/external-import/group-ib/src/lib/external_import.py b/external-import/group-ib/src/lib/external_import.py index 2e5dec5fc94..32ecdc24840 100644 --- a/external-import/group-ib/src/lib/external_import.py +++ b/external-import/group-ib/src/lib/external_import.py @@ -67,7 +67,7 @@ class ExternalImportConnector: def __init__(self): self.cfg = ConfigConnector() - self.helper = OpenCTIConnectorHelper({}) + self.helper = OpenCTIConnectorHelper(config=self.cfg.to_helper_config()) self.helper.connector_logger.info("Initializing ExternalImportConnector") self.helper.connector_logger.debug( "Initialized ConfigConnector, OpenCTIConnectorHelper" From 8936903d703f15ff048ae92b5b5edb3e30ca8775 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Tue, 18 Aug 2026 16:58:52 +0200 Subject: [PATCH 4/9] feat(group-ib): set manager_supported to true in connector manifest (#7282) --- external-import/group-ib/__metadata__/connector_manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external-import/group-ib/__metadata__/connector_manifest.json b/external-import/group-ib/__metadata__/connector_manifest.json index 4c102e935d0..6283d5ef733 100644 --- a/external-import/group-ib/__metadata__/connector_manifest.json +++ b/external-import/group-ib/__metadata__/connector_manifest.json @@ -19,7 +19,7 @@ "support_version": ">=6.2.12", "subscription_link": "https://www.group-ib.com", "source_code": "https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/group-ib", - "manager_supported": false, + "manager_supported": true, "container_version": "rolling", "container_image": "opencti/connector-group-ib", "container_type": "EXTERNAL_IMPORT" From afaedb51ffaadd0b1178b59a6a9a6e0ba1d6ab8b Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Tue, 18 Aug 2026 17:00:36 +0200 Subject: [PATCH 5/9] feat(group-ib): generate connector config schema for manager-supported mode (#7282) --- external-import/group-ib/README.md | 38 +- .../__metadata__/CONNECTOR_CONFIG_DOC.md | 157 ++++ .../__metadata__/connector_config_schema.json | 783 ++++++++++++++++++ 3 files changed, 943 insertions(+), 35 deletions(-) create mode 100644 external-import/group-ib/__metadata__/CONNECTOR_CONFIG_DOC.md create mode 100644 external-import/group-ib/__metadata__/connector_config_schema.json diff --git a/external-import/group-ib/README.md b/external-import/group-ib/README.md index 5dcde4a1b25..f5432f994aa 100644 --- a/external-import/group-ib/README.md +++ b/external-import/group-ib/README.md @@ -14,9 +14,6 @@ The Group-IB connector imports threat intelligence from Group-IB's Threat Intell - [Installation](#installation) - [Requirements](#requirements) - [Configuration variables](#configuration-variables) - - [OpenCTI environment variables](#opencti-environment-variables) - - [Base connector environment variables](#base-connector-environment-variables) - - [Connector extra parameters environment variables](#connector-extra-parameters-environment-variables) - [Deployment](#deployment) - [Docker Deployment](#docker-deployment) - [Manual Deployment](#manual-deployment) @@ -43,39 +40,10 @@ To use the integration, please ensure that you have an active Threat Intelligenc ## Configuration variables -There are a number of configuration options, which are set either in `docker-compose.yml` (for Docker) or in `.env` file (for manual deployment). +Find all the configuration variables available here: [Connector Configurations](./__metadata__/CONNECTOR_CONFIG_DOC.md) -> **Note**: Currently the connector cannot run with `config.yml` file, only with `.env` file because of ConnectorHelper instantiation and proxy settings code. - -### OpenCTI environment variables - -| Parameter | config.yml | Docker environment variable | Mandatory | Description | -|---------------|------------|-----------------------------|-----------|------------------------------------------------------| -| OpenCTI URL | url | `OPENCTI_URL` | Yes | The URL of the OpenCTI platform. | -| OpenCTI Token | token | `OPENCTI_TOKEN` | Yes | The default admin token set in the OpenCTI platform. | - -### Base connector environment variables - -| Parameter | config.yml | Docker environment variable | Default | Mandatory | Description | -|-----------------|-----------------|-------------------------------|---------|-----------|--------------------------------------------------------------------------| -| Connector ID | id | `CONNECTOR_ID` | | Yes | A unique `UUIDv4` identifier for this connector instance. | -| Connector Name | name | `CONNECTOR_NAME` | | Yes | Name of the connector. | -| Connector Scope | scope | `CONNECTOR_SCOPE` | | Yes | The scope or type of data the connector is importing. | -| Log Level | log_level | `CONNECTOR_LOG_LEVEL` | info | No | Determines the verbosity of logs: `debug`, `info`, `warn`, or `error`. | -| Duration Period | duration_period | `CONNECTOR_DURATION_PERIOD` | | Yes | Time interval between runs in ISO 8601 format (e.g., `PT3M`, `P1D`). | - -### Connector extra parameters environment variables - -| Parameter | config.yml | Docker environment variable | Default | Mandatory | Description | -|------------------|--------------------|-----------------------------|---------|-----------|--------------------------------------------------| -| TI API URL | ti_api.url | `TI_API__URL` | | Yes | Group-IB Threat Intelligence API URL. | -| TI API Username | ti_api.username | `TI_API__USERNAME` | | Yes | Threat Intelligence Portal profile email. | -| TI API Token | ti_api.token | `TI_API__TOKEN` | | Yes | Threat Intelligence API Token. | -| Proxy IP | proxy.ip | `PROXY_IP` | | No | Proxy server IP address. | -| Proxy Port | proxy.port | `PROXY_PORT` | | No | Proxy server port. | -| Proxy Protocol | proxy.protocol | `PROXY_PROTOCOL` | | No | Proxy protocol (http/https). | -| Proxy Username | proxy.username | `PROXY_USERNAME` | | No | Proxy authentication username. | -| Proxy Password | proxy.password | `PROXY_PASSWORD` | | No | Proxy authentication password. | +_The `opencti` and `connector` options in the `docker-compose.yml` and `config.yml` are the same as for any other connector. +For more information regarding variables, please refer to [OpenCTI's documentation on connectors](https://docs.opencti.io/latest/deployment/connectors/)._ ## Deployment diff --git a/external-import/group-ib/__metadata__/CONNECTOR_CONFIG_DOC.md b/external-import/group-ib/__metadata__/CONNECTOR_CONFIG_DOC.md new file mode 100644 index 00000000000..0e018c19f35 --- /dev/null +++ b/external-import/group-ib/__metadata__/CONNECTOR_CONFIG_DOC.md @@ -0,0 +1,157 @@ +# 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. | +| TI_API_USERNAME | `string` | ✅ | string | | Username used to authenticate against the Group-IB TI API. | +| TI_API_TOKEN | `string` | ✅ | Format: [`password`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | | API token used to authenticate against the Group-IB TI API. | +| CONNECTOR_NAME | `string` | | string | `"Group-IB Connector"` | The name of the connector. | +| CONNECTOR_SCOPE | `array` | | string | `["stix2", "ipv4-addr", "ipv6-addr", "vulnerability", "domain", "url", "StixFile"]` | The scope of the connector. | +| CONNECTOR_LOG_LEVEL | `string` | | `debug` `info` `warn` `warning` `error` | `"info"` | The minimum level of logs to display. | +| CONNECTOR_TYPE | `const` | | `EXTERNAL_IMPORT` | `"EXTERNAL_IMPORT"` | | +| CONNECTOR_DURATION_PERIOD | `string` | | Format: [`duration`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | `"PT4H"` | The period of time to await between two runs of the connector (ISO-8601 duration format). | +| CONNECTOR_UPDATE_EXISTING_DATA | `boolean` | | boolean | `true` | Whether to update data already ingested into the platform. | +| TI_API_URL | `string` | | string | `"https://tap.group-ib.com/api/v2/"` | Base URL of the Group-IB Threat Intelligence API. | +| TI_API_PROXY_IP | `string` | | string | `null` | Optional proxy ip used to reach the Group-IB TI API. | +| TI_API_PROXY_PORT | `string` | | string | `null` | Optional proxy port used to reach the Group-IB TI API. | +| TI_API_PROXY_PROTOCOL | `string` | | string | `null` | Optional proxy protocol used to reach the Group-IB TI API. | +| TI_API_PROXY_USERNAME | `string` | | string | `null` | Optional proxy username used to reach the Group-IB TI API. | +| TI_API_PROXY_PASSWORD | `string` | | Format: [`password`](https://json-schema.org/understanding-json-schema/reference/string#built-in-formats) | `null` | Optional proxy password used to reach the Group-IB TI API. | +| TI_API_EXTRA_SETTINGS_IGNORE_NON_INDICATOR_THREAT_REPORTS | `boolean` | | boolean | `false` | Extra setting 'ignore_non_indicator_threat_reports'. | +| TI_API_EXTRA_SETTINGS_IGNORE_NON_INDICATOR_THREATS | `boolean` | | boolean | `false` | Extra setting 'ignore_non_indicator_threats'. | +| TI_API_EXTRA_SETTINGS_IGNORE_NON_MALWARE_DDOS | `boolean` | | boolean | `true` | Extra setting 'ignore_non_malware_ddos'. | +| TI_API_EXTRA_SETTINGS_INTRUSION_SET_INSTEAD_OF_THREAT_ACTOR | `boolean` | | boolean | `false` | Extra setting 'intrusion_set_instead_of_threat_actor'. | +| TI_API_EXTRA_SETTINGS_SCHEDULE_TIME | `string` | | string | `"00:00"` | Extra setting 'schedule_time'. | +| TI_API_EXTRA_SETTINGS_TIME_OUTPUT_FORMAT | `string` | | string | `"%Y-%m-%d %H:%M:%S"` | Extra setting 'time_output_format'. | +| TI_API_EXTRA_SETTINGS_ENABLE_STATEMENT_MARKING | `boolean` | | boolean | `false` | Extra setting 'enable_statement_marking'. | +| TI_API_COLLECTIONS_APT_THREAT_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'apt/threat' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_APT_THREAT_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'apt/threat' collection. | +| TI_API_COLLECTIONS_APT_THREAT_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'apt/threat' collection. | +| TI_API_COLLECTIONS_APT_THREAT_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'apt/threat' collection. | +| TI_API_COLLECTIONS_APT_THREAT_USE_HUNTING_RULES | `boolean` | | boolean | `false` | Apply Group-IB hunting rules when importing the 'apt/threat' collection. | +| TI_API_COLLECTIONS_APT_THREAT_ACTOR_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'apt/threat_actor' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_APT_THREAT_ACTOR_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'apt/threat_actor' collection. | +| TI_API_COLLECTIONS_APT_THREAT_ACTOR_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'apt/threat_actor' collection. | +| TI_API_COLLECTIONS_APT_THREAT_ACTOR_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'apt/threat_actor' collection. | +| TI_API_COLLECTIONS_ATTACKS_DDOS_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'attacks/ddos' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_ATTACKS_DDOS_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'attacks/ddos' collection. | +| TI_API_COLLECTIONS_ATTACKS_DDOS_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'attacks/ddos' collection. | +| TI_API_COLLECTIONS_ATTACKS_DDOS_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'attacks/ddos' collection. | +| TI_API_COLLECTIONS_ATTACKS_DEFACE_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'attacks/deface' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_ATTACKS_DEFACE_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'attacks/deface' collection. | +| TI_API_COLLECTIONS_ATTACKS_DEFACE_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'attacks/deface' collection. | +| TI_API_COLLECTIONS_ATTACKS_DEFACE_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'attacks/deface' collection. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'attacks/phishing_group' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'attacks/phishing_group' collection. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'attacks/phishing_group' collection. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'attacks/phishing_group' collection. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'attacks/phishing_kit' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'attacks/phishing_kit' collection. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'attacks/phishing_kit' collection. | +| TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'attacks/phishing_kit' collection. | +| TI_API_COLLECTIONS_COMPROMISED_ACCESS_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/access' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_ACCESS_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/access' collection. | +| TI_API_COLLECTIONS_COMPROMISED_ACCESS_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/access' collection. | +| TI_API_COLLECTIONS_COMPROMISED_ACCESS_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'compromised/access' collection. | +| TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/account_group' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/account_group' collection. | +| TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/account_group' collection. | +| TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'compromised/account_group' collection. | +| TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/bank_card_group' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/bank_card_group' collection. | +| TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/bank_card_group' collection. | +| TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'compromised/bank_card_group' collection. | +| TI_API_COLLECTIONS_COMPROMISED_DISCORD_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/discord' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_DISCORD_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/discord' collection. | +| TI_API_COLLECTIONS_COMPROMISED_DISCORD_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/discord' collection. | +| TI_API_COLLECTIONS_COMPROMISED_DISCORD_TTL | `integer` | | integer | `null` | Time-to-live (in days) for indicators from the 'compromised/discord' collection. | +| TI_API_COLLECTIONS_COMPROMISED_IMEI_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/imei' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_IMEI_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/imei' collection. | +| TI_API_COLLECTIONS_COMPROMISED_IMEI_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/imei' collection. | +| TI_API_COLLECTIONS_COMPROMISED_IMEI_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'compromised/imei' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/masked_card' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/masked_card' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/masked_card' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'compromised/masked_card' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MESSENGER_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/messenger' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_MESSENGER_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/messenger' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MESSENGER_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/messenger' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MESSENGER_TTL | `integer` | | integer | `null` | Time-to-live (in days) for indicators from the 'compromised/messenger' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MULE_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'compromised/mule' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_COMPROMISED_MULE_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'compromised/mule' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MULE_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'compromised/mule' collection. | +| TI_API_COLLECTIONS_COMPROMISED_MULE_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'compromised/mule' collection. | +| TI_API_COLLECTIONS_HI_OPEN_THREATS_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'hi/open_threats' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_HI_OPEN_THREATS_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'hi/open_threats' collection. | +| TI_API_COLLECTIONS_HI_OPEN_THREATS_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'hi/open_threats' collection. | +| TI_API_COLLECTIONS_HI_OPEN_THREATS_TTL | `integer` | | integer | `null` | Time-to-live (in days) for indicators from the 'hi/open_threats' collection. | +| TI_API_COLLECTIONS_HI_THREAT_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'hi/threat' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_HI_THREAT_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'hi/threat' collection. | +| TI_API_COLLECTIONS_HI_THREAT_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'hi/threat' collection. | +| TI_API_COLLECTIONS_HI_THREAT_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'hi/threat' collection. | +| TI_API_COLLECTIONS_HI_THREAT_USE_HUNTING_RULES | `boolean` | | boolean | `false` | Apply Group-IB hunting rules when importing the 'hi/threat' collection. | +| TI_API_COLLECTIONS_HI_THREAT_ACTOR_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'hi/threat_actor' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_HI_THREAT_ACTOR_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'hi/threat_actor' collection. | +| TI_API_COLLECTIONS_HI_THREAT_ACTOR_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'hi/threat_actor' collection. | +| TI_API_COLLECTIONS_HI_THREAT_ACTOR_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'hi/threat_actor' collection. | +| TI_API_COLLECTIONS_IOC_COMMON_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'ioc/common' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_IOC_COMMON_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'ioc/common' collection. | +| TI_API_COLLECTIONS_IOC_COMMON_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'ioc/common' collection. | +| TI_API_COLLECTIONS_IOC_COMMON_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'ioc/common' collection. | +| TI_API_COLLECTIONS_MALWARE_CNC_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'malware/cnc' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_MALWARE_CNC_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'malware/cnc' collection. | +| TI_API_COLLECTIONS_MALWARE_CNC_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'malware/cnc' collection. | +| TI_API_COLLECTIONS_MALWARE_CNC_TTL | `integer` | | integer | `90` | Time-to-live (in days) for indicators from the 'malware/cnc' collection. | +| TI_API_COLLECTIONS_MALWARE_CONFIG_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'malware/config' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_MALWARE_CONFIG_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'malware/config' collection. | +| TI_API_COLLECTIONS_MALWARE_CONFIG_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'malware/config' collection. | +| TI_API_COLLECTIONS_MALWARE_CONFIG_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'malware/config' collection. | +| TI_API_COLLECTIONS_MALWARE_MALWARE_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'malware/malware' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_MALWARE_MALWARE_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'malware/malware' collection. | +| TI_API_COLLECTIONS_MALWARE_MALWARE_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'malware/malware' collection. | +| TI_API_COLLECTIONS_MALWARE_MALWARE_TTL | `integer` | | integer | `null` | Time-to-live (in days) for indicators from the 'malware/malware' collection. | +| TI_API_COLLECTIONS_MALWARE_SIGNATURE_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'malware/signature' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_MALWARE_SIGNATURE_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'malware/signature' collection. | +| TI_API_COLLECTIONS_MALWARE_SIGNATURE_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'malware/signature' collection. | +| TI_API_COLLECTIONS_MALWARE_SIGNATURE_TTL | `integer` | | integer | `null` | Time-to-live (in days) for indicators from the 'malware/signature' collection. | +| TI_API_COLLECTIONS_MALWARE_YARA_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'malware/yara' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_MALWARE_YARA_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'malware/yara' collection. | +| TI_API_COLLECTIONS_MALWARE_YARA_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'malware/yara' collection. | +| TI_API_COLLECTIONS_MALWARE_YARA_TTL | `integer` | | integer | `null` | Time-to-live (in days) for indicators from the 'malware/yara' collection. | +| TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'osi/git_repository' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'osi/git_repository' collection. | +| TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'osi/git_repository' collection. | +| TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'osi/git_repository' collection. | +| TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'osi/public_leak' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'osi/public_leak' collection. | +| TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'osi/public_leak' collection. | +| TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'osi/public_leak' collection. | +| TI_API_COLLECTIONS_OSI_VULNERABILITY_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'osi/vulnerability' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_OSI_VULNERABILITY_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'osi/vulnerability' collection. | +| TI_API_COLLECTIONS_OSI_VULNERABILITY_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'osi/vulnerability' collection. | +| TI_API_COLLECTIONS_OSI_VULNERABILITY_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'osi/vulnerability' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/open_proxy' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'suspicious_ip/open_proxy' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'suspicious_ip/open_proxy' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_TTL | `integer` | | integer | `15` | Time-to-live (in days) for indicators from the 'suspicious_ip/open_proxy' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/scanner' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'suspicious_ip/scanner' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'suspicious_ip/scanner' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_TTL | `integer` | | integer | `15` | Time-to-live (in days) for indicators from the 'suspicious_ip/scanner' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/socks_proxy' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'suspicious_ip/socks_proxy' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'suspicious_ip/socks_proxy' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_TTL | `integer` | | integer | `2` | Time-to-live (in days) for indicators from the 'suspicious_ip/socks_proxy' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/tor_node' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'suspicious_ip/tor_node' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'suspicious_ip/tor_node' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'suspicious_ip/tor_node' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_DEFAULT_DATE | `string` | | string | `null` | Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/vpn' collection; empty means last 3 days. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_ENABLE | `boolean` | | boolean | `false` | Enable ingestion of the 'suspicious_ip/vpn' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_LOCAL_CUSTOM_TAG | `string` | | string | `null` | Optional custom label added to objects from the 'suspicious_ip/vpn' collection. | +| TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_TTL | `integer` | | integer | `30` | Time-to-live (in days) for indicators from the 'suspicious_ip/vpn' collection. | diff --git a/external-import/group-ib/__metadata__/connector_config_schema.json b/external-import/group-ib/__metadata__/connector_config_schema.json new file mode 100644 index 00000000000..c118f794312 --- /dev/null +++ b/external-import/group-ib/__metadata__/connector_config_schema.json @@ -0,0 +1,783 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.filigran.io/connectors/group-ib_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": "Group-IB Connector", + "description": "The name of the connector.", + "type": "string" + }, + "CONNECTOR_SCOPE": { + "default": [ + "stix2", + "ipv4-addr", + "ipv6-addr", + "vulnerability", + "domain", + "url", + "StixFile" + ], + "description": "The scope of the connector.", + "items": { + "type": "string" + }, + "type": "array" + }, + "CONNECTOR_LOG_LEVEL": { + "default": "info", + "description": "The minimum level of logs to display.", + "enum": [ + "debug", + "info", + "warn", + "warning", + "error" + ], + "type": "string" + }, + "CONNECTOR_TYPE": { + "const": "EXTERNAL_IMPORT", + "default": "EXTERNAL_IMPORT", + "type": "string" + }, + "CONNECTOR_DURATION_PERIOD": { + "default": "PT4H", + "description": "The period of time to await between two runs of the connector (ISO-8601 duration format).", + "format": "duration", + "type": "string" + }, + "CONNECTOR_UPDATE_EXISTING_DATA": { + "default": true, + "description": "Whether to update data already ingested into the platform.", + "type": "boolean" + }, + "TI_API_URL": { + "default": "https://tap.group-ib.com/api/v2/", + "description": "Base URL of the Group-IB Threat Intelligence API.", + "type": "string" + }, + "TI_API_USERNAME": { + "description": "Username used to authenticate against the Group-IB TI API.", + "type": "string" + }, + "TI_API_TOKEN": { + "description": "API token used to authenticate against the Group-IB TI API.", + "format": "password", + "type": "string", + "writeOnly": true + }, + "TI_API_PROXY_IP": { + "default": null, + "description": "Optional proxy ip used to reach the Group-IB TI API.", + "type": "string" + }, + "TI_API_PROXY_PORT": { + "default": null, + "description": "Optional proxy port used to reach the Group-IB TI API.", + "type": "string" + }, + "TI_API_PROXY_PROTOCOL": { + "default": null, + "description": "Optional proxy protocol used to reach the Group-IB TI API.", + "type": "string" + }, + "TI_API_PROXY_USERNAME": { + "default": null, + "description": "Optional proxy username used to reach the Group-IB TI API.", + "type": "string" + }, + "TI_API_PROXY_PASSWORD": { + "default": null, + "description": "Optional proxy password used to reach the Group-IB TI API.", + "format": "password", + "type": "string", + "writeOnly": true + }, + "TI_API_EXTRA_SETTINGS_IGNORE_NON_INDICATOR_THREAT_REPORTS": { + "default": false, + "description": "Extra setting 'ignore_non_indicator_threat_reports'.", + "type": "boolean" + }, + "TI_API_EXTRA_SETTINGS_IGNORE_NON_INDICATOR_THREATS": { + "default": false, + "description": "Extra setting 'ignore_non_indicator_threats'.", + "type": "boolean" + }, + "TI_API_EXTRA_SETTINGS_IGNORE_NON_MALWARE_DDOS": { + "default": true, + "description": "Extra setting 'ignore_non_malware_ddos'.", + "type": "boolean" + }, + "TI_API_EXTRA_SETTINGS_INTRUSION_SET_INSTEAD_OF_THREAT_ACTOR": { + "default": false, + "description": "Extra setting 'intrusion_set_instead_of_threat_actor'.", + "type": "boolean" + }, + "TI_API_EXTRA_SETTINGS_SCHEDULE_TIME": { + "default": "00:00", + "description": "Extra setting 'schedule_time'.", + "type": "string" + }, + "TI_API_EXTRA_SETTINGS_TIME_OUTPUT_FORMAT": { + "default": "%Y-%m-%d %H:%M:%S", + "description": "Extra setting 'time_output_format'.", + "type": "string" + }, + "TI_API_EXTRA_SETTINGS_ENABLE_STATEMENT_MARKING": { + "default": false, + "description": "Extra setting 'enable_statement_marking'.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_APT_THREAT_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'apt/threat' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_APT_THREAT_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'apt/threat' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_APT_THREAT_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'apt/threat' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_APT_THREAT_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'apt/threat' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_APT_THREAT_USE_HUNTING_RULES": { + "default": false, + "description": "Apply Group-IB hunting rules when importing the 'apt/threat' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_APT_THREAT_ACTOR_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'apt/threat_actor' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_APT_THREAT_ACTOR_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'apt/threat_actor' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_APT_THREAT_ACTOR_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'apt/threat_actor' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_APT_THREAT_ACTOR_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'apt/threat_actor' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_ATTACKS_DDOS_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'attacks/ddos' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_DDOS_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'attacks/ddos' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_ATTACKS_DDOS_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'attacks/ddos' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_DDOS_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'attacks/ddos' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_ATTACKS_DEFACE_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'attacks/deface' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_DEFACE_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'attacks/deface' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_ATTACKS_DEFACE_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'attacks/deface' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_DEFACE_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'attacks/deface' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'attacks/phishing_group' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'attacks/phishing_group' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'attacks/phishing_group' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_GROUP_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'attacks/phishing_group' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'attacks/phishing_kit' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'attacks/phishing_kit' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'attacks/phishing_kit' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_ATTACKS_PHISHING_KIT_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'attacks/phishing_kit' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCESS_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/access' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCESS_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/access' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCESS_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/access' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCESS_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'compromised/access' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/account_group' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/account_group' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/account_group' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_ACCOUNT_GROUP_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'compromised/account_group' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/bank_card_group' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/bank_card_group' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/bank_card_group' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_BANK_CARD_GROUP_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'compromised/bank_card_group' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_DISCORD_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/discord' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_DISCORD_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/discord' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_DISCORD_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/discord' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_DISCORD_TTL": { + "default": null, + "description": "Time-to-live (in days) for indicators from the 'compromised/discord' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_IMEI_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/imei' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_IMEI_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/imei' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_IMEI_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/imei' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_IMEI_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'compromised/imei' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/masked_card' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/masked_card' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/masked_card' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_MASKED_CARD_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'compromised/masked_card' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_MESSENGER_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/messenger' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_MESSENGER_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/messenger' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_MESSENGER_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/messenger' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_MESSENGER_TTL": { + "default": null, + "description": "Time-to-live (in days) for indicators from the 'compromised/messenger' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_COMPROMISED_MULE_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'compromised/mule' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_MULE_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'compromised/mule' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_COMPROMISED_MULE_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'compromised/mule' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_COMPROMISED_MULE_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'compromised/mule' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_HI_OPEN_THREATS_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'hi/open_threats' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_HI_OPEN_THREATS_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'hi/open_threats' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_HI_OPEN_THREATS_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'hi/open_threats' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_HI_OPEN_THREATS_TTL": { + "default": null, + "description": "Time-to-live (in days) for indicators from the 'hi/open_threats' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_HI_THREAT_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'hi/threat' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_HI_THREAT_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'hi/threat' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_HI_THREAT_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'hi/threat' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_HI_THREAT_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'hi/threat' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_HI_THREAT_USE_HUNTING_RULES": { + "default": false, + "description": "Apply Group-IB hunting rules when importing the 'hi/threat' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_HI_THREAT_ACTOR_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'hi/threat_actor' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_HI_THREAT_ACTOR_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'hi/threat_actor' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_HI_THREAT_ACTOR_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'hi/threat_actor' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_HI_THREAT_ACTOR_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'hi/threat_actor' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_IOC_COMMON_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'ioc/common' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_IOC_COMMON_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'ioc/common' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_IOC_COMMON_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'ioc/common' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_IOC_COMMON_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'ioc/common' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_MALWARE_CNC_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'malware/cnc' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_CNC_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'malware/cnc' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_MALWARE_CNC_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'malware/cnc' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_CNC_TTL": { + "default": 90, + "description": "Time-to-live (in days) for indicators from the 'malware/cnc' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_MALWARE_CONFIG_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'malware/config' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_CONFIG_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'malware/config' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_MALWARE_CONFIG_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'malware/config' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_CONFIG_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'malware/config' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_MALWARE_MALWARE_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'malware/malware' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_MALWARE_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'malware/malware' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_MALWARE_MALWARE_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'malware/malware' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_MALWARE_TTL": { + "default": null, + "description": "Time-to-live (in days) for indicators from the 'malware/malware' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_MALWARE_SIGNATURE_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'malware/signature' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_SIGNATURE_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'malware/signature' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_MALWARE_SIGNATURE_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'malware/signature' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_SIGNATURE_TTL": { + "default": null, + "description": "Time-to-live (in days) for indicators from the 'malware/signature' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_MALWARE_YARA_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'malware/yara' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_YARA_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'malware/yara' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_MALWARE_YARA_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'malware/yara' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_MALWARE_YARA_TTL": { + "default": null, + "description": "Time-to-live (in days) for indicators from the 'malware/yara' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'osi/git_repository' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'osi/git_repository' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'osi/git_repository' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_OSI_GIT_REPOSITORY_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'osi/git_repository' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'osi/public_leak' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'osi/public_leak' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'osi/public_leak' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_OSI_PUBLIC_LEAK_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'osi/public_leak' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_OSI_VULNERABILITY_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'osi/vulnerability' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_OSI_VULNERABILITY_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'osi/vulnerability' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_OSI_VULNERABILITY_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'osi/vulnerability' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_OSI_VULNERABILITY_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'osi/vulnerability' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/open_proxy' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'suspicious_ip/open_proxy' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'suspicious_ip/open_proxy' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_OPEN_PROXY_TTL": { + "default": 15, + "description": "Time-to-live (in days) for indicators from the 'suspicious_ip/open_proxy' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/scanner' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'suspicious_ip/scanner' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'suspicious_ip/scanner' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SCANNER_TTL": { + "default": 15, + "description": "Time-to-live (in days) for indicators from the 'suspicious_ip/scanner' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/socks_proxy' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'suspicious_ip/socks_proxy' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'suspicious_ip/socks_proxy' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_SOCKS_PROXY_TTL": { + "default": 2, + "description": "Time-to-live (in days) for indicators from the 'suspicious_ip/socks_proxy' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/tor_node' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'suspicious_ip/tor_node' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'suspicious_ip/tor_node' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_TOR_NODE_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'suspicious_ip/tor_node' collection.", + "type": "integer" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_DEFAULT_DATE": { + "default": null, + "description": "Start date (YYYY-MM-DD) for the first import of the 'suspicious_ip/vpn' collection; empty means last 3 days.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_ENABLE": { + "default": false, + "description": "Enable ingestion of the 'suspicious_ip/vpn' collection.", + "type": "boolean" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_LOCAL_CUSTOM_TAG": { + "default": null, + "description": "Optional custom label added to objects from the 'suspicious_ip/vpn' collection.", + "type": "string" + }, + "TI_API_COLLECTIONS_SUSPICIOUS_IP_VPN_TTL": { + "default": 30, + "description": "Time-to-live (in days) for indicators from the 'suspicious_ip/vpn' collection.", + "type": "integer" + } + }, + "required": [ + "OPENCTI_URL", + "OPENCTI_TOKEN", + "TI_API_USERNAME", + "TI_API_TOKEN" + ], + "additionalProperties": true +} \ No newline at end of file From 3961979100b45f6334673c915a8a2914085eca8c Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Tue, 18 Aug 2026 17:07:36 +0200 Subject: [PATCH 6/9] feat(group-ib): add unit tests for manager-supported mode (#7282) --- external-import/group-ib/tests/conftest.py | 4 + .../group-ib/tests/test-requirements.txt | 3 + external-import/group-ib/tests/test_main.py | 112 ++++++++++++++ .../tests/tests_connector/test_settings.py | 141 ++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 external-import/group-ib/tests/conftest.py create mode 100644 external-import/group-ib/tests/test-requirements.txt create mode 100644 external-import/group-ib/tests/test_main.py create mode 100644 external-import/group-ib/tests/tests_connector/test_settings.py diff --git a/external-import/group-ib/tests/conftest.py b/external-import/group-ib/tests/conftest.py new file mode 100644 index 00000000000..5ee8fc0e226 --- /dev/null +++ b/external-import/group-ib/tests/conftest.py @@ -0,0 +1,4 @@ +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "src")) diff --git a/external-import/group-ib/tests/test-requirements.txt b/external-import/group-ib/tests/test-requirements.txt new file mode 100644 index 00000000000..d54845b9598 --- /dev/null +++ b/external-import/group-ib/tests/test-requirements.txt @@ -0,0 +1,3 @@ +# Main dependencies need to be installed +-r ../src/requirements.txt +pytest==8.4.2 diff --git a/external-import/group-ib/tests/test_main.py b/external-import/group-ib/tests/test_main.py new file mode 100644 index 00000000000..a4fe0b04f10 --- /dev/null +++ b/external-import/group-ib/tests/test_main.py @@ -0,0 +1,112 @@ +from typing import Any +from unittest.mock import MagicMock + +import config +import pytest +from lib import external_import +from main import CustomConnector +from pycti import OpenCTIConnectorHelper +from settings import ConnectorSettings + + +@pytest.fixture +def mock_opencti_connector_helper(monkeypatch): + """Mock all heavy dependencies of OpenCTIConnectorHelper, typically API calls to OpenCTI.""" + + module_import_path = "pycti.connector.opencti_connector_helper" + monkeypatch.setattr(f"{module_import_path}.killProgramHook", MagicMock()) + monkeypatch.setattr(f"{module_import_path}.sched.scheduler", MagicMock()) + monkeypatch.setattr(f"{module_import_path}.ConnectorInfo", MagicMock()) + monkeypatch.setattr(f"{module_import_path}.OpenCTIApiClient", MagicMock()) + + mock_connector = MagicMock() + mock_connector.name = "Group-IB Test Connector" + monkeypatch.setattr( + f"{module_import_path}.OpenCTIConnector", + MagicMock(return_value=mock_connector), + ) + monkeypatch.setattr(f"{module_import_path}.OpenCTIMetricHandler", MagicMock()) + monkeypatch.setattr(f"{module_import_path}.PingAlive", MagicMock()) + + +class StubConnectorSettings(ConnectorSettings): + """ + Subclass of `ConnectorSettings` (implementation of `BaseConnectorSettings`) for testing purpose. + It overrides `BaseConnectorSettings._load_config_dict` to return a fake but valid config dict. + """ + + @classmethod + def _load_config_dict(cls, _, handler) -> dict[str, Any]: + return handler( + { + "opencti": { + "url": "http://localhost:8080", + "token": "test-token", + }, + "connector": { + "id": "test-connector-id", + "name": "Group-IB Test Connector", + "scope": "stix2,ipv4-addr,ipv6-addr", + "log_level": "error", + "duration_period": "PT4H", + "update_existing_data": True, + }, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + "url": "https://tap.group-ib.com/api/v2/", + "collections_apt_threat_enable": True, + "collections_apt_threat_ttl": 90, + "extra_settings_enable_statement_marking": False, + }, + } + ) + + +def test_connector_settings_is_instantiated(): + """ + Test that the implementation of `BaseConnectorSettings` (from `connectors-sdk`) + can be instantiated successfully. + """ + settings = StubConnectorSettings() + + assert isinstance(settings, ConnectorSettings) + assert isinstance(settings.to_helper_config(), dict) + + +def test_opencti_connector_helper_is_instantiated(mock_opencti_connector_helper): + """ + Test that `OpenCTIConnectorHelper` (from `pycti`) can be instantiated successfully + from the config produced by the new Pydantic settings. + """ + settings = StubConnectorSettings() + helper = OpenCTIConnectorHelper(config=settings.to_helper_config()) + + assert helper.opencti_url == "http://localhost:8080/" + assert helper.opencti_token == "test-token" + assert helper.connect_id == "test-connector-id" + assert helper.connect_name == "Group-IB Test Connector" + assert helper.connect_scope == "stix2,ipv4-addr,ipv6-addr" + assert helper.log_level == "ERROR" + assert helper.connect_duration_period == "PT4H" + + +def test_connector_is_instantiated(monkeypatch, mock_opencti_connector_helper): + """ + Test that the connector's main class (`CustomConnector`) can be instantiated + successfully when its configuration flows through the new Pydantic settings. + + `config.ConnectorSettings` is patched with the stub so no real environment / + `config.yml` is required, and the heavy `TIAdapter` dependency is mocked. + """ + monkeypatch.setattr(config, "ConnectorSettings", StubConnectorSettings) + monkeypatch.setattr(external_import, "TIAdapter", MagicMock()) + + connector = CustomConnector() + + assert isinstance(connector.cfg, config.ConfigConnector) + assert connector.helper is not None + assert connector.interval == "PT4H" + assert connector.update_existing_data is True + # The helper must have been built from the settings' `to_helper_config()`. + assert connector.cfg.to_helper_config()["opencti"]["token"] == "test-token" diff --git a/external-import/group-ib/tests/tests_connector/test_settings.py b/external-import/group-ib/tests/tests_connector/test_settings.py new file mode 100644 index 00000000000..eecebae42f2 --- /dev/null +++ b/external-import/group-ib/tests/tests_connector/test_settings.py @@ -0,0 +1,141 @@ +from typing import Any + +import pytest +from connectors_sdk import BaseConfigModel, ConfigValidationError +from settings import ConnectorSettings + + +@pytest.mark.parametrize( + "settings_dict", + [ + pytest.param( + { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": { + "id": "connector-id", + "name": "Group-IB Test Connector", + "scope": "stix2,ipv4-addr,ipv6-addr", + "log_level": "error", + "duration_period": "PT4H", + "update_existing_data": True, + }, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + "url": "https://tap.group-ib.com/api/v2/", + "proxy_ip": "10.0.0.5", + "proxy_port": "8080", + "extra_settings_schedule_time": "00:00", + "extra_settings_enable_statement_marking": False, + "collections_apt_threat_enable": True, + "collections_apt_threat_ttl": 90, + "collections_apt_threat_use_hunting_rules": True, + "collections_hi_threat_enable": False, + }, + }, + id="full_valid_settings_dict", + ), + pytest.param( + { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": {}, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + }, + }, + id="minimal_valid_settings_dict", + ), + ], +) +def test_settings_should_accept_valid_input(settings_dict): + """ + Test that `ConnectorSettings` (implementation of `BaseConnectorSettings` from `connectors-sdk`) + accepts valid input. For the test purpose, `BaseConnectorSettings._load_config_dict` is + overridden to return a fake but valid dict (instead of the env/config vars parsed from + `config.yml`, `.env` or env vars). + + :param settings_dict: The dict to use as `ConnectorSettings` input + """ + + class FakeConnectorSettings(ConnectorSettings): + """ + Subclass of `ConnectorSettings` (implementation of `BaseConnectorSettings`) for testing purpose. + It overrides `BaseConnectorSettings._load_config_dict` to return a fake but valid config dict. + """ + + @classmethod + def _load_config_dict(cls, _, handler) -> dict[str, Any]: + return handler(settings_dict) + + settings = FakeConnectorSettings() + assert isinstance(settings.opencti, BaseConfigModel) is True + assert isinstance(settings.connector, BaseConfigModel) is True + assert isinstance(settings.ti_api, BaseConfigModel) is True + + +@pytest.mark.parametrize( + "settings_dict, field_name", + [ + pytest.param({}, "settings", id="empty_settings_dict"), + pytest.param( + { + "opencti": {"url": "http://localhost:8080"}, + "connector": { + "id": "connector-id", + "name": "Group-IB Test Connector", + "scope": "stix2,ipv4-addr", + "log_level": "error", + "duration_period": "PT4H", + }, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + }, + }, + "opencti.token", + id="missing_opencti_token", + ), + pytest.param( + { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": { + "id": 123456, + "name": "Group-IB Test Connector", + "scope": "stix2,ipv4-addr", + "log_level": "error", + "duration_period": "PT4H", + }, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + }, + }, + "connector.id", + id="invalid_connector_id", + ), + ], +) +def test_settings_should_raise_when_invalid_input(settings_dict, field_name): + """ + Test that `ConnectorSettings` (implementation of `BaseConnectorSettings` from `connectors-sdk`) + raises on invalid input. For the test purpose, `BaseConnectorSettings._load_config_dict` is + overridden to return a fake and invalid dict (instead of the env/config vars parsed from + `config.yml`, `.env` or env vars). + + :param settings_dict: The dict to use as `ConnectorSettings` input + """ + + class FakeConnectorSettings(ConnectorSettings): + """ + Subclass of `ConnectorSettings` (implementation of `BaseConnectorSettings`) for testing purpose. + It overrides `BaseConnectorSettings._load_config_dict` to return a fake but invalid config dict. + """ + + @classmethod + def _load_config_dict(cls, _, handler) -> dict[str, Any]: + return handler(settings_dict) + + with pytest.raises(ConfigValidationError) as err: + FakeConnectorSettings() + assert "Error validating configuration" in str(err.value) From f9010186131d302cedc8de6bcd0bbef8450de044 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Wed, 19 Aug 2026 18:10:23 +0200 Subject: [PATCH 7/9] feat(group-ib): keep legacy TI_API__* env vars working with deprecation warnings (#7282) The manager-supported migration flattened the deeply-nested ti_api config into single-underscore fields, which renamed every TI_API__* env var. Add a backward-compatibility shim on GroupIBTIApiConfig that maps legacy double-underscore variables to the new fields and emits a DeprecationWarning, so existing deployments keep working. The canonical variable wins when both are set. Covered by unit tests. --- external-import/group-ib/src/settings.py | 44 ++++++++++++- .../tests/tests_connector/test_settings.py | 65 +++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/external-import/group-ib/src/settings.py b/external-import/group-ib/src/settings.py index f360abb660c..9b0a9df0fb3 100644 --- a/external-import/group-ib/src/settings.py +++ b/external-import/group-ib/src/settings.py @@ -8,8 +8,9 @@ apt_threat_enable``) so the rest of the connector keeps working unchanged. """ +import warnings from datetime import timedelta -from typing import Literal +from typing import Any, Literal from connectors_sdk import ( BaseConfigModel, @@ -17,7 +18,7 @@ BaseExternalImportConnectorConfig, ListFromString, ) -from pydantic import Field, SecretStr +from pydantic import Field, SecretStr, model_validator class GroupIBConnectorConfig(BaseExternalImportConnectorConfig): @@ -65,6 +66,45 @@ class GroupIBTIApiConfig(BaseConfigModel): are flattened into prefixed fields so each value maps to a single env var. """ + @model_validator(mode="before") + @classmethod + def _migrate_legacy_double_underscore_env_vars(cls, data: Any) -> Any: + """Map legacy ``TI_API__*`` env vars to the flattened single-underscore fields. + + Before the manager-supported migration the deeply-nested ``ti_api`` config was + exposed through double-underscore env vars (e.g. ``TI_API__PROXY__IP``, + ``TI_API__COLLECTIONS__APT_THREAT__ENABLE``). Those now map to flattened fields + using single underscores (``proxy_ip``, ``collections_apt_threat_enable``). + + The connectors-sdk loader still parses a legacy variable into this section but + keeps its raw suffix (e.g. ``TI_API__PROXY__IP`` becomes the key + ``_proxy__ip``). This validator renames such legacy keys to their canonical + field name and emits a ``DeprecationWarning``. The canonical (new) variable wins + when both are provided. + """ + if not isinstance(data, dict): + return data + + for legacy_key in [k for k in data if isinstance(k, str) and k.startswith("_")]: + canonical_key = legacy_key.lstrip("_").replace("__", "_") + if canonical_key == legacy_key or canonical_key not in cls.model_fields: + continue + + legacy_env_var = f"TI_API_{legacy_key.upper()}" + canonical_env_var = f"TI_API_{canonical_key.upper()}" + warnings.warn( + f"Environment variable '{legacy_env_var}' is deprecated and will be " + f"removed in a future release; use '{canonical_env_var}' instead.", + DeprecationWarning, + stacklevel=2, + ) + + legacy_value = data.pop(legacy_key) + if data.get(canonical_key) in (None, ""): + data[canonical_key] = legacy_value + + return data + url: str = Field( description="Base URL of the Group-IB Threat Intelligence API.", default="https://tap.group-ib.com/api/v2/", diff --git a/external-import/group-ib/tests/tests_connector/test_settings.py b/external-import/group-ib/tests/tests_connector/test_settings.py index eecebae42f2..e2eedcae8af 100644 --- a/external-import/group-ib/tests/tests_connector/test_settings.py +++ b/external-import/group-ib/tests/tests_connector/test_settings.py @@ -139,3 +139,68 @@ def _load_config_dict(cls, _, handler) -> dict[str, Any]: with pytest.raises(ConfigValidationError) as err: FakeConnectorSettings() assert "Error validating configuration" in str(err.value) + + +def _fake_settings_from_dict(settings_dict: dict[str, Any]) -> type[ConnectorSettings]: + """Build a `ConnectorSettings` subclass returning ``settings_dict`` as raw config.""" + + class FakeConnectorSettings(ConnectorSettings): + @classmethod + def _load_config_dict(cls, _, handler) -> dict[str, Any]: + return handler(settings_dict) + + return FakeConnectorSettings + + +def test_settings_should_migrate_legacy_double_underscore_ti_api_keys(): + """ + Legacy ``TI_API__*`` env vars are parsed by the connectors-sdk loader into the + ``ti_api`` section with a leading-underscore/double-underscore suffix (e.g. + ``TI_API__PROXY__IP`` -> ``_proxy__ip``). They must be migrated to the flattened + single-underscore fields while emitting a ``DeprecationWarning``. + """ + settings_dict = { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": {}, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + "_url": "https://legacy.group-ib.com/api/v2/", + "_proxy__ip": "10.0.0.5", + "_extra_settings__schedule_time": "02:30", + "_collections__apt_threat__enable": "true", + "_collections__apt_threat__ttl": "777", + }, + } + + with pytest.warns(DeprecationWarning) as warning_records: + settings = _fake_settings_from_dict(settings_dict)() + + assert settings.ti_api.url == "https://legacy.group-ib.com/api/v2/" + assert settings.ti_api.proxy_ip == "10.0.0.5" + assert settings.ti_api.extra_settings_schedule_time == "02:30" + assert settings.ti_api.collections_apt_threat_enable is True + assert settings.ti_api.collections_apt_threat_ttl == 777 + + messages = [str(record.message) for record in warning_records] + assert any("TI_API__PROXY__IP" in message for message in messages) + assert any("TI_API_PROXY_IP" in message for message in messages) + + +def test_settings_new_keys_take_precedence_over_legacy_keys(): + """When both the legacy and the canonical variable are set, the canonical one wins.""" + settings_dict = { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": {}, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + "proxy_ip": "5.5.5.5", + "_proxy__ip": "9.9.9.9", + }, + } + + with pytest.warns(DeprecationWarning): + settings = _fake_settings_from_dict(settings_dict)() + + assert settings.ti_api.proxy_ip == "5.5.5.5" From 77b645233c2c7eb097eec46e18b8a55be1794116 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Thu, 20 Aug 2026 10:33:47 +0200 Subject: [PATCH 8/9] refactor(group-ib): simplify ConfigConnector config exposure (#7282) Replace the eager _expose_settings_as_attributes/_unwrap shim, which generated flat attributes for every settings field (including unused opencti_* and connector id/name/scope/log_level), with explicit properties for the values actually consumed and helpers that read the nested settings directly. Removes dead attribute generation while preserving the historical ConfigConnector interface (secret unwrapping, ISO-8601 duration, and None-for-unknown collection/extra settings). --- external-import/group-ib/src/config.py | 112 ++++++++++++++----------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/external-import/group-ib/src/config.py b/external-import/group-ib/src/config.py index 85f70414792..f63a53ceb39 100644 --- a/external-import/group-ib/src/config.py +++ b/external-import/group-ib/src/config.py @@ -1,10 +1,9 @@ import os -from typing import Any +from typing import ClassVar import isodate import pycti from cyberintegrations.utils import FileHandler -from pydantic import SecretStr from settings import ConnectorSettings from stix2 import TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, MarkingDefinition from stix2.v21.vocab import MALWARE_TYPE @@ -16,60 +15,71 @@ def __init__(self): Initialize the connector with necessary configurations. Configuration is loaded and validated through the Pydantic - ``ConnectorSettings`` model. The validated values are then exposed using - the connector's historical flat attribute names (e.g. - ``ti_api_collections_apt_threat_enable``, ``connector_duration_period``) - so the rest of the connector keeps working unchanged. + ``ConnectorSettings`` model. Values consumed by the rest of the connector + are exposed under their historical names via the properties and helpers + below, so no downstream code needs to change. """ self.settings = ConnectorSettings() - self._expose_settings_as_attributes() self.collection_mapping_config = FileHandler().read_json_config( self.CONFIG_JSON ) - @staticmethod - def _unwrap(value: Any) -> Any: - """Return the plain value of a ``SecretStr`` (or the value unchanged).""" - if isinstance(value, SecretStr): - return value.get_secret_value() - return value + def to_helper_config(self) -> dict: + """Return a config dict suitable for ``pycti.OpenCTIConnectorHelper``.""" + return self.settings.to_helper_config() - def _expose_settings_as_attributes(self) -> None: - """ - Expose validated settings using the connector's historical attribute names. + # --- Connector settings consumed by the scheduler / helpers --- + @property + def connector_duration_period(self) -> str: + # Historical ISO-8601 string form used by the interval validation helper. + return isodate.duration_isoformat(self.settings.connector.duration_period) - The rest of the connector reads flat attributes such as - ``ti_api_proxy_ip`` or ``connector_duration_period``; they are derived - here from the nested Pydantic settings so no downstream code needs to - change. - """ - for field_name in type(self.settings.opencti).model_fields: - value = self._unwrap(getattr(self.settings.opencti, field_name)) - setattr(self, f"opencti_{field_name}", value) + @property + def connector_update_existing_data(self) -> bool: + return self.settings.connector.update_existing_data - for field_name in type(self.settings.connector).model_fields: - value = getattr(self.settings.connector, field_name) - if field_name == "duration_period": - # Preserve the historical ISO-8601 string form used by the - # scheduler / interval validation helper. - value = isodate.duration_isoformat(value) - setattr(self, f"connector_{field_name}", self._unwrap(value)) + # --- Group-IB TI API credentials & proxy consumed by the TI adapter --- + @property + def ti_api_url(self) -> str: + return self.settings.ti_api.url - for field_name in type(self.settings.ti_api).model_fields: - value = self._unwrap(getattr(self.settings.ti_api, field_name)) - setattr(self, f"ti_api_{field_name}", value) + @property + def ti_api_username(self) -> str: + return self.settings.ti_api.username - def to_helper_config(self) -> dict: - """Return a config dict suitable for ``pycti.OpenCTIConnectorHelper``.""" - return self.settings.to_helper_config() + @property + def ti_api_token(self) -> str: + return self.settings.ti_api.token.get_secret_value() + + @property + def ti_api_proxy_ip(self): + return self.settings.ti_api.proxy_ip + + @property + def ti_api_proxy_port(self): + return self.settings.ti_api.proxy_port + + @property + def ti_api_proxy_protocol(self): + return self.settings.ti_api.proxy_protocol - def get_collection_settings(self, collection, setting_name) -> Any: - collection_attr_name = f"ti_api_collections_{collection}_{setting_name}" - return getattr(self, collection_attr_name, None) + @property + def ti_api_proxy_username(self): + return self.settings.ti_api.proxy_username + + @property + def ti_api_proxy_password(self): + password = self.settings.ti_api.proxy_password + return password.get_secret_value() if password is not None else None + + # --- Dynamic collection / extra settings (unknown names resolve to None) --- + def get_collection_settings(self, collection, setting_name): + return getattr( + self.settings.ti_api, f"collections_{collection}_{setting_name}", None + ) def get_extra_settings_by_name(self, setting_name): - extra_setting_attr_name = f"ti_api_extra_settings_{setting_name}" - return getattr(self, extra_setting_attr_name, None) + return getattr(self.settings.ti_api, f"extra_settings_{setting_name}", None) # Set up product metadata PRODUCT_TYPE = "SCRIPT" @@ -120,7 +130,7 @@ def get_extra_settings_by_name(self, setting_name): # fallback if custom TLP cannot be created by stix2 in this runtime TLP_AMBER_STRICT = TLP_AMBER - STIX_TLP_MAP = { + STIX_TLP_MAP: ClassVar[dict] = { "white": TLP_WHITE, "green": TLP_GREEN, "amber": TLP_AMBER, @@ -129,12 +139,12 @@ def get_extra_settings_by_name(self, setting_name): } # Default TLPs by SDO type when upstream API did not provide a valid TLP - DEFAULT_TLP_BY_SDO = { + DEFAULT_TLP_BY_SDO: ClassVar[dict] = { "malware": "amber+strict", "threat-actor": "amber+strict", "intrusion-set": "amber+strict", } - STIX_MAIN_OBSERVABLE_TYPE_MAP = { + STIX_MAIN_OBSERVABLE_TYPE_MAP: ClassVar[dict] = { "domain": "Domain-Name", "domain-name": "Domain-Name", "file": "StixFile", @@ -146,9 +156,9 @@ def get_extra_settings_by_name(self, setting_name): "yara": "StixFile", "suricata": "Network-Traffic", } - STIX_MALWARE_TYPE_MAP = {*MALWARE_TYPE} + STIX_MALWARE_TYPE_MAP: ClassVar[set] = {*MALWARE_TYPE} # ISO3166-1 https://www.iso.org/standard/72482.html - COUNTRIES = { + COUNTRIES: ClassVar[dict] = { "AF": "Afghanistan", "AX": "Ă…land Islands", "AL": "Albania", @@ -399,19 +409,19 @@ def get_extra_settings_by_name(self, setting_name): "ZM": "Zambia", "ZW": "Zimbabwe", } - STIX_COUNTRY_TYPE_MAP = { + STIX_COUNTRY_TYPE_MAP: ClassVar[dict] = { "country": "Country", "city": "City", "state": "Administrative-Area", } - STIX_REPORT_TYPE_MAP = {"threat_report": "Threat-Report"} - STIX_RELATION_TYPE_MAP = { + STIX_REPORT_TYPE_MAP: ClassVar[dict] = {"threat_report": "Threat-Report"} + STIX_RELATION_TYPE_MAP: ClassVar[dict] = { "indicator": "based-on", "attack_pattern": "indicates", "malware": "indicates", "threat_actor": "indicates", } - COLLECTION_MAP = { + COLLECTION_MAP: ClassVar[dict] = { "apt_threat": "apt/threat", "apt_threat_actor": "apt/threat_actor", "attacks_ddos": "attacks/ddos", From 1d21ba8c0c2d807c471fd69041a01fd257e89044 Mon Sep 17 00:00:00 2001 From: Hugo DUPRAS Date: Thu, 20 Aug 2026 11:04:58 +0200 Subject: [PATCH 9/9] feat(group-ib): support legacy nested config.yml with deprecation warnings (#7282) The manager-supported migration flattened the nested ti_api config, which also broke deployments still using a nested config.yml (proxy, extra_settings and slash-keyed collections sub-sections were silently ignored). Extend the GroupIBTIApiConfig migration validator to flatten those nested sub-sections onto the canonical fields (in addition to the legacy double-underscore env vars), emitting a DeprecationWarning per section. The flattened (canonical) value takes precedence when both forms are provided. Covered by unit tests. --- external-import/group-ib/src/settings.py | 75 ++++++++++++++----- .../tests/tests_connector/test_settings.py | 62 +++++++++++++++ 2 files changed, 119 insertions(+), 18 deletions(-) diff --git a/external-import/group-ib/src/settings.py b/external-import/group-ib/src/settings.py index 9b0a9df0fb3..129f6cc379a 100644 --- a/external-import/group-ib/src/settings.py +++ b/external-import/group-ib/src/settings.py @@ -68,40 +68,79 @@ class GroupIBTIApiConfig(BaseConfigModel): @model_validator(mode="before") @classmethod - def _migrate_legacy_double_underscore_env_vars(cls, data: Any) -> Any: - """Map legacy ``TI_API__*`` env vars to the flattened single-underscore fields. + def _migrate_legacy_config(cls, data: Any) -> Any: + """Map legacy Group-IB TI API configuration shapes to the flattened fields. - Before the manager-supported migration the deeply-nested ``ti_api`` config was - exposed through double-underscore env vars (e.g. ``TI_API__PROXY__IP``, - ``TI_API__COLLECTIONS__APT_THREAT__ENABLE``). Those now map to flattened fields - using single underscores (``proxy_ip``, ``collections_apt_threat_enable``). + Before the manager-supported migration the ``ti_api`` configuration was + deeply nested. Two legacy shapes are still accepted for backward compatibility: - The connectors-sdk loader still parses a legacy variable into this section but - keeps its raw suffix (e.g. ``TI_API__PROXY__IP`` becomes the key - ``_proxy__ip``). This validator renames such legacy keys to their canonical - field name and emits a ``DeprecationWarning``. The canonical (new) variable wins - when both are provided. + * the original **nested** ``config.yml`` sub-sections ``proxy``, + ``extra_settings`` and ``collections`` (the latter keyed by slash, e.g. + ``apt/threat``); + * the legacy **double-underscore env vars** (e.g. ``TI_API__PROXY__IP``, + ``TI_API__COLLECTIONS__APT_THREAT__ENABLE``) which the connectors-sdk loader + keeps as raw suffix keys (``_proxy__ip``, ``_collections__apt_threat__enable``). + + Both are migrated to the flattened fields (``proxy_ip``, + ``collections_apt_threat_enable``, ...) with a ``DeprecationWarning`` so operators + update their configuration. The already-flattened (canonical) value takes + precedence when both forms are provided. """ if not isinstance(data, dict): return data + data = dict(data) + + def set_if_absent(canonical_key: str, value: Any) -> None: + if canonical_key in cls.model_fields and data.get(canonical_key) in ( + None, + "", + ): + data[canonical_key] = value + + # 1. Legacy nested ``config.yml`` sub-sections. + for section in ("proxy", "extra_settings"): + nested = data.pop(section, None) + if isinstance(nested, dict): + warnings.warn( + f"Deprecated nested 'ti_api.{section}' configuration detected; " + f"use the flattened '{section}_*' settings instead.", + DeprecationWarning, + stacklevel=2, + ) + for key, value in nested.items(): + set_if_absent(f"{section}_{key}", value) + + collections = data.pop("collections", None) + if isinstance(collections, dict): + warnings.warn( + "Deprecated nested 'ti_api.collections' configuration detected; use the " + "flattened 'collections__' settings instead.", + DeprecationWarning, + stacklevel=2, + ) + for collection_name, collection_settings in collections.items(): + if isinstance(collection_settings, dict): + flat_name = collection_name.replace("/", "_") + for key, value in collection_settings.items(): + set_if_absent(f"collections_{flat_name}_{key}", value) + + # 2. Legacy double-underscore env vars kept as raw suffix keys (e.g. _proxy__ip). for legacy_key in [k for k in data if isinstance(k, str) and k.startswith("_")]: canonical_key = legacy_key.lstrip("_").replace("__", "_") if canonical_key == legacy_key or canonical_key not in cls.model_fields: continue - legacy_env_var = f"TI_API_{legacy_key.upper()}" - canonical_env_var = f"TI_API_{canonical_key.upper()}" warnings.warn( - f"Environment variable '{legacy_env_var}' is deprecated and will be " - f"removed in a future release; use '{canonical_env_var}' instead.", + f"Environment variable 'TI_API_{legacy_key.upper()}' is deprecated and " + f"will be removed in a future release; use " + f"'TI_API_{canonical_key.upper()}' instead.", DeprecationWarning, stacklevel=2, ) - legacy_value = data.pop(legacy_key) - if data.get(canonical_key) in (None, ""): - data[canonical_key] = legacy_value + value = data.pop(legacy_key) + set_if_absent(canonical_key, value) return data diff --git a/external-import/group-ib/tests/tests_connector/test_settings.py b/external-import/group-ib/tests/tests_connector/test_settings.py index e2eedcae8af..daded964efa 100644 --- a/external-import/group-ib/tests/tests_connector/test_settings.py +++ b/external-import/group-ib/tests/tests_connector/test_settings.py @@ -204,3 +204,65 @@ def test_settings_new_keys_take_precedence_over_legacy_keys(): settings = _fake_settings_from_dict(settings_dict)() assert settings.ti_api.proxy_ip == "5.5.5.5" + + +def test_settings_should_migrate_legacy_nested_config(): + """ + A legacy nested ``config.yml`` exposes ``ti_api`` with nested ``proxy``, + ``extra_settings`` and ``collections`` sub-sections (the latter keyed by slash, + e.g. ``apt/threat``). They must be flattened onto the canonical fields while + emitting a ``DeprecationWarning``. + """ + settings_dict = { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": {}, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + "url": "https://legacy.group-ib.com/api/v2/", + "proxy": {"ip": "10.0.0.5", "port": "8080"}, + "extra_settings": { + "schedule_time": "02:30", + "enable_statement_marking": True, + }, + "collections": { + "apt/threat": {"enable": True, "ttl": 777}, + "suspicious_ip/scanner": {"enable": True}, + }, + }, + } + + with pytest.warns(DeprecationWarning) as warning_records: + settings = _fake_settings_from_dict(settings_dict)() + + assert settings.ti_api.url == "https://legacy.group-ib.com/api/v2/" + assert settings.ti_api.proxy_ip == "10.0.0.5" + assert settings.ti_api.proxy_port == "8080" + assert settings.ti_api.extra_settings_schedule_time == "02:30" + assert settings.ti_api.extra_settings_enable_statement_marking is True + assert settings.ti_api.collections_apt_threat_enable is True + assert settings.ti_api.collections_apt_threat_ttl == 777 + assert settings.ti_api.collections_suspicious_ip_scanner_enable is True + + messages = [str(record.message) for record in warning_records] + assert any("ti_api.proxy" in message for message in messages) + assert any("ti_api.collections" in message for message in messages) + + +def test_settings_new_flat_keys_take_precedence_over_nested_config(): + """When both a nested sub-section and its flattened field are set, the flat one wins.""" + settings_dict = { + "opencti": {"url": "http://localhost:8080", "token": "test-token"}, + "connector": {}, + "ti_api": { + "username": "user@example.com", + "token": "test-ti-token", + "proxy_ip": "5.5.5.5", + "proxy": {"ip": "9.9.9.9"}, + }, + } + + with pytest.warns(DeprecationWarning): + settings = _fake_settings_from_dict(settings_dict)() + + assert settings.ti_api.proxy_ip == "5.5.5.5"