diff --git a/.github/workflows/publish_charm.yaml b/.github/workflows/publish_charm.yaml index e14e332..128021d 100644 --- a/.github/workflows/publish_charm.yaml +++ b/.github/workflows/publish_charm.yaml @@ -1,14 +1,92 @@ name: Publish to edge on: - workflow_dispatch: push: branches: - main + pull_request: jobs: - publish-to-edge: - uses: canonical/operator-workflows/.github/workflows/publish_charm.yaml@main - secrets: inherit - with: - channel: latest/edge + find-charms: + name: Find Charms + runs-on: ubuntu-latest + outputs: + charm-dirs: ${{ steps.charm-dirs.outputs.charm-dirs }} + steps: + - uses: actions/checkout@v4 + - id: charm-dirs + run: | + echo charm-dirs=`find -name charmcraft.yaml | xargs dirname | jq --raw-input --slurp 'split("\n") | map(select(. != ""))'` >> $GITHUB_OUTPUT + + publish-charm: + needs: [ find-charms ] + strategy: + fail-fast: false + matrix: + charm-dir: ${{ fromJSON(needs.find-charms.outputs.charm-dirs) }} + name: Publish Charm (${{ matrix.charm-dir }}) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: change directory + run: | + TEMP_DIR=$(mktemp -d) + cp -rp ./${{ matrix.charm-dir }}/. $TEMP_DIR + rm -rf .* * || : + cp -rp $TEMP_DIR/. . + rm -rf $TEMP_DIR + - name: setup lxd + uses: canonical/setup-lxd@v0.1.2 + - name: find rock + id: rock-dir + run: | + echo rock-dir=`dirname *rock/rockcraft.yaml` >> $GITHUB_OUTPUT + - name: build rock + id: rockcraft + run: | + sudo snap install --channel latest/stable --classic rockcraft + cd ${{ steps.rock-dir.outputs.rock-dir }} + rockcraft pack --verbosity trace + echo rock=`ls *.rock` >> $GITHUB_OUTPUT + - run: | + echo rockcraft pack: + echo ${{ steps.rockcraft.outputs.rock }} + - name: upload rock + run: | + cd ${{ steps.rock-dir.outputs.rock-dir }} + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false oci-archive:${{ steps.rockcraft.outputs.rock }} docker-daemon:rock:latest + - name: build charm + id: charmcraft + run: | + sudo snap install --channel latest/stable --classic charmcraft + charmcraft pack --verbosity trace + echo charms=`ls *.charm` >> $GITHUB_OUTPUT + - run: | + echo charmcraft pack: + echo ${{ steps.charmcraft.outputs.charms }} + - id: charm-name + run: | + echo charm-name=`yq -r .name charmcraft.yaml` >> $GITHUB_OUTPUT + - run: | + sudo apt update && sudo apt install python3-yaml -y + - name: update upstream-source + shell: python + run: | + import yaml + + charmcraft_yaml = yaml.safe_load(open("charmcraft.yaml")) + resources = charmcraft_yaml["resources"] + resources[list(resources)[0]]["upstream-source"] = "rock:latest" + yaml.dump(charmcraft_yaml, open("charmcraft.yaml", "w"), sort_keys=False) + - run: | + echo upload charm ${{ steps.charm-name.outputs.charm-name }} + - run: | + cat charmcraft.yaml + - if: github.event_name == 'push' + name: publish charm + uses: canonical/charming-actions/upload-charm@2.6.3 + with: + credentials: ${{ secrets.CHARMHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + built-charm-path: ${{ steps.charmcraft.outputs.charms }} + tag-prefix: ${{ steps.charm-name.outputs.charm-name }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ca7556e..06c0fba 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -5,11 +5,13 @@ on: jobs: unit-tests: + name: Unit Tests uses: canonical/operator-workflows/.github/workflows/test.yaml@main secrets: inherit with: self-hosted-runner: false integration-tests: + name: Integration Tests uses: canonical/operator-workflows/.github/workflows/integration_test.yaml@main secrets: inherit with: @@ -19,3 +21,14 @@ jobs: microk8s-addons: "dns ingress rbac storage" pre-run-script: tests/integration/prepare.sh self-hosted-runner: false + check-connector-sync: + name: Check Connectors + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - run: pip install tox + - run: tox -e generate-connectors + - run: git diff --exit-code diff --git a/.gitignore b/.gitignore index 8461f41..481504d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ __pycache__/ .vscode .mypy_cache *.egg-info/ -*/*.rock +*.rock diff --git a/.licenserc.yaml b/.licenserc.yaml index afdab38..efc295b 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -34,4 +34,5 @@ header: - 'trivy.yaml' - 'zap_rules.tsv' - 'lib/**' + - 'src/opencti.graphql' comment: on-failure diff --git a/.woke.yaml b/.woke.yaml index df1c258..75de6d3 100644 --- a/.woke.yaml +++ b/.woke.yaml @@ -1,2 +1,5 @@ ignore_files: - lib/charms/redis_k8s/v0/redis.py + - connectors/** + - scripts/** + - tests/unit/test_connectors.py diff --git a/charmcraft.yaml b/charmcraft.yaml index 75e8d61..da37575 100644 --- a/charmcraft.yaml +++ b/charmcraft.yaml @@ -53,6 +53,8 @@ requires: interface: ingress optional: false limit: 1 + opencti-connector: + interface: opencti_connector logging: interface: loki_push_api optional: true diff --git a/connector-template/charmcraft.yaml.j2 b/connector-template/charmcraft.yaml.j2 new file mode 100644 index 0000000..24c5ea4 --- /dev/null +++ b/connector-template/charmcraft.yaml.j2 @@ -0,0 +1,46 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-{{ name }}-connector +title: OpenCTI {{ display_name_short }} Charm +summary: OpenCTI {{ display_name }} connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +{{ config | safe }} + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-{{ name }}-connector: + resource: opencti-{{ name }}-connector-image +resources: + opencti-{{ name }}-connector-image: + type: oci-image + description: OCI image for the OpenCTI {{ display_name }} connector. + +assumes: + - juju >= 3.4 diff --git a/connector-template/requirements.txt b/connector-template/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connector-template/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connector-template/rock/rockcraft.yaml.j2 b/connector-template/rock/rockcraft.yaml.j2 new file mode 100644 index 0000000..5957ba8 --- /dev/null +++ b/connector-template/rock/rockcraft.yaml.j2 @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-{{ name }}-connector +base: ubuntu@24.04 +version: &version '{{ version }}' +summary: OpenCTI {{ display_name }} Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + {{ name }}-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd {{ constant_to_kebab(connector_type) }}/{{ connector_name }} + cp -rp src $CRAFT_PART_INSTALL/opt/{{ install_location }} + {{ generate_entrypoint }} + cat entrypoint.sh | grep {{ install_location }} + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connector-template/src/charm.py.j2 b/connector-template/src/charm.py.j2 new file mode 100644 index 0000000..10d7d6e --- /dev/null +++ b/connector-template/src/charm.py.j2 @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI {{ display_name }} connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class Opencti{{ kebab_to_pascal(name) }}ConnectorCharm(OpenctiConnectorCharm): + connector_type = "{{ connector_type }}" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + {{ charm_override | safe | indent(4) }} + +if __name__ == "__main__": + ops.main(Opencti{{ kebab_to_pascal(name) }}ConnectorCharm) diff --git a/connectors/abuseipdb_ipblacklist/charmcraft.yaml b/connectors/abuseipdb_ipblacklist/charmcraft.yaml new file mode 100644 index 0000000..f08a7d8 --- /dev/null +++ b/connectors/abuseipdb_ipblacklist/charmcraft.yaml @@ -0,0 +1,78 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-abuseipdb-ipblacklist-connector +title: OpenCTI abuseipdb ipblacklist Charm +summary: OpenCTI abuseipdb ipblacklist connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + abuseipdb-api-key: + description: Abuse IPDB API KEY + optional: false + type: string + abuseipdb-interval: + description: interval between 2 collect itself + optional: false + type: int + abuseipdb-limit: + description: limit number of result itself + optional: false + type: int + abuseipdb-score: + description: AbuseIPDB Score Limitation + optional: false + type: int + connector-scope: + type: string + description: connector scope + optional: false + abuseipdb-url: + description: the Abuse IPDB URL + type: string + optional: false + default: https://api.abuseipdb.com/api/v2/blacklist + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-abuseipdb-ipblacklist-connector: + resource: opencti-abuseipdb-ipblacklist-connector-image +resources: + opencti-abuseipdb-ipblacklist-connector-image: + type: oci-image + description: OCI image for the OpenCTI abuseipdb ipblacklist connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/abuseipdb_ipblacklist/lib/charms/opencti/v0/opencti_connector.py b/connectors/abuseipdb_ipblacklist/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/abuseipdb_ipblacklist/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/abuseipdb_ipblacklist/requirements.txt b/connectors/abuseipdb_ipblacklist/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/abuseipdb_ipblacklist/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/abuseipdb_ipblacklist/rock/rockcraft.yaml b/connectors/abuseipdb_ipblacklist/rock/rockcraft.yaml new file mode 100644 index 0000000..ff7d9da --- /dev/null +++ b/connectors/abuseipdb_ipblacklist/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-abuseipdb-ipblacklist-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI abuseipdb ipblacklist Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + abuseipdb-ipblacklist-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/abuseipdb-ipblacklist + cp -rp src $CRAFT_PART_INSTALL/opt/abuseipdb-ipblacklist + + cat entrypoint.sh | grep abuseipdb-ipblacklist + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/abuseipdb_ipblacklist/src/charm.py b/connectors/abuseipdb_ipblacklist/src/charm.py new file mode 100755 index 0000000..4de217c --- /dev/null +++ b/connectors/abuseipdb_ipblacklist/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI abuseipdb ipblacklist connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiAbuseipdbIpblacklistConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiAbuseipdbIpblacklistConnectorCharm) diff --git a/connectors/alienvault/charmcraft.yaml b/connectors/alienvault/charmcraft.yaml new file mode 100644 index 0000000..8c1f886 --- /dev/null +++ b/connectors/alienvault/charmcraft.yaml @@ -0,0 +1,165 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-alienvault-connector +title: OpenCTI AlienVault Charm +summary: OpenCTI AlienVault connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + alienvault-base-url: + description: The base URL for the OTX DirectConnect API. + type: string + optional: false + alienvault-excluded-pulse-indicator-types: + description: The Pulse indicator types that will be excluded from the import. + type: string + optional: false + alienvault-guess-cve: + description: The Pulse tags are used to guess (checks whether tag matches (CVE-\d{4}-\d{4,7})) vulnerabilities. + type: boolean + optional: false + alienvault-guess-malware: + description: The Pulse tags are used to guess (queries malwares in the OpenCTI) malwares related to the given Pulse. + type: boolean + optional: false + alienvault-interval-sec: + description: alienvault interval seconds + type: int + optional: false + alienvault-pulse-start-timestamp: + description: The Pulses modified after this timestamp will be imported. Timestamp in ISO 8601 format, UTC. + type: string + optional: false + alienvault-report-status: + description: The status of imported reports in the OpenCTI. + type: string + optional: false + alienvault-tlp: + description: The default TLP marking used if the Pulse does not define TLP. + type: string + optional: false + connector-duration-period: + description: Determines the time interval between each launch of the connector in ISO 8601, ex:PT30M. + type: string + optional: false + connector-scope: + type: string + description: connector scope + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + alienvault-api-key: + description: (optional) The OTX Key. + type: string + optional: true + alienvault-create-indicators: + description: (optional) If true then indicators will be created from Pulse indicators and added to the report. + type: boolean + optional: true + alienvault-create-observables: + description: (optional) If true then observables will be created from Pulse indicators and added to the report. + type: boolean + optional: true + alienvault-default-x-opencti-score: + description: (optional) The default x_opencti_score to use for indicators. If a per indicator type score is not set, this is used. + type: int + optional: true + alienvault-enable-attack-patterns-indicates: + description: (optional) If true then the relationshipsindicateswill be created between indicators and attack patterns. + type: boolean + optional: true + alienvault-enable-relationships: + description: (optional) If true then the relationships will be created between SDOs. + type: boolean + optional: true + alienvault-filter-indicators: + description: (optional) This boolean filters out indicators created before the latest pulse datetime, ensuring only recent indicators are processed. + type: boolean + optional: true + alienvault-report-type: + description: (optional) The type of imported reports in the OpenCTI. + type: string + optional: true + alienvault-x-opencti-score-cryptocurrency-wallet: + description: (optional) The x_opencti_score to use for Cryptocurrency Wallet indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-domain: + description: (optional) The x_opencti_score to use for Domain indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-email: + description: (optional) The x_opencti_score to use for Email indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-file: + description: (optional) The x_opencti_score to use for StixFile indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-hostname: + description: (optional) The x_opencti_score to use for Hostname indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-ip: + description: (optional) The x_opencti_score to use for IP indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-mutex: + description: (optional) The x_opencti_score to use for Mutex indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + alienvault-x-opencti-score-url: + description: (optional) The x_opencti_score to use for URL indicators. If not set, the default value isdefault_x_opencti_score. + type: int + optional: true + connector-queue-threshold: + description: (optional) Used to determine the limit (RabbitMQ) in MB at which the connector must go into buffering mode. + type: int + optional: true + connector-run-and-terminate: + description: (optional) Launch the connector once if set to True. Takes 2 available values:TrueorFalse. + type: boolean + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-alienvault-connector: + resource: opencti-alienvault-connector-image +resources: + opencti-alienvault-connector-image: + type: oci-image + description: OCI image for the OpenCTI AlienVault connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/alienvault/lib/charms/opencti/v0/opencti_connector.py b/connectors/alienvault/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/alienvault/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/alienvault/requirements.txt b/connectors/alienvault/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/alienvault/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/alienvault/rock/rockcraft.yaml b/connectors/alienvault/rock/rockcraft.yaml new file mode 100644 index 0000000..7ddb0e2 --- /dev/null +++ b/connectors/alienvault/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-alienvault-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI AlienVault Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + alienvault-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/alienvault + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-alienvault + + cat entrypoint.sh | grep opencti-connector-alienvault + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/alienvault/src/charm.py b/connectors/alienvault/src/charm.py new file mode 100755 index 0000000..38685b4 --- /dev/null +++ b/connectors/alienvault/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI AlienVault connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiAlienvaultConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiAlienvaultConnectorCharm) diff --git a/connectors/cisa_kev/charmcraft.yaml b/connectors/cisa_kev/charmcraft.yaml new file mode 100644 index 0000000..78f365f --- /dev/null +++ b/connectors/cisa_kev/charmcraft.yaml @@ -0,0 +1,81 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-cisa-kev-connector +title: OpenCTI CISA KEV Charm +summary: OpenCTI CISA Known Exploited Vulnerabilities connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + cisa-catalog-url: + description: The URL that hosts the KEV Cataloghttps://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json + type: string + optional: false + cisa-create-infrastructures: + description: Allows you to create or not create an infrastructure in opencti + type: boolean + optional: false + cisa-tlp: + description: TLP for data coming from this connector + type: string + optional: false + connector-duration-period: + description: Determines the time interval between each launch of the connector in ISO 8601, ex:P7D. + type: string + optional: false + connector-scope: + type: string + description: connector scope + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-queue-threshold: + description: (optional) Used to determine the limit (RabbitMQ) in MB at which the connector must go into buffering mode. + type: int + optional: true + connector-run-and-terminate: + description: (optional) Launch the connector once if set to True. Takes 2 available values:TrueorFalse. + type: boolean + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-cisa-kev-connector: + resource: opencti-cisa-kev-connector-image +resources: + opencti-cisa-kev-connector-image: + type: oci-image + description: OCI image for the OpenCTI CISA Known Exploited Vulnerabilities connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/cisa_kev/lib/charms/opencti/v0/opencti_connector.py b/connectors/cisa_kev/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/cisa_kev/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/cisa_kev/requirements.txt b/connectors/cisa_kev/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/cisa_kev/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/cisa_kev/rock/rockcraft.yaml b/connectors/cisa_kev/rock/rockcraft.yaml new file mode 100644 index 0000000..3050426 --- /dev/null +++ b/connectors/cisa_kev/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-cisa-kev-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI CISA Known Exploited Vulnerabilities Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + cisa-kev-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/cisa-known-exploited-vulnerabilities + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-cisa-known-exploited-vulnerabilities + + cat entrypoint.sh | grep opencti-connector-cisa-known-exploited-vulnerabilities + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/cisa_kev/src/charm.py b/connectors/cisa_kev/src/charm.py new file mode 100755 index 0000000..8ec72a3 --- /dev/null +++ b/connectors/cisa_kev/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI CISA Known Exploited Vulnerabilities connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiCisaKevConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiCisaKevConnectorCharm) diff --git a/connectors/crowdstrike/charmcraft.yaml b/connectors/crowdstrike/charmcraft.yaml new file mode 100644 index 0000000..bcc4898 --- /dev/null +++ b/connectors/crowdstrike/charmcraft.yaml @@ -0,0 +1,161 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-crowdstrike-connector +title: OpenCTI CrowdStrike Charm +summary: OpenCTI CrowdStrike connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-duration-period: + description: 'Determines the time interval between each launch of the connector in ISO 8601, ex: .' + type: string + optional: false + crowdstrike-actor-start-timestamp: + description: The Actors created after this timestamp will be imported. Timestamp in UNIX Epoch time, UTC. + type: int + optional: false + crowdstrike-client-id: + description: The CrowdStrike API client ID. + type: string + optional: false + crowdstrike-client-secret: + description: The CrowdStrike API client secret. + type: string + optional: false + crowdstrike-create-indicators: + description: If true then indicators will be created from the CrowdStrike indicators. + type: string + optional: false + crowdstrike-create-observables: + description: If true then observables will be created from the CrowdStrike indicators. + type: string + optional: false + crowdstrike-indicator-exclude-types: + description: The types of Indicators excluded from the import. The types are defined by the CrowdStrike. + type: string + optional: false + crowdstrike-indicator-start-timestamp: + description: The Indicators published after this timestamp will be imported. Timestamp in UNIX Epoch time, UTC. + type: int + optional: false + crowdstrike-report-guess-malware: + description: The Report tags are used to guess (queries malwares in the OpenCTI) malwares related to the given Report. + type: string + optional: false + crowdstrike-report-include-types: + description: The types of Reports included in the import. The types are defined by the CrowdStrike. + type: string + optional: false + crowdstrike-report-start-timestamp: + description: The Reports created after this timestamp will be imported. Timestamp in UNIX Epoch time, UTC. + type: int + optional: false + crowdstrike-report-status: + description: The status of imported reports in the OpenCTI. + type: string + optional: false + crowdstrike-report-target-industries: + description: The reports to be imported must contain this industry/sector. The industry's names are defined by the CrowdStrike. + type: string + optional: false + crowdstrike-report-type: + description: The type of imported reports in the OpenCTI. + type: string + optional: false + crowdstrike-scopes: + description: The scopes defines what data will be imported from the CrowdStrike. + type: string + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-queue-threshold: + description: (optional) Used to determine the limit (RabbitMQ) in MB at which the connector must go into buffering mode. + type: int + optional: true + connector-run-and-terminate: + description: (optional) Launch the connector once if set to True. Takes 2 available values:TrueorFalse. + type: string + optional: true + crowdstrike-base-url: + description: (optional) The base URL for the CrowdStrike APIs. + type: string + optional: true + crowdstrike-default-x-opencti-score: + description: (optional) crowdstrike default x opencti score. + type: int + optional: true + crowdstrike-indicator-high-score: + description: (optional) If any of the low score labels are found on the indicator then this value is used as a score. + type: int + optional: true + crowdstrike-indicator-high-score-labels: + description: (optional) The labels used to determine the low score indicators. + type: string + optional: true + crowdstrike-indicator-low-score: + description: (optional) If any of the low score labels are found on the indicator then this value is used as a score. + type: int + optional: true + crowdstrike-indicator-low-score-labels: + description: (optional) The labels used to determine the low score indicators. + type: string + optional: true + crowdstrike-indicator-medium-score: + description: (optional) If any of the low score labels are found on the indicator then this value is used as a score. + type: int + optional: true + crowdstrike-indicator-medium-score-labels: + description: (optional) The labels used to determine the low score indicators. + type: string + optional: true + crowdstrike-indicator-unwanted-labels: + description: (optional) Indicators to be excluded from import based on the labels affixed to them. + type: string + optional: true + crowdstrike-tlp: + description: (optional) The TLP marking used for the imported objects in the OpenCTI. + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-crowdstrike-connector: + resource: opencti-crowdstrike-connector-image +resources: + opencti-crowdstrike-connector-image: + type: oci-image + description: OCI image for the OpenCTI CrowdStrike connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/crowdstrike/lib/charms/opencti/v0/opencti_connector.py b/connectors/crowdstrike/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/crowdstrike/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/crowdstrike/requirements.txt b/connectors/crowdstrike/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/crowdstrike/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/crowdstrike/rock/rockcraft.yaml b/connectors/crowdstrike/rock/rockcraft.yaml new file mode 100644 index 0000000..64c4e24 --- /dev/null +++ b/connectors/crowdstrike/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-crowdstrike-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI CrowdStrike Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + crowdstrike-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/crowdstrike + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-crowdstrike + + cat entrypoint.sh | grep opencti-connector-crowdstrike + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/crowdstrike/src/charm.py b/connectors/crowdstrike/src/charm.py new file mode 100755 index 0000000..91ad6b0 --- /dev/null +++ b/connectors/crowdstrike/src/charm.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI CrowdStrike connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiCrowdstrikeConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + def _gen_env(self) -> dict[str, str]: + env = super()._gen_env() + env["CONNECTOR_SCOPE"] = "crowdstrike" + return env + + +if __name__ == "__main__": + ops.main(OpenctiCrowdstrikeConnectorCharm) diff --git a/connectors/cyber_campaign/charmcraft.yaml b/connectors/cyber_campaign/charmcraft.yaml new file mode 100644 index 0000000..ed9e00a --- /dev/null +++ b/connectors/cyber_campaign/charmcraft.yaml @@ -0,0 +1,72 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-cyber-campaign-connector +title: OpenCTI APT & Cyber Campaign Charm +summary: OpenCTI APT & Cybercriminals Campaign Collection connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-log-level: + description: The log level for the connector. + type: string + optional: false + connector-run-and-terminate: + description: Whether the connector should run and terminate after execution. + type: boolean + optional: false + connector-scope: + description: The data scope of the connector. + type: string + optional: false + cyber-monitor-from-year: + description: The starting year for monitoring cyber campaigns. + type: int + optional: false + cyber-monitor-interval: + description: The interval in days, must be strictly greater than 1. + type: int + optional: false + cyber-monitor-github-token: + description: (optional) If not provided, rate limit will be very low. + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-cyber-campaign-connector: + resource: opencti-cyber-campaign-connector-image +resources: + opencti-cyber-campaign-connector-image: + type: oci-image + description: OCI image for the OpenCTI APT & Cybercriminals Campaign Collection connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/cyber_campaign/lib/charms/opencti/v0/opencti_connector.py b/connectors/cyber_campaign/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/cyber_campaign/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/cyber_campaign/requirements.txt b/connectors/cyber_campaign/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/cyber_campaign/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/cyber_campaign/rock/rockcraft.yaml b/connectors/cyber_campaign/rock/rockcraft.yaml new file mode 100644 index 0000000..77798f1 --- /dev/null +++ b/connectors/cyber_campaign/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-cyber-campaign-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI APT & Cybercriminals Campaign Collection Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + cyber-campaign-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/cyber-campaign-collection + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-cyber-campaign-collection + + cat entrypoint.sh | grep opencti-connector-cyber-campaign-collection + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/cyber_campaign/src/charm.py b/connectors/cyber_campaign/src/charm.py new file mode 100755 index 0000000..91fbebc --- /dev/null +++ b/connectors/cyber_campaign/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI APT & Cybercriminals Campaign Collection connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiCyberCampaignConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiCyberCampaignConnectorCharm) diff --git a/connectors/export_file_csv/charmcraft.yaml b/connectors/export_file_csv/charmcraft.yaml new file mode 100644 index 0000000..3fda9c2 --- /dev/null +++ b/connectors/export_file_csv/charmcraft.yaml @@ -0,0 +1,65 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-export-file-csv-connector +title: OpenCTI Export CSV File Charm +summary: OpenCTI Export CSV File connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-confidence-level: + type: int + description: (optional) the confidence level of the connector. + optional: true + export-file-csv-delimiter: + type: string + description: (optional) the delimiter of the exported CSV file. + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-export-file-csv-connector: + resource: opencti-export-file-csv-connector-image +resources: + opencti-export-file-csv-connector-image: + type: oci-image + description: OCI image for the OpenCTI Export CSV File connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/export_file_csv/lib/charms/opencti/v0/opencti_connector.py b/connectors/export_file_csv/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/export_file_csv/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/export_file_csv/requirements.txt b/connectors/export_file_csv/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/export_file_csv/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/export_file_csv/rock/rockcraft.yaml b/connectors/export_file_csv/rock/rockcraft.yaml new file mode 100644 index 0000000..ac0f1eb --- /dev/null +++ b/connectors/export_file_csv/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-export-file-csv-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Export CSV File Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + export-file-csv-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd internal-export-file/export-file-csv + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-export-file-csv + + cat entrypoint.sh | grep opencti-connector-export-file-csv + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/export_file_csv/src/charm.py b/connectors/export_file_csv/src/charm.py new file mode 100755 index 0000000..5c2a899 --- /dev/null +++ b/connectors/export_file_csv/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Export CSV File connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiExportFileCsvConnectorCharm(OpenctiConnectorCharm): + connector_type = "INTERNAL_EXPORT_FILE" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiExportFileCsvConnectorCharm) diff --git a/connectors/export_file_stix/charmcraft.yaml b/connectors/export_file_stix/charmcraft.yaml new file mode 100644 index 0000000..3de8d02 --- /dev/null +++ b/connectors/export_file_stix/charmcraft.yaml @@ -0,0 +1,61 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-export-file-stix-connector +title: OpenCTI Export STIX File Charm +summary: OpenCTI Export STIX File connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-confidence-level: + type: int + description: (optional) the confidence level of the connector. + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-export-file-stix-connector: + resource: opencti-export-file-stix-connector-image +resources: + opencti-export-file-stix-connector-image: + type: oci-image + description: OCI image for the OpenCTI Export STIX File connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/export_file_stix/lib/charms/opencti/v0/opencti_connector.py b/connectors/export_file_stix/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/export_file_stix/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/export_file_stix/requirements.txt b/connectors/export_file_stix/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/export_file_stix/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/export_file_stix/rock/rockcraft.yaml b/connectors/export_file_stix/rock/rockcraft.yaml new file mode 100644 index 0000000..0f9ebd5 --- /dev/null +++ b/connectors/export_file_stix/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-export-file-stix-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Export STIX File Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + export-file-stix-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd internal-export-file/export-file-stix + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-export-file-stix + + cat entrypoint.sh | grep opencti-connector-export-file-stix + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/export_file_stix/src/charm.py b/connectors/export_file_stix/src/charm.py new file mode 100755 index 0000000..3237285 --- /dev/null +++ b/connectors/export_file_stix/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Export STIX File connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiExportFileStixConnectorCharm(OpenctiConnectorCharm): + connector_type = "INTERNAL_EXPORT_FILE" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiExportFileStixConnectorCharm) diff --git a/connectors/export_file_txt/charmcraft.yaml b/connectors/export_file_txt/charmcraft.yaml new file mode 100644 index 0000000..bf659fd --- /dev/null +++ b/connectors/export_file_txt/charmcraft.yaml @@ -0,0 +1,61 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-export-file-txt-connector +title: OpenCTI Export TXT File Charm +summary: OpenCTI Export TXT File connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-confidence-level: + type: int + description: (optional) the confidence level of the connector. + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-export-file-txt-connector: + resource: opencti-export-file-txt-connector-image +resources: + opencti-export-file-txt-connector-image: + type: oci-image + description: OCI image for the OpenCTI Export TXT File connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/export_file_txt/lib/charms/opencti/v0/opencti_connector.py b/connectors/export_file_txt/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/export_file_txt/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/export_file_txt/requirements.txt b/connectors/export_file_txt/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/export_file_txt/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/export_file_txt/rock/rockcraft.yaml b/connectors/export_file_txt/rock/rockcraft.yaml new file mode 100644 index 0000000..8ab7136 --- /dev/null +++ b/connectors/export_file_txt/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-export-file-txt-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Export TXT File Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + export-file-txt-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd internal-export-file/export-file-txt + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-export-file-txt + + cat entrypoint.sh | grep opencti-connector-export-file-txt + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/export_file_txt/src/charm.py b/connectors/export_file_txt/src/charm.py new file mode 100755 index 0000000..ceb37a4 --- /dev/null +++ b/connectors/export_file_txt/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Export TXT File connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiExportFileTxtConnectorCharm(OpenctiConnectorCharm): + connector_type = "INTERNAL_EXPORT_FILE" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiExportFileTxtConnectorCharm) diff --git a/connectors/import_document/charmcraft.yaml b/connectors/import_document/charmcraft.yaml new file mode 100644 index 0000000..527bc75 --- /dev/null +++ b/connectors/import_document/charmcraft.yaml @@ -0,0 +1,77 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-import-document-connector +title: OpenCTI Document Import Charm +summary: OpenCTI Document Import connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-auto: + description: enable/disable auto import of report file + type: boolean + optional: false + connector-confidence-level: + description: connector confidence level, from 0 (unknown) to 100 (fully trusted). + type: int + optional: false + connector-only-contextual: + description: true only extract data related to an entity (a report, a threat actor, etc.) + type: boolean + optional: false + connector-scope: + description: connector scope + type: string + optional: false + connector-validate-before-import: + description: validate any bundle before import. + type: boolean + optional: false + import-document-create-indicator: + description: import document create indicator + type: boolean + optional: false + connector-log-level: + description: log level for this connector. + type: string + default: info + optional: false + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-import-document-connector: + resource: opencti-import-document-connector-image +resources: + opencti-import-document-connector-image: + type: oci-image + description: OCI image for the OpenCTI Document Import connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/import_document/lib/charms/opencti/v0/opencti_connector.py b/connectors/import_document/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/import_document/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/import_document/requirements.txt b/connectors/import_document/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/import_document/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/import_document/rock/rockcraft.yaml b/connectors/import_document/rock/rockcraft.yaml new file mode 100644 index 0000000..135dbc5 --- /dev/null +++ b/connectors/import_document/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-import-document-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Document Import Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + import-document-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd internal-import-file/import-document + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-import-document + + cat entrypoint.sh | grep opencti-connector-import-document + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/import_document/src/charm.py b/connectors/import_document/src/charm.py new file mode 100755 index 0000000..e3b4795 --- /dev/null +++ b/connectors/import_document/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Document Import connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiImportDocumentConnectorCharm(OpenctiConnectorCharm): + connector_type = "INTERNAL_IMPORT_FILE" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiImportDocumentConnectorCharm) diff --git a/connectors/import_file_stix/charmcraft.yaml b/connectors/import_file_stix/charmcraft.yaml new file mode 100644 index 0000000..d740aee --- /dev/null +++ b/connectors/import_file_stix/charmcraft.yaml @@ -0,0 +1,69 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-import-file-stix-connector +title: OpenCTI Import File Stix Charm +summary: OpenCTI Import File Stix connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-auto: + description: enable/disable auto-import of file + type: boolean + optional: false + connector-confidence-level: + description: from 0 (Unknown) to 100 (Fully trusted) + type: int + optional: false + connector-scope: + description: connector scope + type: string + optional: false + connector-validate-before-import: + description: validate any bundle before import + type: boolean + optional: false + connector-log-level: + description: logging level of the connector + type: string + default: info + optional: false + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-import-file-stix-connector: + resource: opencti-import-file-stix-connector-image +resources: + opencti-import-file-stix-connector-image: + type: oci-image + description: OCI image for the OpenCTI Import File Stix connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/import_file_stix/lib/charms/opencti/v0/opencti_connector.py b/connectors/import_file_stix/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/import_file_stix/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/import_file_stix/requirements.txt b/connectors/import_file_stix/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/import_file_stix/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/import_file_stix/rock/rockcraft.yaml b/connectors/import_file_stix/rock/rockcraft.yaml new file mode 100644 index 0000000..5c167e6 --- /dev/null +++ b/connectors/import_file_stix/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-import-file-stix-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Import File Stix Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + import-file-stix-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd internal-import-file/import-file-stix + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-import-file-stix + + cat entrypoint.sh | grep opencti-connector-import-file-stix + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/import_file_stix/src/charm.py b/connectors/import_file_stix/src/charm.py new file mode 100755 index 0000000..1a213e9 --- /dev/null +++ b/connectors/import_file_stix/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Import File Stix connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiImportFileStixConnectorCharm(OpenctiConnectorCharm): + connector_type = "INTERNAL_IMPORT_FILE" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiImportFileStixConnectorCharm) diff --git a/connectors/malwarebazaar/charmcraft.yaml b/connectors/malwarebazaar/charmcraft.yaml new file mode 100644 index 0000000..c489f9e --- /dev/null +++ b/connectors/malwarebazaar/charmcraft.yaml @@ -0,0 +1,76 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-malwarebazaar-connector +title: OpenCTI MalwareBazaar Charm +summary: OpenCTI MalwareBazaar Recent Additions connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-log-level: + description: The log level for the connector + type: string + optional: false + malwarebazaar-recent-additions-api-url: + description: The API URL + type: string + optional: false + malwarebazaar-recent-additions-cooldown-seconds: + description: Time to wait in seconds between subsequent requests + type: int + optional: false + malwarebazaar-recent-additions-labels-color: + description: Color to use for labels + type: string + optional: false + malwarebazaar-recent-additions-include-reporters: + description: (optional) Only download files uploaded by these reporters. (Comma separated) + type: string + optional: true + malwarebazaar-recent-additions-include-tags: + description: (optional) Only download files if any tag matches. (Comma separated) + type: string + optional: true + malwarebazaar-recent-additions-labels: + description: (optional) Labels to apply to uploaded Artifacts. (Comma separated) + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-malwarebazaar-connector: + resource: opencti-malwarebazaar-connector-image +resources: + opencti-malwarebazaar-connector-image: + type: oci-image + description: OCI image for the OpenCTI MalwareBazaar Recent Additions connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/malwarebazaar/lib/charms/opencti/v0/opencti_connector.py b/connectors/malwarebazaar/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/malwarebazaar/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/malwarebazaar/requirements.txt b/connectors/malwarebazaar/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/malwarebazaar/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/malwarebazaar/rock/rockcraft.yaml b/connectors/malwarebazaar/rock/rockcraft.yaml new file mode 100644 index 0000000..b104da8 --- /dev/null +++ b/connectors/malwarebazaar/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-malwarebazaar-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI MalwareBazaar Recent Additions Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + malwarebazaar-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/malwarebazaar-recent-additions + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-malwarebazaar-recent-additions + + cat entrypoint.sh | grep opencti-connector-malwarebazaar-recent-additions + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/malwarebazaar/src/charm.py b/connectors/malwarebazaar/src/charm.py new file mode 100755 index 0000000..42b5e3f --- /dev/null +++ b/connectors/malwarebazaar/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI MalwareBazaar Recent Additions connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiMalwarebazaarConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiMalwarebazaarConnectorCharm) diff --git a/connectors/misp_feed/charmcraft.yaml b/connectors/misp_feed/charmcraft.yaml new file mode 100644 index 0000000..bd4c330 --- /dev/null +++ b/connectors/misp_feed/charmcraft.yaml @@ -0,0 +1,157 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-misp-feed-connector +title: OpenCTI MISP Source Charm +summary: OpenCTI MISP Source connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + misp-feed-interval: + type: int + description: misp feed interval in minutes + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + aws-access-key-id: + description: (optional) Access key used to access the bucket + type: string + optional: true + aws-endpoint-url: + description: (optional) URL to specify for compatibility with other S3 buckets (MinIO) + type: string + optional: true + aws-secret-access-key: + description: (optional) Secret key used to access the bucket + type: string + optional: true + connector-run-and-terminate: + type: boolean + description: (optional) Launch the connector once if set to True + optional: true + misp-bucket-name: + description: (optional) Bucket Name where the MISP's files are stored + type: string + optional: true + misp-bucket-prefix: + description: (optional) Used to filter imports + type: string + optional: true + misp-create-tags-as-labels: + description: (optional) Whether to convert tags into labels. + type: boolean + optional: true + misp-feed-author-from-tags: + description: (optional) Whether to infer authors from tags. + type: boolean + optional: true + misp-feed-create-indicators: + description: (optional) Whether to create indicators from the MISP feed. + type: boolean + optional: true + misp-feed-create-object-observables: + description: (optional) Whether to create object observables. + type: boolean + optional: true + misp-feed-create-observables: + description: (optional) Whether to create observables from the MISP feed. + type: boolean + optional: true + misp-feed-create-reports: + description: (optional) Whether to create reports from MISP feed data. + type: boolean + optional: true + misp-feed-create-tags-as-labels: + type: boolean + description: (optional) create tags as labels (sanitize MISP tag to OpenCTI labels) + optional: true + misp-feed-guess-threat-from-tags: + description: (optional) Whether to infer threats from tags. + type: boolean + optional: true + misp-feed-import-from-date: + description: (optional) Start date for importing data from the MISP feed. + type: string + optional: true + misp-feed-import-to-ids-no-score: + description: (optional) Import data without a score to IDS. + type: boolean + optional: true + misp-feed-import-unsupported-observables-as-text: + description: (optional) Import unsupported observables as plain text. + type: boolean + optional: true + misp-feed-import-unsupported-observables-as-text-transparent: + description: (optional) Whether to import unsupported observables transparently as text. + type: boolean + optional: true + misp-feed-import-with-attachments: + description: (optional) Whether to import attachments from the feed. + type: boolean + optional: true + misp-feed-markings-from-tags: + description: (optional) Whether to infer markings from tags. + type: boolean + optional: true + misp-feed-report-type: + description: (optional) The type of reports to create from the MISP feed. + type: string + optional: true + misp-feed-source-type: + description: (optional) Source type for the MISP feed (url or s3). + type: string + optional: true + misp-feed-ssl-verify: + description: (optional) Whether to verify SSL certificates for the feed URL. + type: boolean + optional: true + misp-feed-url: + description: (optional) The URL of the MISP feed (required ifsource_typeisurl). + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-misp-feed-connector: + resource: opencti-misp-feed-connector-image +resources: + opencti-misp-feed-connector-image: + type: oci-image + description: OCI image for the OpenCTI MISP Source connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/misp_feed/lib/charms/opencti/v0/opencti_connector.py b/connectors/misp_feed/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/misp_feed/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/misp_feed/requirements.txt b/connectors/misp_feed/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/misp_feed/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/misp_feed/rock/rockcraft.yaml b/connectors/misp_feed/rock/rockcraft.yaml new file mode 100644 index 0000000..efae159 --- /dev/null +++ b/connectors/misp_feed/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-misp-feed-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI MISP Source Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + misp-feed-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/misp-feed + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-misp-feed + + cat entrypoint.sh | grep opencti-connector-misp-feed + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/misp_feed/src/charm.py b/connectors/misp_feed/src/charm.py new file mode 100755 index 0000000..2adbbeb --- /dev/null +++ b/connectors/misp_feed/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI MISP Source connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiMispFeedConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiMispFeedConnectorCharm) diff --git a/connectors/mitre/charmcraft.yaml b/connectors/mitre/charmcraft.yaml new file mode 100644 index 0000000..b8f57b9 --- /dev/null +++ b/connectors/mitre/charmcraft.yaml @@ -0,0 +1,85 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-mitre-connector +title: OpenCTI MITRE Datasets Charm +summary: OpenCTI MITRE Datasets connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + mitre-interval: + description: Number of the days between each MITRE datasets collection. + type: int + optional: false + mitre-remove-statement-marking: + description: Remove the statement MITRE marking definition. + type: boolean + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-run-and-terminate: + type: boolean + description: (optional) Launch the connector once if set to True + optional: true + mitre-capec-file-url: + description: (optional) Resource URL + type: string + optional: true + mitre-enterprise-file-url: + description: (optional) Resource URL + type: string + optional: true + mitre-ics-attack-file-url: + description: (optional) Resource URL + type: string + optional: true + mitre-mobile-attack-file-url: + description: (optional) Resource URL + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-mitre-connector: + resource: opencti-mitre-connector-image +resources: + opencti-mitre-connector-image: + type: oci-image + description: OCI image for the OpenCTI MITRE Datasets connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/mitre/lib/charms/opencti/v0/opencti_connector.py b/connectors/mitre/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/mitre/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/mitre/requirements.txt b/connectors/mitre/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/mitre/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/mitre/rock/rockcraft.yaml b/connectors/mitre/rock/rockcraft.yaml new file mode 100644 index 0000000..857bc5c --- /dev/null +++ b/connectors/mitre/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-mitre-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI MITRE Datasets Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + mitre-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/mitre + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-mitre + echo 'cd /opt/opencti-connector-mitre; python3 connector.py' > entrypoint.sh + cat entrypoint.sh | grep opencti-connector-mitre + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/mitre/src/charm.py b/connectors/mitre/src/charm.py new file mode 100755 index 0000000..fbbfc02 --- /dev/null +++ b/connectors/mitre/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI MITRE Datasets connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiMitreConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiMitreConnectorCharm) diff --git a/connectors/sekoia/charmcraft.yaml b/connectors/sekoia/charmcraft.yaml new file mode 100644 index 0000000..d609c23 --- /dev/null +++ b/connectors/sekoia/charmcraft.yaml @@ -0,0 +1,78 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-sekoia-connector +title: OpenCTI Sekoia.io Charm +summary: OpenCTI Sekoia.io connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + sekoia-api-key: + description: Sekoia API key + type: string + optional: false + sekoia-collection: + description: Sekoia collection + type: string + optional: false + sekoia-create-observables: + description: create observables from indicators + type: boolean + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + sekoia-base-url: + description: Sekoia base url + type: string + default: https://api.sekoia.io + optional: false + sekoia-start-date: + description: (optional) the date to start consuming data from. Maybe in the formats YYYY-MM-DD or YYYY-MM-DDT00:00:00 + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-sekoia-connector: + resource: opencti-sekoia-connector-image +resources: + opencti-sekoia-connector-image: + type: oci-image + description: OCI image for the OpenCTI Sekoia.io connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/sekoia/lib/charms/opencti/v0/opencti_connector.py b/connectors/sekoia/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/sekoia/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/sekoia/requirements.txt b/connectors/sekoia/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/sekoia/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/sekoia/rock/rockcraft.yaml b/connectors/sekoia/rock/rockcraft.yaml new file mode 100644 index 0000000..5d9876b --- /dev/null +++ b/connectors/sekoia/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-sekoia-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Sekoia.io Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + sekoia-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/sekoia + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-sekoia + echo 'cd /opt/opencti-connector-sekoia; python3 sekoia.py' > entrypoint.sh + cat entrypoint.sh | grep opencti-connector-sekoia + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/sekoia/src/charm.py b/connectors/sekoia/src/charm.py new file mode 100755 index 0000000..3fd9a09 --- /dev/null +++ b/connectors/sekoia/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Sekoia.io connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiSekoiaConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiSekoiaConnectorCharm) diff --git a/connectors/urlscan/charmcraft.yaml b/connectors/urlscan/charmcraft.yaml new file mode 100644 index 0000000..755acf1 --- /dev/null +++ b/connectors/urlscan/charmcraft.yaml @@ -0,0 +1,100 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-urlscan-connector +title: OpenCTI Urlscan.io Charm +summary: OpenCTI Urlscan.io connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-confidence-level: + description: The default confidence level for created relationships (0 -> 100). + type: int + optional: false + connector-log-level: + description: The log level for this connector, could be `debug`, `info`, `warn` or `error` (less verbose). + type: string + optional: false + connector-update-existing-data: + description: If an entity already exists, update its attributes with information provided by this connector. + type: boolean + optional: false + urlscan-api-key: + description: The Urlscan client secret. + type: string + optional: false + urlscan-url: + description: The Urlscan URL. + type: string + optional: false + connector-create-indicators: + description: (optional) Create indicators for each observable processed. + type: boolean + optional: true + connector-interval: + description: (optional) An interval (in seconds) for data gathering from Urlscan. + type: int + optional: true + connector-labels: + description: (optional) Comma delimited list of labels to apply to each observable. + type: string + optional: true + connector-lookback: + description: (optional) How far to look back in days if the connector has never run or the last run is older than this value. Default is 3. You should not go above 7. + type: int + optional: true + connector-tlp: + description: (optional) The TLP to apply to any indicators and observables, this could be `white`,`green`,`amber` or `red` + type: string + optional: true + urlscan-default-x-opencti-score: + description: (optional) The default x_opencti_score to use across observable/indicator types. Default is 50. + type: int + optional: true + urlscan-x-opencti-score-domain: + description: (optional) The x_opencti_score to use across Domain-Name observable and indicators. Defaults to default score. + type: int + optional: true + urlscan-x-opencti-score-url: + description: (optional) The x_opencti_score to use across Url observable and indicators. Defaults to default score. + type: integer + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-urlscan-connector: + resource: opencti-urlscan-connector-image +resources: + opencti-urlscan-connector-image: + type: oci-image + description: OCI image for the OpenCTI Urlscan.io connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/urlscan/lib/charms/opencti/v0/opencti_connector.py b/connectors/urlscan/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/urlscan/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/urlscan/requirements.txt b/connectors/urlscan/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/urlscan/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/urlscan/rock/rockcraft.yaml b/connectors/urlscan/rock/rockcraft.yaml new file mode 100644 index 0000000..f605e2e --- /dev/null +++ b/connectors/urlscan/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-urlscan-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI Urlscan.io Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + urlscan-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/urlscan + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-urlscan + + cat entrypoint.sh | grep opencti-connector-urlscan + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/urlscan/src/charm.py b/connectors/urlscan/src/charm.py new file mode 100755 index 0000000..f41b67b --- /dev/null +++ b/connectors/urlscan/src/charm.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI Urlscan.io connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiUrlscanConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + def _gen_env(self) -> dict[str, str]: + env = super()._gen_env() + env["CONNECTOR_SCOPE"] = "threatmatch" + return env + + +if __name__ == "__main__": + ops.main(OpenctiUrlscanConnectorCharm) diff --git a/connectors/urlscan_enrichment/charmcraft.yaml b/connectors/urlscan_enrichment/charmcraft.yaml new file mode 100644 index 0000000..ab1a47e --- /dev/null +++ b/connectors/urlscan_enrichment/charmcraft.yaml @@ -0,0 +1,89 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-urlscan-enrichment-connector +title: OpenCTI URLScan Enrichment Charm +summary: OpenCTI URLScan Enrichment connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-auto: + type: boolean + description: connector auto + optional: false + connector-scope: + type: string + description: connector scope + optional: false + urlscan-enrichment-api-base-url: + description: URLScan Base Url + type: string + optional: false + urlscan-enrichment-api-key: + description: URLScan API Key + type: string + optional: false + urlscan-enrichment-import-screenshot: + description: Allows or not the import of the screenshot of the scan submitted in URLScan to OpenCTI. + type: boolean + optional: false + urlscan-enrichment-max-tlp: + description: Do not send any data to URLScan if the TLP of the observable is greater than MAX_TLP + type: string + optional: false + urlscan-enrichment-search-filtered-by-date: + description: Allows you to filter by date available:>now-1h,>now-1d,>now-1y,[2022 TO 2023],[2022/01/01 TO 2023/12/01] + type: string + optional: false + urlscan-enrichment-visibility: + description: URLScan offers several levels of visibility for submitted scans:public,unlisted,private + type: string + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + connector-run-and-terminate: + description: (optional) Launch the connector once if set to True. Takes 2 available values:TrueorFalse + type: boolean + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-urlscan-enrichment-connector: + resource: opencti-urlscan-enrichment-connector-image +resources: + opencti-urlscan-enrichment-connector-image: + type: oci-image + description: OCI image for the OpenCTI URLScan Enrichment connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/urlscan_enrichment/lib/charms/opencti/v0/opencti_connector.py b/connectors/urlscan_enrichment/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/urlscan_enrichment/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/urlscan_enrichment/requirements.txt b/connectors/urlscan_enrichment/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/urlscan_enrichment/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/urlscan_enrichment/rock/rockcraft.yaml b/connectors/urlscan_enrichment/rock/rockcraft.yaml new file mode 100644 index 0000000..24e21f9 --- /dev/null +++ b/connectors/urlscan_enrichment/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-urlscan-enrichment-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI URLScan Enrichment Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + urlscan-enrichment-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd internal-enrichment/urlscan-enrichment + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-urlscan-enrichment + + cat entrypoint.sh | grep opencti-connector-urlscan-enrichment + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/urlscan_enrichment/src/charm.py b/connectors/urlscan_enrichment/src/charm.py new file mode 100755 index 0000000..83ebe09 --- /dev/null +++ b/connectors/urlscan_enrichment/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI URLScan Enrichment connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiUrlscanEnrichmentConnectorCharm(OpenctiConnectorCharm): + connector_type = "INTERNAL_ENRICHMENT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiUrlscanEnrichmentConnectorCharm) diff --git a/connectors/virustotal_livehunt/charmcraft.yaml b/connectors/virustotal_livehunt/charmcraft.yaml new file mode 100644 index 0000000..813846a --- /dev/null +++ b/connectors/virustotal_livehunt/charmcraft.yaml @@ -0,0 +1,109 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-virustotal-livehunt-connector +title: OpenCTI VirusTotal Livehunt Charm +summary: OpenCTI VirusTotal Livehunt Notifications connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + type: string + description: connector scope + optional: false + virustotal-livehunt-notifications-api-key: + description: Private API Key + type: string + optional: false + virustotal-livehunt-notifications-create-alert: + description: Set to true to create alerts + type: boolean + optional: false + virustotal-livehunt-notifications-create-file: + description: Set to true to create file object linked to the alerts + type: boolean + optional: false + virustotal-livehunt-notifications-create-yara-rule: + description: Set to true to create yara rule linked to the alert and the file + type: boolean + optional: false + virustotal-livehunt-notifications-delete-notification: + description: Set to true to remove livehunt notifications + type: boolean + optional: false + virustotal-livehunt-notifications-filter-with-tag: + description: Filter livehunt notifications with this tag + type: string + optional: false + virustotal-livehunt-notifications-interval-sec: + description: Time to wait in seconds between subsequent requests + type: int + optional: false + virustotal-livehunt-notifications-max-age-days: + description: Only create the alert if the first submission of the file is not older than `max_age_days` + type: int + optional: false + virustotal-livehunt-notifications-upload-artifact: + description: Set to true to upload the file to opencti + type: boolean + optional: false + connector-log-level: + type: string + description: determines the verbosity of the logs. Options are debug, info, warn, or error + default: info + optional: false + virustotal-livehunt-notifications-extensions: + description: (optional) Comma separated filter to only download files matching these extensions + type: string + optional: true + virustotal-livehunt-notifications-max-file-size: + description: (optional) Don't download files larger than this many bytes + type: int + optional: true + virustotal-livehunt-notifications-min-file-size: + description: (optional) Don't download files smaller than this many bytes + type: int + optional: true + virustotal-livehunt-notifications-min-positives: + description: (optional) Don't download files with less than this many vendors marking malicious + type: int + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-virustotal-livehunt-connector: + resource: opencti-virustotal-livehunt-connector-image +resources: + opencti-virustotal-livehunt-connector-image: + type: oci-image + description: OCI image for the OpenCTI VirusTotal Livehunt Notifications connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/virustotal_livehunt/lib/charms/opencti/v0/opencti_connector.py b/connectors/virustotal_livehunt/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/virustotal_livehunt/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/virustotal_livehunt/requirements.txt b/connectors/virustotal_livehunt/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/virustotal_livehunt/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/virustotal_livehunt/rock/rockcraft.yaml b/connectors/virustotal_livehunt/rock/rockcraft.yaml new file mode 100644 index 0000000..754bf47 --- /dev/null +++ b/connectors/virustotal_livehunt/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-virustotal-livehunt-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI VirusTotal Livehunt Notifications Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + virustotal-livehunt-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/virustotal-livehunt-notifications + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-virustotal-livehunt-notifications + + cat entrypoint.sh | grep opencti-connector-virustotal-livehunt-notifications + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/virustotal_livehunt/src/charm.py b/connectors/virustotal_livehunt/src/charm.py new file mode 100755 index 0000000..a50c26d --- /dev/null +++ b/connectors/virustotal_livehunt/src/charm.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI VirusTotal Livehunt Notifications connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiVirustotalLivehuntConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + @property + def boolean_style(self) -> str: + return "python" + + +if __name__ == "__main__": + ops.main(OpenctiVirustotalLivehuntConnectorCharm) diff --git a/connectors/vxvault/charmcraft.yaml b/connectors/vxvault/charmcraft.yaml new file mode 100644 index 0000000..4911a3e --- /dev/null +++ b/connectors/vxvault/charmcraft.yaml @@ -0,0 +1,74 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-vxvault-connector +title: OpenCTI VXVault Charm +summary: OpenCTI VXVault connector charm. +links: + documentation: https://discourse.charmhub.io + issues: https://github.com/canonical/opencti-operator/issues + source: https://github.com/canonical/opencti-operator + contact: https://launchpad.net/~canonical-is-devops + +description: | + A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators) + for deploying and managing the [OpenCTI Connectors](https://docs.opencti.io/latest/deployment/connectors/) + for the OpenCTI charm. + + This charm simplifies the configuration and maintenance of OpenCTI Connectors + across a range of environments, organize your cyber threat intelligence to + enhance and disseminate actionable insights. + +config: + options: + connector-scope: + description: connector scope + type: string + optional: false + vxvault-create-indicators: + description: vxvault create indicators + type: boolean + optional: false + vxvault-interval: + description: In days, must be strictly greater than 1 + type: int + optional: false + vxvault-ssl-verify: + description: Whether to verify SSL certificates + type: boolean + default: true + optional: false + vxvault-url: + description: vxvault url + type: string + default: https://vxvault.net/URL_List.php + optional: false + connector-log-level: + description: (optional) The log level of the connector + type: string + optional: true + + +provides: + opencti-connector: + interface: opencti_connector + limit: 1 + +type: charm +base: ubuntu@24.04 +build-base: ubuntu@24.04 +platforms: + amd64: +parts: + charm: {} + +containers: + opencti-vxvault-connector: + resource: opencti-vxvault-connector-image +resources: + opencti-vxvault-connector-image: + type: oci-image + description: OCI image for the OpenCTI VXVault connector. + +assumes: + - juju >= 3.4 diff --git a/connectors/vxvault/lib/charms/opencti/v0/opencti_connector.py b/connectors/vxvault/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/connectors/vxvault/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/connectors/vxvault/requirements.txt b/connectors/vxvault/requirements.txt new file mode 100644 index 0000000..99572b6 --- /dev/null +++ b/connectors/vxvault/requirements.txt @@ -0,0 +1 @@ +ops == 2.17.0 diff --git a/connectors/vxvault/rock/rockcraft.yaml b/connectors/vxvault/rock/rockcraft.yaml new file mode 100644 index 0000000..bb5263f --- /dev/null +++ b/connectors/vxvault/rock/rockcraft.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: opencti-vxvault-connector +base: ubuntu@24.04 +version: &version '6.4.5' +summary: OpenCTI VXVault Connector +description: >- + OpenCTI connectors are the cornerstone of the OpenCTI platform and + allow organizations to easily ingest, enrich or export data. +platforms: + amd64: + +parts: + vxvault-connector: + source: https://github.com/OpenCTI-Platform/connectors.git + source-type: git + source-tag: *version + source-depth: 1 + plugin: nil + build-packages: + - python3-pip + stage-packages: + - python3 + - libmagic1 + - libffi8 + - libxslt1.1 + - libxml2 + - python-is-python3 + override-build: | + craftctl default + mkdir -p $CRAFT_PART_INSTALL/opt + cd external-import/vxvault + cp -rp src $CRAFT_PART_INSTALL/opt/opencti-connector-vxvault + + cat entrypoint.sh | grep opencti-connector-vxvault + mkdir -p $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages + pip install \ + --target $CRAFT_PART_INSTALL/usr/local/lib/python3.12/dist-packages \ + -r $(find -name requirements.txt) + cp entrypoint.sh $CRAFT_PART_INSTALL/ diff --git a/connectors/vxvault/src/charm.py b/connectors/vxvault/src/charm.py new file mode 100755 index 0000000..174445f --- /dev/null +++ b/connectors/vxvault/src/charm.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI VXVault connector charm the service.""" + +import pathlib + +import ops + +from charms.opencti.v0.opencti_connector import OpenctiConnectorCharm + + +class OpenctiVxvaultConnectorCharm(OpenctiConnectorCharm): + connector_type = "EXTERNAL_IMPORT" + + @property + def charm_dir(self) -> pathlib.Path: + return pathlib.Path(__file__).parent.parent.absolute() + + + +if __name__ == "__main__": + ops.main(OpenctiVxvaultConnectorCharm) diff --git a/lib/charms/opencti/v0/opencti_connector.py b/lib/charms/opencti/v0/opencti_connector.py new file mode 100644 index 0000000..5ea5a96 --- /dev/null +++ b/lib/charms/opencti/v0/opencti_connector.py @@ -0,0 +1,236 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI connector charm library.""" + +# The unique Charmhub library identifier, never change it +LIBID = "312661b5c30e4aeba8767706f3974899" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft publish-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +import abc +import os +import pathlib +import urllib.parse +import uuid + +import ops +import yaml + + +class NotReady(Exception): + """The OpenCTI connector is not ready.""" + + +class OpenctiConnectorCharm(ops.CharmBase, abc.ABC): + """OpenCTI connector base charm.""" + + @property + @abc.abstractmethod + def connector_type(self) -> str: + """The OpenCTI connector type. + + Can be either "EXTERNAL_IMPORT", "INTERNAL_ENRICHMENT", "INTERNAL_IMPORT_FILE", + "INTERNAL_EXPORT_FILE" or "STREAM". + + Returns: the connector type. + """ + pass + + @property + @abc.abstractmethod + def charm_dir(self) -> pathlib.Path: + """Return the charm directory (the one with charmcraft.yaml in it).""" + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._reconcile) + self.framework.observe(self.on["opencti-connector"].relation_changed, self._reconcile) + self.framework.observe(self.on.secret_changed, self._reconcile) + self.framework.observe(self.on.upgrade_charm, self._reconcile) + self.framework.observe(self.on[self.meta.name].pebble_ready, self._reconcile) + + @property + def boolean_style(self) -> str: + """Dictate how boolean-typed configurations should translate to environment variable values. + + The style should be either "json" for true/false or "python" for True/False. + + Returns: "json" or "python" + """ + return "json" + + def _config_metadata(self) -> dict: + """Get charm configuration metadata. + + Returns: + The charm configuration metadata. + + Raises: + RuntimeError: If charm metadata file doesn't exist. + """ + config_file = self.charm_dir / "config.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["options"] + config_file = self.charm_dir / "charmcraft.yaml" + if config_file.exists(): + return yaml.safe_load(config_file.read_text())["config"]["options"] + raise RuntimeError("charm configuration metadata doesn't exist") + + def kebab_to_constant(self, name: str) -> str: + """Convert kebab case to constant case + + Args: + name: Kebab case name. + + Returns: + Input in constant case. + """ + return name.replace("-", "_").upper() + + def _check_config(self) -> None: + """Check if required charm configurations are ready. + + Raises: + NotReady: If some charm configurations isn't ready. + """ + missing = [] + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None and not config_meta["description"].strip().startswith("(optional)"): + missing.append(config) + if missing: + raise NotReady("missing configurations: {}".format(", ".join(missing))) + + def _check_integration(self) -> None: + """Check if required charm integrations are ready. + + Raises: + NotReady: If some charm integrations isn't ready. + """ + integration = self.model.get_relation("opencti-connector") + if integration is None: + raise NotReady("missing opencti-connector integration") + + def _reconcile(self, _) -> None: + """Reconcile the charm.""" + try: + if self.app.planned_units() != 1: + self.unit.status = ops.BlockedStatus( + "connector charm cannot have multiple units, " + "scale down using the `juju scale` command" + ) + return + self._check_config() + self._check_integration() + self._reconcile_integration() + self._reconcile_connector() + self.unit.status = ops.ActiveStatus() + except NotReady as exc: + self.unit.status = ops.WaitingStatus(str(exc)) + + def _reconcile_integration(self) -> None: + """Reconcile the charm integrations.""" + if self.unit.is_leader(): + integration = self.model.get_relation("opencti-connector") + data = integration.data[self.app] + data.update( + { + "connector_charm_name": self.meta.name, + "connector_type": self.connector_type, + } + ) + if "connector_id" not in data: + data["connector_id"] = str(uuid.uuid4()) + + def _gen_env(self) -> dict[str, str]: + """Generate environment variables for the opencti connector service. + + Returns: + Environment variables. + """ + integration = self.model.get_relation("opencti-connector") + integration_data = integration.data[integration.app] + opencti_url, opencti_token_id = ( + integration_data.get("opencti_url"), + integration_data.get("opencti_token"), + ) + if not opencti_url or not opencti_token_id: + raise NotReady("waiting for opencti-connector integration") + opencti_token_secret = self.model.get_secret(id=opencti_token_id) + opencti_token = opencti_token_secret.get_content(refresh=True)["token"] + environment = { + "OPENCTI_URL": opencti_url, + "OPENCTI_TOKEN": opencti_token, + "CONNECTOR_ID": integration.data[self.app]["connector_id"], + "CONNECTOR_NAME": self.app.name, + "CONNECTOR_TYPE": self.connector_type, + } + + for config, config_meta in self._config_metadata().items(): + value = self.config.get(config) + if value is None: + continue + environment[self.kebab_to_constant(config)] = str(value) + if self.boolean_style == "json" and isinstance(value, bool): + environment[self.kebab_to_constant(config)] = str(value).lower() + + environment.update(self._get_proxy_environment(opencti_url)) + + return environment + + def _get_proxy_environment(self, opencti_url: str) -> dict[str, str]: + """Get proxy environment variables. + + Args: + opencti_url: OpenCTI URL. + + Returns: + proxy environment variables. + """ + environment = {} + http_proxy = os.environ.get("JUJU_CHARM_HTTP_PROXY") + https_proxy = os.environ.get("JUJU_CHARM_HTTPS_PROXY") + no_proxy = os.environ.get("JUJU_CHARM_NO_PROXY") + if http_proxy: + environment["HTTP_PROXY"] = http_proxy + environment["http_proxy"] = http_proxy + if https_proxy: + environment["HTTPS_PROXY"] = https_proxy + environment["https_proxy"] = https_proxy + no_proxy_list = no_proxy.split(",") if no_proxy else [] + if http_proxy or https_proxy: + opencti_host = urllib.parse.urlparse(opencti_url).hostname + no_proxy_list.append(opencti_host) + environment["NO_PROXY"] = ",".join(no_proxy_list) + environment["no_proxy"] = ",".join(no_proxy_list) + return environment + + def _reconcile_connector(self) -> None: + """Reconcile connector service.""" + container = self.unit.get_container(self.meta.name) + if not container.can_connect(): + raise NotReady("waiting for container ready") + container.add_layer( + "connector", + layer=ops.pebble.LayerDict( + summary=self.meta.name, + description=self.meta.name, + services={ + "connector": { + "startup": "enabled", + "on-failure": "restart", + "override": "replace", + "command": "bash /entrypoint.sh", + "environment": self._gen_env(), + }, + }, + ), + combine=True, + ) + container.replan() diff --git a/opencti_rock/rockcraft.yaml b/opencti_rock/rockcraft.yaml index 84a666c..dd89ed4 100644 --- a/opencti_rock/rockcraft.yaml +++ b/opencti_rock/rockcraft.yaml @@ -3,7 +3,7 @@ name: opencti base: ubuntu@24.04 -version: &version '6.4.1' +version: &version '6.4.5' summary: Open Cyber Threat Intelligence Platform description: >- OpenCTI is an open source platform allowing organizations to manage their diff --git a/pyproject.toml b/pyproject.toml index 3cc6d51..2d3c16e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ branch = true # Formatting tools configuration [tool.black] line-length = 99 -target-version = ["py38"] +target-version = ["py312"] [tool.coverage.report] show_missing = true diff --git a/renovate.json b/renovate.json index e6c587e..867dcee 100644 --- a/renovate.json +++ b/renovate.json @@ -1,7 +1,8 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base" + "config:base", + "group:all" ], "regexManagers": [ { diff --git a/requirements.txt b/requirements.txt index 96cd09c..76ab9c8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -ops >= 2.2.0 -requests == 2.32.3 +ops == 2.17.0 +gql[requests] == 3.5.0 diff --git a/scripts/gen_connector_charm.py b/scripts/gen_connector_charm.py new file mode 100644 index 0000000..f8c01da --- /dev/null +++ b/scripts/gen_connector_charm.py @@ -0,0 +1,1038 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +import operator +import pathlib +import textwrap +from typing import Callable + +import jinja2 +import requests +import markdown +import yaml + +from bs4 import BeautifulSoup + +_CONNECTOR_GENERATORS = {} + + +def connector_generator(name: str) -> Callable: + """Decorator for marking connector generators.""" + + def decorator(func: Callable) -> Callable: + _CONNECTOR_GENERATORS[name] = func + return func + + return decorator + + +DEFAULT_CONFIG = { + "connector-scope": { + "type": "string", + "description": "connector scope", + "optional": False, + }, + "connector-log-level": { + "type": "string", + "description": "determines the verbosity of the logs. Options are debug, info, warn, or error", + "default": "info", + "optional": False, + }, +} + +CHARM_MANAGED_ENV = { + "OPENCTI_URL", + "OPENCTI_TOKEN", + "CONNECTOR_ID", + "CONNECTOR_NAME", +} + + +def constant_to_kebab(string: str) -> str: + """Convert names in constant case to kebab case.""" + return string.replace("_", "-").lower() + + +def kebab_to_pascal(string: str) -> str: + """Convert names in kebab case to pascal case.""" + words = string.split("-") + return "".join(word.capitalize() for word in words) + + +def kebab_to_snake(string: str) -> str: + """Convert names in kebab case to snake case.""" + return string.replace("-", "_") + + +def extract_tables(doc) -> list[dict[str, str]]: + """Extract table rows from a markdown document.""" + html = markdown.markdown(doc, extensions=["tables"]) + soup = BeautifulSoup(html, "html.parser") + tables = soup.find_all("table") + rows = [] + for table in tables: + headers = [th.get_text(strip=True) for th in table.find_all("th")] + for row in table.find_all("tr"): + cells = row.find_all(["td"]) + if len(cells) == len(headers): + row_data = { + headers[i].lower(): cells[i].get_text(strip=True) for i in range(len(headers)) + } + rows.append(row_data) + return rows + + +def extract_template_configs(doc_url: str) -> dict: + """Extract OpenCTI connector configuration from connector document derived from document template.""" + response = requests.get(doc_url, timeout=10) + response.raise_for_status() + rows = extract_tables(response.text) + result = {} + for row in rows: + name = row["docker environment variable"] + if name in CHARM_MANAGED_ENV: + continue + is_mandatory = row["mandatory"].lower() + assert is_mandatory in ("yes", "no") + is_mandatory = is_mandatory == "yes" + description = row["description"] + if not is_mandatory: + description = "(optional) " + description + config_type = "string" + if row["default"].lower() in ("true", "false"): + config_type = "boolean" + if row["default"].isdigit(): + config_type = "int" + result[constant_to_kebab(name)] = { + "description": description, + "type": config_type, + "optional": not is_mandatory, + } + result.update(DEFAULT_CONFIG) + return result + + +def sort_config(options: dict) -> dict: + """Sorting configuration options, first mandatory, then optional, alphabetically.""" + mandatory = {k: v for k, v in options.items() if not v["optional"] and "default" not in v} + mandatory_with_default = { + k: v for k, v in options.items() if not v["optional"] and "default" in v + } + optional = { + k: v for k, v in options.items() if k not in mandatory and k not in mandatory_with_default + } + sorted_options = {} + sorted_options.update(sorted(mandatory.items(), key=operator.itemgetter(0))) + sorted_options.update(sorted(mandatory_with_default.items(), key=operator.itemgetter(0))) + sorted_options.update(sorted(optional.items(), key=operator.itemgetter(0))) + return sorted_options + + +def render_template( + *, + name: str, + connector_type: str, + version: str, + display_name: str, + config: dict, + output_dir: pathlib.Path, + connector_name: str | None = None, + display_name_short: str | None = None, + charm_override: str = "", + generate_entrypoint: str = "", + install_location: str | None = None, + template_dir: pathlib.Path = pathlib.Path("connector-template"), +) -> None: + """Render the connector template. + + Args: + name: The connector charm name. + connector_type: The type of connector. + version: The version of the connector. + display_name: The display name of the connector. + config: The configuration for the connector charm. + output_dir: The output directory for the connector charm. + connector_name: The name of the connector, defaults to the connector charm name if not set. + display_name_short: The short version of the connector display name, defaults to display_name if not set. + charm_override: A Python snippet to append after the connector charm class. + generate_entrypoint: A shell script snippet to generate `entrypoint.sh` in Rock. + install_location: The install location of the connector inside Rock. + template_dir: The directory containing the connector template. + """ + if "_" in name or not name.islower(): + raise ValueError(f"connector name should be in kebab case: {name}") + connector_name = connector_name or name + display_name_short = display_name_short or display_name + output_dir.mkdir(exist_ok=True) + + for source in template_dir.glob("**/*"): + file = source.relative_to(template_dir) + if "__pycache__" in str(file): + continue + output = output_dir / file + if source.is_dir(): + output.mkdir(exist_ok=True) + continue + if not str(file).endswith(".j2"): + output.write_bytes(source.read_bytes()) + continue + + output = pathlib.Path(str(output).removesuffix(".j2")) + template = jinja2.Template(source.read_text(), keep_trailing_newline=True) + template.globals["kebab_to_pascal"] = kebab_to_pascal + template.globals["constant_to_kebab"] = constant_to_kebab + + output.write_text( + template.render( + name=name, + connector_name=connector_name, + connector_type=connector_type, + version=version, + display_name=display_name, + display_name_short=( + display_name if display_name_short is None else display_name_short + ), + config=yaml.safe_dump( + {"config": {"options": sort_config(config)}}, width=99999, sort_keys=False + ), + charm_override=charm_override, + install_location=( + install_location if install_location else f"opencti-connector-{connector_name}" + ), + generate_entrypoint=generate_entrypoint, + ), + encoding="utf-8", + ) + + (output_dir / "lib/charms/opencti/v0").mkdir(parents=True, exist_ok=True) + (output_dir / "lib/charms/opencti/v0/opencti_connector.py").write_bytes( + pathlib.Path("lib/charms/opencti/v0/opencti_connector.py").read_bytes() + ) + (output_dir / "src/charm.py").chmod(0o755) + + +@connector_generator("abuseipdb-ipblacklist") +def generate_abuseipdb_ipblacklist_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti abuseipdb-ipblacklist connector + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/abuseipdb-ipblacklist + """ + render_template( + name="abuseipdb-ipblacklist", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="abuseipdb ipblacklist", + output_dir=location, + config={ + **DEFAULT_CONFIG, + "abuseipdb-url": { + "description": "the Abuse IPDB URL", + "type": "string", + "optional": False, + "default": "https://api.abuseipdb.com/api/v2/blacklist", + }, + "abuseipdb-api-key": { + "description": "Abuse IPDB API KEY", + "optional": False, + "type": "string", + }, + "abuseipdb-score": { + "description": "AbuseIPDB Score Limitation", + "optional": False, + "type": "int", + }, + "abuseipdb-limit": { + "description": "limit number of result itself", + "optional": False, + "type": "int", + }, + "abuseipdb-interval": { + "description": "interval between 2 collect itself", + "optional": False, + "type": "int", + }, + }, + install_location="abuseipdb-ipblacklist", + ) + + +@connector_generator("alienvault") +def generate_alienvault_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti alienvault connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/alienvault + """ + config = extract_template_configs( + "https://raw.githubusercontent.com/OpenCTI-Platform/connectors" + f"/refs/tags/{version}/external-import/alienvault/README.md" + ) + config["alienvault-interval-sec"] = { + "description": "alienvault interval seconds", + "type": "int", + "optional": False, + } + render_template( + name="alienvault", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="AlienVault", + output_dir=location, + config=config, + ) + + +@connector_generator("cisa-kev") +def generate_cisa_known_exploited_vulnerabilities_connector( + location: pathlib.Path, version: str +) -> None: + """Generate opencti cisa-known-exploited-vulnerabilities (cisa-kev) connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/cisa-known-exploited-vulnerabilities + """ + config = extract_template_configs( + "https://raw.githubusercontent.com/OpenCTI-Platform/connectors" + f"/refs/tags/{version}/external-import/cisa-known-exploited-vulnerabilities/README.md" + ) + config["cisa-create-infrastructures"]["type"] = "boolean" + render_template( + name="cisa-kev", + connector_name="cisa-known-exploited-vulnerabilities", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="CISA Known Exploited Vulnerabilities", + display_name_short="CISA KEV", + output_dir=location, + config=config, + ) + + +def extract_crowdstrike_configs(doc_url: str) -> dict: + """Extract crowdstrike connector config from the crowdstrike connector document.""" + response = requests.get(doc_url, timeout=10) + response.raise_for_status() + rows = extract_tables(response.text) + result = {} + for row in rows: + name = row["docker environment variable"] + if name in CHARM_MANAGED_ENV: + continue + is_mandatory = row["mandatory"].lower() + assert is_mandatory in ("yes", "no") + is_mandatory = is_mandatory == "yes" + description = row["description"] + if not is_mandatory: + description = "(optional) " + description + config_type = "int" if (row["example"].isdigit() or row["default"].isdigit()) else "string" + result[constant_to_kebab(name)] = { + "description": description, + "type": config_type, + "optional": not is_mandatory, + } + result.update(DEFAULT_CONFIG) + del result["connector-scope"] + result["crowdstrike-default-x-opencti-score"] = { + "description": "(optional) crowdstrike default x opencti score.", + "type": "int", + "optional": True, + } + return result + + +@connector_generator("crowdstrike") +def gen_crowdstrike_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti crowdstrike connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/crowdstrike + """ + render_template( + name="crowdstrike", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="CrowdStrike", + config=extract_crowdstrike_configs( + "https://raw.githubusercontent.com/OpenCTI-Platform/connectors" + f"/refs/tags/{version}/external-import/crowdstrike/README.md" + ), + output_dir=location, + charm_override=textwrap.dedent( + """\ + def _gen_env(self) -> dict[str, str]: + env = super()._gen_env() + env["CONNECTOR_SCOPE"] = "crowdstrike" + return env + """ + ), + ) + + +@connector_generator("cyber-campaign") +def gen_cyber_campaign_collection_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti cyber-campaign-collection (cyber-campaign) connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/cyber-campaign-collection + """ + render_template( + name="cyber-campaign", + connector_name="cyber-campaign-collection", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="APT & Cybercriminals Campaign Collection", + display_name_short="APT & Cyber Campaign", + output_dir=location, + config={ + "connector-scope": { + "description": "The data scope of the connector.", + "type": "string", + "optional": False, + }, + "connector-run-and-terminate": { + "description": "Whether the connector should run and terminate after execution.", + "type": "boolean", + "optional": False, + }, + "connector-log-level": { + "description": "The log level for the connector.", + "type": "string", + "optional": False, + }, + "cyber-monitor-github-token": { + "description": "(optional) If not provided, rate limit will be very low.", + "type": "string", + "optional": True, + }, + "cyber-monitor-from-year": { + "description": "The starting year for monitoring cyber campaigns.", + "type": "int", + "optional": False, + }, + "cyber-monitor-interval": { + "description": "The interval in days, must be strictly greater than 1.", + "type": "int", + "optional": False, + }, + }, + ) + + +_FILE_EXPORTER_CONFIGS = { + **DEFAULT_CONFIG, + "connector-confidence-level": { + "type": "int", + "description": "(optional) the confidence level of the connector.", + "optional": True, + }, +} + + +@connector_generator("export-file-csv") +def gen_export_file_csv_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti export-file-csv connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/internal-export-file/export-file-csv + """ + render_template( + name="export-file-csv", + connector_type="INTERNAL_EXPORT_FILE", + version=version, + display_name="Export CSV File", + output_dir=location, + config={ + **_FILE_EXPORTER_CONFIGS, + "export-file-csv-delimiter": { + "type": "string", + "description": "(optional) the delimiter of the exported CSV file.", + "optional": True, + }, + }, + ) + + +@connector_generator("export-file-stix") +def gen_export_file_stix_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti export-file-stix connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/internal-export-file/export-file-stix + """ + render_template( + name="export-file-stix", + connector_type="INTERNAL_EXPORT_FILE", + version=version, + display_name="Export STIX File", + output_dir=location, + config=_FILE_EXPORTER_CONFIGS, + ) + + +@connector_generator("export-file-txt") +def gen_export_file_txt_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti export-file-txt connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/internal-export-file/export-file-txt + """ + render_template( + name="export-file-txt", + connector_type="INTERNAL_EXPORT_FILE", + version=version, + display_name="Export TXT File", + output_dir=location, + config=_FILE_EXPORTER_CONFIGS, + ) + + +@connector_generator("import-document") +def gen_import_document(location: pathlib.Path, version: str) -> None: + """Generate opencti import-document connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/internal-import-file/import-document + """ + render_template( + name="import-document", + connector_type="INTERNAL_IMPORT_FILE", + version=version, + display_name="Document Import", + output_dir=location, + config={ + "connector-only-contextual": { + "description": "true only extract data related to an entity (a report, a threat actor, etc.)", + "type": "boolean", + "optional": False, + }, + "connector-auto": { + "description": "enable/disable auto import of report file", + "type": "boolean", + "optional": False, + }, + "connector-scope": { + "description": "connector scope", + "type": "string", + "optional": False, + }, + "connector-confidence-level": { + "description": "connector confidence level, from 0 (unknown) to 100 (fully trusted).", + "type": "int", + "optional": False, + }, + "connector-log-level": { + "description": "log level for this connector.", + "type": "string", + "default": "info", + "optional": False, + }, + "connector-validate-before-import": { + "description": "validate any bundle before import.", + "type": "boolean", + "optional": False, + }, + "import-document-create-indicator": { + "description": "import document create indicator", + "type": "boolean", + "optional": False, + }, + }, + ) + + +@connector_generator("import-file-stix") +def gen_import_file_stix_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti import-file-stix connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/internal-import-file/import-file-stix + """ + render_template( + name="import-file-stix", + connector_type="INTERNAL_IMPORT_FILE", + version=version, + display_name="Import File Stix", + output_dir=location, + config={ + "connector-validate-before-import": { + "description": "validate any bundle before import", + "type": "boolean", + "optional": False, + }, + "connector-scope": { + "description": "connector scope", + "type": "string", + "optional": False, + }, + "connector-auto": { + "description": "enable/disable auto-import of file", + "type": "boolean", + "optional": False, + }, + "connector-confidence-level": { + "description": "from 0 (Unknown) to 100 (Fully trusted)", + "type": "int", + "optional": False, + }, + "connector-log-level": { + "description": "logging level of the connector", + "type": "string", + "default": "info", + "optional": False, + }, + }, + ) + + +@connector_generator("malwarebazaar") +def gen_malwarebazaar_recent_additions_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti malwarebazaar-recent-additions (malwarebazaar) connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/malwarebazaar-recent-additions + """ + render_template( + name="malwarebazaar", + connector_name="malwarebazaar-recent-additions", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="MalwareBazaar Recent Additions", + display_name_short="MalwareBazaar", + output_dir=location, + config={ + "connector-log-level": { + "description": "The log level for the connector", + "type": "string", + "optional": False, + }, + "malwarebazaar-recent-additions-api-url": { + "description": "The API URL", + "type": "string", + "optional": False, + }, + "malwarebazaar-recent-additions-cooldown-seconds": { + "description": "Time to wait in seconds between subsequent requests", + "type": "int", + "optional": False, + }, + "malwarebazaar-recent-additions-include-tags": { + "description": "(optional) Only download files if any tag matches. (Comma separated)", + "type": "string", + "optional": True, + }, + "malwarebazaar-recent-additions-include-reporters": { + "description": "(optional) Only download files uploaded by these reporters. (Comma separated)", + "type": "string", + "optional": True, + }, + "malwarebazaar-recent-additions-labels": { + "description": "(optional) Labels to apply to uploaded Artifacts. (Comma separated)", + "type": "string", + "optional": True, + }, + "malwarebazaar-recent-additions-labels-color": { + "description": "Color to use for labels", + "type": "string", + "optional": False, + }, + }, + ) + + +@connector_generator("misp-feed") +def gen_misp_feed_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti misp-feed connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/misp-feed + """ + config = extract_template_configs( + "https://raw.githubusercontent.com/OpenCTI-Platform/connectors" + f"/refs/tags/{version}/external-import/misp-feed/README.md" + ) + del config["connector-type"] + config["misp-feed-create-indicators"]["type"] = "boolean" + config["misp-feed-create-observables"]["type"] = "boolean" + config["misp-feed-import-to-ids-no-score"]["type"] = "boolean" + config["connector-run-and-terminate"] = { + "type": "boolean", + "description": "(optional) Launch the connector once if set to True", + "optional": True, + } + config["misp-feed-interval"] = { + "type": "int", + "description": "misp feed interval in minutes", + "optional": False, + } + config["misp-feed-create-tags-as-labels"] = { + "type": "boolean", + "description": "(optional) create tags as labels (sanitize MISP tag to OpenCTI labels)", + "optional": True, + } + render_template( + name="misp-feed", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="MISP Source", + output_dir=location, + config=config, + ) + + +@connector_generator("mitre") +def gen_mitre_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti mitre connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/mitre + """ + render_template( + name="mitre", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="MITRE Datasets", + output_dir=location, + config={ + "connector-run-and-terminate": { + "type": "boolean", + "description": "(optional) Launch the connector once if set to True", + "optional": True, + }, + "mitre-interval": { + "description": "Number of the days between each MITRE datasets collection.", + "type": "int", + "optional": False, + }, + "mitre-remove-statement-marking": { + "description": "Remove the statement MITRE marking definition.", + "type": "boolean", + "optional": False, + }, + "mitre-enterprise-file-url": { + "description": "(optional) Resource URL", + "type": "string", + "optional": True, + }, + "mitre-mobile-attack-file-url": { + "description": "(optional) Resource URL", + "type": "string", + "optional": True, + }, + "mitre-ics-attack-file-url": { + "description": "(optional) Resource URL", + "type": "string", + "optional": True, + }, + "mitre-capec-file-url": { + "description": "(optional) Resource URL", + "type": "string", + "optional": True, + }, + **DEFAULT_CONFIG, + }, + generate_entrypoint="echo 'cd /opt/opencti-connector-mitre; python3 connector.py' > entrypoint.sh", + ) + + +@connector_generator("sekoia") +def gen_sekoia_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti sekoia connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/sekoia + """ + render_template( + name="sekoia", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="Sekoia.io", + output_dir=location, + config={ + **DEFAULT_CONFIG, + "sekoia-base-url": { + "description": "Sekoia base url", + "type": "string", + "default": "https://api.sekoia.io", + "optional": False, + }, + "sekoia-api-key": { + "description": "Sekoia API key", + "type": "string", + "optional": False, + }, + "sekoia-collection": { + "description": "Sekoia collection", + "type": "string", + "optional": False, + }, + "sekoia-start-date": { + "description": "(optional) the date to start consuming data from. Maybe in the formats YYYY-MM-DD or YYYY-MM-DDT00:00:00", + "type": "string", + "optional": True, + }, + "sekoia-create-observables": { + "description": "create observables from indicators", + "type": "boolean", + "optional": False, + }, + }, + generate_entrypoint="echo 'cd /opt/opencti-connector-sekoia; python3 sekoia.py' > entrypoint.sh", + ) + + +@connector_generator("urlscan") +def genc_urlscan_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti urlscan connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/urlscan + """ + render_template( + name="urlscan", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="Urlscan.io", + output_dir=location, + config={ + "connector-confidence-level": { + "description": "The default confidence level for created relationships (0 -> 100).", + "type": "int", + "optional": False, + }, + "connector-update-existing-data": { + "description": "If an entity already exists, update its attributes with information provided by this connector.", + "type": "boolean", + "optional": False, + }, + "connector-log-level": { + "description": "The log level for this connector, could be `debug`, `info`, `warn` or `error` (less verbose).", + "type": "string", + "optional": False, + }, + "connector-create-indicators": { + "description": "(optional) Create indicators for each observable processed.", + "type": "boolean", + "optional": True, + }, + "connector-tlp": { + "description": "(optional) The TLP to apply to any indicators and observables, this could be `white`,`green`,`amber` or `red`", + "type": "string", + "optional": True, + }, + "connector-labels": { + "description": "(optional) Comma delimited list of labels to apply to each observable.", + "type": "string", + "optional": True, + }, + "connector-interval": { + "description": "(optional) An interval (in seconds) for data gathering from Urlscan.", + "type": "int", + "optional": True, + }, + "connector-lookback": { + "description": "(optional) How far to look back in days if the connector has never run or the last run is older than this value. Default is 3. You should not go above 7.", + "type": "int", + "optional": True, + }, + "urlscan-url": { + "description": "The Urlscan URL.", + "type": "string", + "optional": False, + }, + "urlscan-api-key": { + "description": "The Urlscan client secret.", + "type": "string", + "optional": False, + }, + "urlscan-default-x-opencti-score": { + "description": "(optional) The default x_opencti_score to use across observable/indicator types. Default is 50.", + "type": "int", + "optional": True, + }, + "urlscan-x-opencti-score-domain": { + "description": "(optional) The x_opencti_score to use across Domain-Name observable and indicators. Defaults to default score.", + "type": "int", + "optional": True, + }, + "urlscan-x-opencti-score-url": { + "description": "(optional) The x_opencti_score to use across Url observable and indicators. Defaults to default score.", + "type": "integer", + "optional": True, + }, + }, + charm_override=textwrap.dedent( + """\ + def _gen_env(self) -> dict[str, str]: + env = super()._gen_env() + env["CONNECTOR_SCOPE"] = "threatmatch" + return env + """ + ), + ) + + +@connector_generator("urlscan-enrichment") +def gen_urlscan_enrichment_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti urlscan-enrichment connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/internal-enrichment/urlscan-enrichment + """ + config = extract_template_configs( + "https://raw.githubusercontent.com/OpenCTI-Platform/connectors" + f"/refs/tags/{version}/internal-enrichment/urlscan-enrichment/README.md" + ) + config["connector-auto"] = { + "type": "boolean", + "description": "connector auto", + "optional": False, + } + render_template( + name="urlscan-enrichment", + connector_type="INTERNAL_ENRICHMENT", + version=version, + display_name="URLScan Enrichment", + output_dir=location, + config=config, + ) + + +@connector_generator("virustotal-livehunt") +def gen_virustotal_livehunt_notifications_connector(location: pathlib.Path, version: str) -> None: + """Generate opencti virustotal-livehunt-notifications (virustotal-livehunt) connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/virustotal-livehunt-notifications + """ + render_template( + name="virustotal-livehunt", + connector_name="virustotal-livehunt-notifications", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="VirusTotal Livehunt Notifications", + display_name_short="VirusTotal Livehunt", + output_dir=location, + config={ + **DEFAULT_CONFIG, + "virustotal-livehunt-notifications-api-key": { + "description": "Private API Key", + "type": "string", + "optional": False, + }, + "virustotal-livehunt-notifications-interval-sec": { + "description": "Time to wait in seconds between subsequent requests", + "type": "int", + "optional": False, + }, + "virustotal-livehunt-notifications-create-alert": { + "description": "Set to true to create alerts", + "type": "boolean", + "optional": False, + }, + "virustotal-livehunt-notifications-extensions": { + "description": "(optional) Comma separated filter to only download files matching these extensions", + "type": "string", + "optional": True, + }, + "virustotal-livehunt-notifications-min-file-size": { + "description": "(optional) Don't download files smaller than this many bytes", + "type": "int", + "optional": True, + }, + "virustotal-livehunt-notifications-max-file-size": { + "description": "(optional) Don't download files larger than this many bytes", + "type": "int", + "optional": True, + }, + "virustotal-livehunt-notifications-max-age-days": { + "description": "Only create the alert if the first submission of the file is not older than `max_age_days`", + "type": "int", + "optional": False, + }, + "virustotal-livehunt-notifications-min-positives": { + "description": "(optional) Don't download files with less than this many vendors marking malicious", + "type": "int", + "optional": True, + }, + "virustotal-livehunt-notifications-create-file": { + "description": "Set to true to create file object linked to the alerts", + "type": "boolean", + "optional": False, + }, + "virustotal-livehunt-notifications-upload-artifact": { + "description": "Set to true to upload the file to opencti", + "type": "boolean", + "optional": False, + }, + "virustotal-livehunt-notifications-create-yara-rule": { + "description": "Set to true to create yara rule linked to the alert and the file", + "type": "boolean", + "optional": False, + }, + "virustotal-livehunt-notifications-delete-notification": { + "description": "Set to true to remove livehunt notifications", + "type": "boolean", + "optional": False, + }, + "virustotal-livehunt-notifications-filter-with-tag": { + "description": "Filter livehunt notifications with this tag", + "type": "string", + "optional": False, + }, + }, + charm_override=textwrap.dedent( + """\ + @property + def boolean_style(self) -> str: + return "python" + """ + ), + ) + + +@connector_generator("vxvault") +def gen_vxvault_connector(location: pathlib, version: str) -> None: + """Generate opencti vxvault (vxvault) connector. + + https://github.com/OpenCTI-Platform/connectors/tree/master/external-import/vxvault + """ + render_template( + name="vxvault", + connector_type="EXTERNAL_IMPORT", + version=version, + display_name="VXVault", + output_dir=location, + config={ + "connector-scope": { + "description": "connector scope", + "type": "string", + "optional": False, + }, + "connector-log-level": { + "description": "(optional) The log level of the connector", + "type": "string", + "optional": True, + }, + "vxvault-url": { + "description": "vxvault url", + "type": "string", + "default": "https://vxvault.net/URL_List.php", + "optional": False, + }, + "vxvault-create-indicators": { + "description": "vxvault create indicators", + "type": "boolean", + "optional": False, + }, + "vxvault-interval": { + "description": "In days, must be strictly greater than 1", + "type": "int", + "optional": False, + }, + "vxvault-ssl-verify": { + "description": "Whether to verify SSL certificates", + "type": "boolean", + "default": True, + "optional": False, + }, + }, + ) + + +def render(version: str) -> None: + """Render a OpenCTI connector charm from the template.""" + for connector in _CONNECTOR_GENERATORS: + location = ( + pathlib.Path(__file__).resolve().parent.parent + / "connectors" + / kebab_to_snake(connector) + ) + _CONNECTOR_GENERATORS[connector](location=location, version=version) + + +if __name__ == "__main__": + render("6.4.5") diff --git a/src/charm.py b/src/charm.py index eee8d6e..8f3be4b 100755 --- a/src/charm.py +++ b/src/charm.py @@ -25,6 +25,8 @@ from charms.redis_k8s.v0.redis import RedisRelationCharmEvents, RedisRequires from charms.traefik_k8s.v2.ingress import IngressPerAppRequirer +import opencti + logger = logging.getLogger(__name__) @@ -63,6 +65,7 @@ class PlatformNotReady(Exception): _PEER_SECRET_HEALTH_ACCESS_KEY_SECRET_FIELD = "health-access-key" # nosec _CHARM_CALLBACK_SCRIPT_PATH = pathlib.Path("/opt/opencti/charm-callback.sh") _OPENSEARCH_CERT_PATH = pathlib.Path("/opt/opencti/config/opensearch.pem") +_OPENCTI_CONNECTOR_USER_PREFIX = "charm-connector-" # caused by charm libraries @@ -113,6 +116,8 @@ def __init__(self, *args: typing.Any): ) self.framework.observe(self.on.opencti_peer_relation_broken, self._cleanup_secrets) self.framework.observe(self.on.stop, self._cleanup_secrets) + self.framework.observe(self.on.opencti_connector_relation_joined, self._reconcile) + self.framework.observe(self.on.opencti_connector_relation_changed, self._reconcile) def _register_opensearch(self) -> OpenSearchRequires: """Create OpenSearchRequires instance and register related event handlers. @@ -236,6 +241,7 @@ def _reconcile(self, _: ops.EventBase) -> None: """Run charm reconcile function and catch all exceptions.""" try: self._reconcile_platform() + self._reconcile_connector() self.unit.status = ops.ActiveStatus() except (MissingIntegration, MissingConfig, InvalidIntegration, InvalidConfig) as exc: self.unit.status = ops.BlockedStatus(str(exc)) @@ -243,7 +249,7 @@ def _reconcile(self, _: ops.EventBase) -> None: self.unit.status = ops.WaitingStatus(str(exc)) def _reconcile_platform(self) -> None: - """Run charm reconcile function. + """Run charm reconcile function for OpenCTI platform and workers. Raises: PlatformNotReady: failed to start the OpenCTI platform at this moment @@ -672,6 +678,113 @@ def _dump_integration(self, name: str) -> str: dump["unit-data"] = {unit.name: dict(integration.data[unit]) for unit in units} return json.dumps(dump) + def _reconcile_connector(self) -> None: + """Run charm reconcile function for OpenCTI connectors.""" + client = opencti.OpenctiClient( + url="http://localhost:8080", + api_token=self._get_peer_secret(_PEER_SECRET_ADMIN_TOKEN_SECRET_FIELD), + ) + integrations = self.model.relations["opencti-connector"] + active_connector_users = set() + for integration in integrations: + if integration.app is None: + continue + user = self._setup_connector_integration_and_user(client, integration) + if user: + active_connector_users.add(user) + for opencti_user in client.list_users(name_starts_with=_OPENCTI_CONNECTOR_USER_PREFIX): + if opencti_user.name not in active_connector_users: + client.set_account_status(opencti_user.id, "Inactive") + + def _setup_connector_integration_and_user( + self, client: opencti.OpenctiClient, integration: ops.Relation + ) -> str | None: + """Set up the connector integration and connector user. + + Args: + client: the OpenCTI client. + integration: the opencti-connector integration object. + + Returns: + name of the opencti user created for this integration, None if no user is needed. + """ + integration_data = integration.data[integration.app] + connector_charm_name = integration_data.get("connector_charm_name") + connector_type = integration_data.get("connector_type") + if not connector_charm_name or not connector_type: + return None + opencti_url = f"http://{self.app.name}-endpoints.{self.model.name}.svc:8080" + integration.data[self.app]["opencti_url"] = opencti_url + connector_user_name = f"charm-connector-{connector_charm_name.replace('_', '-').lower()}" + connector_user = self._get_opencti_user(client, connector_user_name) + if connector_user is None: + connector_user = self._create_opencti_user( + client, connector_user_name, self._get_connector_group(connector_type) + ) + if connector_user.account_status == "Inactive": + client.set_account_status(connector_user.id, "Active") + + api_token = connector_user.api_token + opencti_token_id = integration.data[self.app].get("opencti_token") + if not opencti_token_id: + secret = self.app.add_secret(content={"token": api_token}) + secret.grant(integration) + integration.data[self.app]["opencti_token"] = typing.cast(str, secret.id) + else: + secret = self.model.get_secret(id=opencti_token_id) + if secret.get_content(refresh=True)["token"] != api_token: + secret.set_content({"token": api_token}) + return connector_user_name + + def _get_connector_group(self, connector_type: str) -> str: + """Get the connector group for the given connector type. + + Args: + connector_type: the connector type. + + Returns: + connector group name for the given connector type. + """ + return ( + "Administrators" + if connector_type.replace("-", "_").upper() == "INTERNAL_EXPORT_FILE" + else "Connectors" + ) + + def _create_opencti_user( + self, client: opencti.OpenctiClient, name: str, group_name: str + ) -> opencti.OpenctiUser: + """Create a new OpenCTI user. + + Args: + client: the OpenCTI client. + name: the name of the user. + group_name: the name of the group. + + Returns: + The new OpenCTI user. + """ + groups = {g.name: g for g in client.list_groups()} + group_id = groups[group_name].id + return client.create_user(name=name, groups=[group_id]) + + def _get_opencti_user( + self, client: opencti.OpenctiClient, name: str + ) -> opencti.OpenctiUser | None: + """Get the OpenCTI user by name. + + Args: + client: the OpenCTI client. + name: the name of the user. + + Returns: + The OpenCTI user. + """ + users = users = { + u.name: u for u in client.list_users(name_starts_with=_OPENCTI_CONNECTOR_USER_PREFIX) + } + return users.get(name) + if __name__ == "__main__": # pragma: nocover ops.main(OpenCTICharm) diff --git a/src/opencti.graphql b/src/opencti.graphql new file mode 100644 index 0000000..4b7b11f --- /dev/null +++ b/src/opencti.graphql @@ -0,0 +1,12526 @@ +directive @auth(for: [Capabilities] = [], and: Boolean = false) on OBJECT | FIELD_DEFINITION + +directive @public on OBJECT | FIELD_DEFINITION + +directive @constraint(minLength: Int, maxLength: Int, startsWith: String, endsWith: String, notContains: String, pattern: String, format: String, min: Int, max: Int, exclusiveMin: Int, exclusiveMax: Int, multipleOf: Int) on INPUT_FIELD_DEFINITION + +"""Controls the rate of traffic.""" +directive @rateLimit( + """Number of occurrences allowed over duration.""" + limit: Int! = 60 + + """Number of seconds before limit is reset.""" + duration: Int! = 60 +) on OBJECT | FIELD_DEFINITION + +""" +Indicates exactly one field must be supplied and this field must not be `null`. +""" +directive @oneOf on INPUT_OBJECT + +""" +A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. +""" +scalar DateTime + +scalar ConstraintString + +scalar ConstraintNumber + +"""The `Upload` scalar type represents a file upload.""" +scalar Upload + +"""STIX ID Scalar Type""" +scalar StixId + +"""STIX Reference Scalar Type""" +scalar StixRef + +"""Arbitrary object""" +scalar Any + +scalar JSON + +enum State { + wait + progress + complete + timeout +} + +enum Capabilities { + CONNECTORAPI + KNOWLEDGE + KNOWLEDGE_KNUPDATE + KNOWLEDGE_KNPARTICIPATE + KNOWLEDGE_KNUPDATE_KNDELETE + KNOWLEDGE_KNUPDATE_KNORGARESTRICT + KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS + KNOWLEDGE_KNUPLOAD + KNOWLEDGE_KNASKIMPORT + KNOWLEDGE_KNGETEXPORT + KNOWLEDGE_KNGETEXPORT_KNASKEXPORT + KNOWLEDGE_KNENRICHMENT + EXPLORE + EXPLORE_EXUPDATE + EXPLORE_EXUPDATE_EXDELETE + EXPLORE_EXUPDATE_PUBLISH + INVESTIGATION + INVESTIGATION_INUPDATE + INVESTIGATION_INUPDATE_INDELETE + MODULES + MODULES_MODMANAGE + SETTINGS + SETTINGS_SETPARAMETERS + SETTINGS_SETACCESSES + SETTINGS_SETMARKINGS + SETTINGS_SETLABELS + SETTINGS_SETCUSTOMIZATION + SETTINGS_SECURITYACTIVITY + SETTINGS_FILEINDEXING + SETTINGS_SUPPORT + TAXIIAPI + TAXIIAPI_SETCOLLECTIONS + INGESTION + INGESTION_SETINGESTIONS + CSVMAPPERS + VIRTUAL_ORGANIZATION_ADMIN +} + +enum MemberType { + User + Group + Organization +} + +type PageInfo { + startCursor: String! + endCursor: String! + hasNextPage: Boolean! + hasPreviousPage: Boolean! + globalCount: Int! +} + +enum OrderingMode { + asc + desc +} + +enum FilterMode { + and + or +} + +enum FilterOperator { + eq + not_eq + lt + lte + gt + gte + match + wildcard + contains + not_contains + ends_with + not_ends_with + starts_with + not_starts_with + script + nil + not_nil + search +} + +input FilterGroup { + mode: FilterMode! + filters: [Filter!]! + filterGroups: [FilterGroup!]! +} + +input Filter { + key: [String!]! + values: [Any!]! + operator: FilterOperator + mode: FilterMode +} + +type RepresentativeWithId { + id: String! + value: String + entity_type: String + color: String +} + +type FilterKeysSchema { + entity_type: String! + filters_schema: [FilterDefinitionSchema!]! +} + +type FilterDefinitionSchema { + filterKey: String! + filterDefinition: FilterDefinition! +} + +type FilterDefinition { + filterKey: String! + label: String! + type: String! + multiple: Boolean! + subEntityTypes: [String!]! + elementsForFilterValuesSearch: [String!]! + subFilters: [FilterDefinition!] +} + +enum EditOperation { + add + replace + remove +} + +input EditInput { + key: String! + object_path: String + value: [Any]! + operation: EditOperation +} + +input EditContext { + focusOn: String +} + +type EditUserContext { + name: String! + focusOn: String +} + +input DictionaryInput { + key: String! + value: String! +} + +type Dictionary { + key: String! + value: String! +} + +"""Dependency information containing the name and the deployed version.""" +type DependencyVersion { + name: String! + version: String! +} + +""" +NodeJs memory. +https://nodejs.org/api/process.html#process_process_memoryusage +https://nodejs.org/docs/latest-v11.x/api/v8.html#v8_v8_getheapstatistics +""" +type AppMemory { + rss: Float + heapTotal: Float + heapUsed: Float + external: Float + arrayBuffers: Float + total_heap_size: Float + total_heap_size_executable: Float + total_physical_size: Float + total_available_size: Float + used_heap_size: Float + heap_size_limit: Float + malloced_memory: Float + peak_malloced_memory: Float + does_zap_garbage: Float +} + +input ExportContext { + entity_id: String + entity_type: String! +} + +type AppDebugDistribution { + label: String! + value: Int +} + +type AppDebugStatistics { + objects: [AppDebugDistribution] + relationships: [AppDebugDistribution] +} + +"""Retrieve the application information version add dependencies""" +type AppInfo { + """The OpenCTI application version""" + version: String! + + """The OpenCTI api current memory usage""" + memory: AppMemory + + """The list of OpenCTI software dependencies""" + dependencies: [DependencyVersion!]! + + """The objects statistics""" + debugStats: AppDebugStatistics +} + +type AckDetails { + rate: Float +} + +type MessagesStats { + ack: String + ack_details: AckDetails +} + +type QueueArguments { + config: String +} + +type QueueMetrics { + name: String! + arguments: QueueArguments + messages: String + messages_ready: String + messages_unacknowledged: String + consumers: String + idle_since: DateTime + message_stats: MessagesStats +} + +type QueueTotals { + messages: String + messages_ready: String + messages_unacknowledged: String +} + +type ObjectTotals { + channels: String + consumers: String + queues: String +} + +type OverviewMetrics { + object_totals: ObjectTotals + queue_totals: QueueTotals + message_stats: MessagesStats +} + +type RabbitMQMetrics { + consumers: String + queues: [QueueMetrics] + overview: OverviewMetrics +} + +type SearchMetrics { + query_total: String + fetch_total: String +} + +type IndexingMetrics { + index_total: String + delete_total: String +} + +type GetMetrics { + total: String +} + +type DocsMetrics { + count: String +} + +type ElasticSearchMetrics { + docs: DocsMetrics + search: SearchMetrics + get: GetMetrics + indexing: IndexingMetrics +} + +enum StatsOperation { + count + sum +} + +type TimeSeries { + date: DateTime! + value: Int! +} + +type MultiTimeSeries { + data: [TimeSeries] +} + +input AuditsTimeSeriesParameters { + field: String! + types: [String] + filters: FilterGroup + search: String +} + +input StixCoreObjectsTimeSeriesParameters { + field: String! + types: [String] + filters: FilterGroup + search: String +} + +input StixRelationshipsTimeSeriesParameters { + field: String! + fromOrToId: [String] + elementWithTargetTypes: [String] + fromId: [String] + fromRole: String + fromTypes: [String] + toId: [String] + toRole: String + toTypes: [String] + relationship_type: [String] + confidences: [Int] + search: String + filters: FilterGroup + dynamicFrom: FilterGroup + dynamicTo: FilterGroup +} + +input StixCoreRelationshipsTimeSeriesParameters { + field: String! + fromOrToId: [String] + elementWithTargetTypes: [String] + fromId: [String] + fromRole: String + fromTypes: [String] + toId: [String] + toRole: String + toTypes: [String] + relationship_type: [String] + confidences: [Int] + search: String + filters: FilterGroup + dynamicFrom: FilterGroup + dynamicTo: FilterGroup +} + +type Distribution { + label: String! + entity: StixObjectOrStixRelationshipOrCreator + value: Int +} + +type MultiDistribution { + data: [Distribution] +} + +input StixCoreObjectsDistributionParameters { + objectId: String + relationship_type: [String] + toTypes: [String] + types: [String] + filters: FilterGroup + search: String +} + +input StixCoreRelationshipsDistributionParameters { + field: String! + fromOrToId: [String] + elementWithTargetTypes: [String] + fromId: [String] + fromRole: String + fromTypes: [String] + toId: [String] + toRole: String + toTypes: [String] + relationship_type: [String] + confidences: [Int] + search: String + filters: FilterGroup +} + +type Number { + total: Int! + count: Int! +} + +input StixCoreObjectsNumberParameters { + types: [String] + filters: FilterGroup + search: String +} + +type OpinionsMetrics { + mean: Float + min: Int + max: Int + total: Int +} + +type LogsWorkerConfig { + elasticsearch_url: [String]! + elasticsearch_proxy: String + elasticsearch_index: String! + elasticsearch_username: String + elasticsearch_password: String + elasticsearch_api_key: String + elasticsearch_ssl_reject_unauthorized: Boolean +} + +enum LogsOrdering { + event + timestamp + created_at + event_type + event_scope + _score +} + +type LogConnection { + pageInfo: PageInfo! + edges: [LogEdge] +} + +type LogEdge { + cursor: String! + node: Log! +} + +type ContextData { + entity_id: String + entity_name: String + entity_type: String + from_id: String + to_id: String + message: String! + commit: String + external_references: [ExternalReference!] +} + +type Log { + id: ID! + entity_type: String + event_type: String! + event_scope: String + event_status: String! + timestamp: DateTime! + user_id: String! + user: Creator + raw_data: String + context_uri: String + context_data: ContextData +} + +enum AttributesOrdering { + value + _score +} + +type AttributeConnection { + pageInfo: PageInfo! + edges: [AttributeEdge!]! +} + +type AttributeEdge { + cursor: String! + node: Attribute! +} + +type Attribute { + id: ID! + key: String! + value: String! +} + +input WorkErrorInput { + error: String + source: String +} + +type TaxiiCollection { + id: ID! + name: String + description: String + filters: String + include_inferences: Boolean + score_to_confidence: Boolean + taxii_public: Boolean + authorized_members: [MemberAccess!] +} + +type TaxiiCollectionConnection { + pageInfo: PageInfo! + edges: [TaxiiCollectionEdge]! +} + +type TaxiiCollectionEdge { + cursor: String! + node: TaxiiCollection! +} + +input TaxiiCollectionAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + filters: String + taxii_public: Boolean + authorized_members: [MemberAccessInput!] + include_inferences: Boolean + score_to_confidence: Boolean +} + +enum TaxiiCollectionOrdering { + name + id + _score +} + +type FeedMapping { + type: String! + attribute: String! +} + +type FeedAttribute { + attribute: String! + mappings: [FeedMapping!]! +} + +type Feed { + id: ID! + standard_id: ID! + name: String! + description: String + filters: String + separator: String! + rolling_time: Int! + feed_date_attribute: String + include_header: Boolean! + feed_types: [String!]! + feed_attributes: [FeedAttribute!]! + feed_public: Boolean + authorized_members: [MemberAccess!] +} + +input FeedMappingInput { + type: String! + attribute: String! +} + +input FeedAttributeMappingInput { + attribute: String! + mappings: [FeedMappingInput!]! +} + +input FeedAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + filters: String + separator: String! + feed_date_attribute: String! + rolling_time: Int! + include_header: Boolean! + feed_types: [String!]! + feed_public: Boolean + feed_attributes: [FeedAttributeMappingInput!]! + authorized_members: [MemberAccessInput!] +} + +enum FeedOrdering { + name + rolling_time + feed_types + _score +} + +type FeedEdge { + cursor: String! + node: Feed! +} + +type FeedConnection { + pageInfo: PageInfo! + edges: [FeedEdge]! +} + +type RemoteStreamCollection { + id: ID! + name: String + description: String + filters: String +} + +type StreamCollection { + id: ID! + name: String + description: String + filters: String + stream_live: Boolean + stream_public: Boolean + authorized_members: [MemberAccess!] +} + +type StreamCollectionConnection { + pageInfo: PageInfo! + edges: [StreamCollectionEdge!]! +} + +type StreamCollectionEdge { + cursor: String! + node: StreamCollection! +} + +input StreamCollectionAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + filters: String + stream_live: Boolean + stream_public: Boolean + authorized_members: [MemberAccessInput!] +} + +enum StreamCollectionOrdering { + name + stream_public + id + stream_live + _score +} + +enum SubTypesOrdering { + label + _score +} + +type SubTypeConnection { + pageInfo: PageInfo! + edges: [SubTypeEdge!]! +} + +type SubTypeEdge { + cursor: String! + node: SubType! +} + +type SubType { + id: ID! + label: String! + statuses: [Status!]! + workflowEnabled: Boolean + settings: EntitySetting +} + +enum StatusTemplateOrdering { + name + _score +} + +type StatusTemplate { + id: ID! + name: String! + color: String! + editContext: [EditUserContext!] + usages: Int +} + +type StatusTemplateConnection { + pageInfo: PageInfo! + edges: [StatusTemplateEdge] +} + +type StatusTemplateEdge { + cursor: String! + node: StatusTemplate! +} + +enum StatusOrdering { + type + order + _score +} + +type Status { + id: ID! + template_id: String! + template: StatusTemplate + type: String! + order: Int! + disabled: Boolean +} + +type StatusConnection { + pageInfo: PageInfo! + edges: [StatusEdge!]! +} + +type StatusEdge { + cursor: String! + node: Status! +} + +input StatusAddInput { + template_id: String! + order: Int! +} + +input StatusTemplateAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + color: String! +} + +enum SynchronizersOrdering { + id + name + current_state_date + running + uri + stream_id + _score +} + +type Synchronizer { + id: ID! + name: String! + uri: String! + token: String + stream_id: String! + user: Creator + running: Boolean! + current_state_date: DateTime + listen_deletion: Boolean! + no_dependencies: Boolean! + ssl_verify: Boolean + synchronized: Boolean + queue_messages: Int! +} + +type SynchronizerEdge { + cursor: String! + node: Synchronizer! +} + +type SynchronizerConnection { + pageInfo: PageInfo! + edges: [SynchronizerEdge] +} + +input SynchronizerAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + + "*Constraints:*\n* Minimal length: `2`\n" + uri: String! + token: String + + "*Constraints:*\n* Minimal length: `2`\n" + stream_id: String! + user_id: String + recover: DateTime + current_state_date: DateTime + listen_deletion: Boolean! + no_dependencies: Boolean! + ssl_verify: Boolean + synchronized: Boolean +} + +input SynchronizerFetchInput { + uri: String! + token: String + ssl_verify: Boolean +} + +enum WorksOrdering { + status + timestamp + _score +} + +type WorkMessage { + timestamp: DateTime + message: String + sequence: Int + source: String +} + +type WorkTracking { + import_expected_number: Int + import_last_processed: DateTime + import_processed_number: Int +} + +type Work { + id: ID! + name: String + user: Creator + connector: Connector + timestamp: DateTime! + status: State! + event_source_id: String + received_time: DateTime + processed_time: DateTime + completed_time: DateTime + completed_number: Int + messages: [WorkMessage] + errors: [WorkMessage] + tracking: WorkTracking +} + +type WorkEdge { + cursor: String! + node: Work! +} + +type WorkConnection { + pageInfo: PageInfo! + edges: [WorkEdge] +} + +type FileMetadata { + encoding: String + mimetype: String + version: String + messages: [WorkMessage] + errors: [WorkMessage] + list_filters: String + entity_id: String + entity: StixObject + labels_text: String + labels: [String] + file_markings: [String] + creator_id: String + external_reference_id: String + creator: Creator + description: String + order: Int + inCarousel: Boolean + analysis_content_source: String + analysis_content_type: String + analysis_type: String +} + +enum FileOrdering { + _score + name + lastModified + objectMarking +} + +type File { + id: ID! + entity_type: String! + name: String! + size: Int + lastModified: DateTime + lastModifiedSinceMin: Int + metaData: FileMetadata + objectMarking: [MarkingDefinition!]! + uploadStatus: State! + works: [Work] +} + +type FileEdge { + cursor: String! + node: File! +} + +type FileConnection { + pageInfo: PageInfo! + edges: [FileEdge!]! +} + +enum WidgetPerspective { + entities + relationships + audits +} + +type WidgetColumn { + attribute: String! + displayStyle: String + label: String + variableName: String +} + +type WidgetDataSelection { + label: String + number: Int + attribute: String + date_attribute: String + centerLat: Float + centerLng: Float + zoom: Float + isTo: Boolean + perspective: WidgetPerspective + filters: String + dynamicFrom: String + dynamicTo: String + columns: [WidgetColumn!] + instance_id: String +} + +type WidgetParameters { + title: String + description: String + interval: String + stacked: Boolean + legend: Boolean + distributed: Boolean +} + +type WidgetLayout { + w: Float + h: Float + x: Float + y: Float + i: Float + moved: Boolean + static: Boolean +} + +type Widget { + id: ID! + type: String! + perspective: WidgetPerspective + dataSelection: [WidgetDataSelection!]! + parameters: WidgetParameters + layout: WidgetLayout +} + +type Template { + id: ID! + name: String! + description: String + filters: String + content: String! + template_widgets_ids: [String!]! +} + +type TemplateAndUtils { + template: Template! + template_widgets: [Widget!]! +} + +type IndexedFile { + id: ID! + name: String! + file_id: String! + uploaded_at: DateTime! + entity: StixObject + searchOccurrences: Int +} + +type IndexedFileEdge { + cursor: String! + node: IndexedFile! +} + +type IndexedFileConnection { + pageInfo: PageInfo! + edges: [IndexedFileEdge] +} + +type MetricsByMimeType { + mimeType: String! + count: Int! + size: Float! +} + +type FilesMetrics { + globalCount: Int! + globalSize: Float! + metricsByMimeType: [MetricsByMimeType!] +} + +type OpenCtiFile { + id: ID! + name: String! + mime_type: String! + description: String + order: Int + inCarousel: Boolean +} + +enum BackgroundTaskType { + QUERY + LIST + RULE +} + +type BackgroundTaskError { + id: ID! + timestamp: DateTime + message: String +} + +enum BackgroundTaskScope { + KNOWLEDGE + USER + SETTINGS + IMPORT + DASHBOARD + PUBLIC_DASHBOARD + INVESTIGATION +} + +enum BackgroundTaskActionType { + DELETE + COMPLETE_DELETE + RESTORE + ADD + REMOVE + REPLACE + MERGE + ENRICHMENT + PROMOTE + RULE_ELEMENT_RESCAN + SHARE + UNSHARE + SHARE_MULTIPLE + UNSHARE_MULTIPLE +} + +enum BackgroundTaskContextType { + ATTRIBUTE + RELATION + REVERSED_RELATION +} + +enum BackgroundTasksOrdering { + id + type + completed + created_at + last_execution_date + _score +} + +type BackgroundTaskContext { + field: String + type: BackgroundTaskContextType + values: [String]! +} + +type BackgroundTaskAction { + type: BackgroundTaskActionType + context: BackgroundTaskContext +} + +interface BackgroundTask { + id: ID! + type: BackgroundTaskType + initiator: Creator + actions: [BackgroundTaskAction] + created_at: DateTime + last_execution_date: DateTime + completed: Boolean + task_expected_number: Int + task_processed_number: Int + errors: [BackgroundTaskError] +} + +type RuleTask implements BackgroundTask { + id: ID! + type: BackgroundTaskType + initiator: Creator + actions: [BackgroundTaskAction] + created_at: DateTime + last_execution_date: DateTime + completed: Boolean + task_expected_number: Int + task_processed_number: Int + errors: [BackgroundTaskError] + rule: ID! + enable: Boolean +} + +type ListTask implements BackgroundTask { + id: ID! + type: BackgroundTaskType + initiator: Creator + actions: [BackgroundTaskAction] + created_at: DateTime + last_execution_date: DateTime + completed: Boolean + task_expected_number: Int + task_processed_number: Int + errors: [BackgroundTaskError] + scope: BackgroundTaskScope! + authorized_members: [MemberAccess!] + authorized_authorities: [String] + task_ids: [ID!] +} + +type QueryTask implements BackgroundTask { + id: ID! + type: BackgroundTaskType + initiator: Creator + actions: [BackgroundTaskAction] + created_at: DateTime + last_execution_date: DateTime + completed: Boolean + task_expected_number: Int + task_processed_number: Int + errors: [BackgroundTaskError] + scope: BackgroundTaskScope! + authorized_members: [MemberAccess!] + authorized_authorities: [String] + task_filters: String! + task_search: String +} + +type BackgroundTaskConnectionEdge { + cursor: String! + node: BackgroundTask! +} + +type BackgroundTaskConnection { + pageInfo: PageInfo! + edges: [BackgroundTaskConnectionEdge] +} + +input BackgroundTaskContextOptionsInput { + includeNeighbours: Boolean +} + +input BackgroundTaskContextInput { + field: String + type: BackgroundTaskContextType + values: [String]! + options: BackgroundTaskContextOptionsInput +} + +input BackgroundTaskActionInput { + containerId: String + type: BackgroundTaskActionType! + context: BackgroundTaskContextInput +} + +input ListTaskAddInput { + ids: [ID!] + actions: [BackgroundTaskActionInput]! + scope: BackgroundTaskScope! +} + +input QueryTaskAddInput { + filters: String + search: String + excluded_ids: [ID] + actions: [BackgroundTaskActionInput]! + scope: BackgroundTaskScope! +} + +input RetentionRuleAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + filters: String + + "*Constraints:*\n* Minimal value: `1`\n" + max_retention: Int! + retention_unit: RetentionUnit + scope: RetentionRuleScope! +} + +enum RetentionRuleOrdering { + name + scope + remaining_count + last_execution_date + max_retention + _score +} + +enum RetentionRuleScope { + knowledge + file + workbench +} + +enum RetentionUnit { + minutes + hours + days +} + +type RetentionRule { + id: ID! + standard_id: String! + name: String! + filters: String! + max_retention: Int! + retention_unit: RetentionUnit! + last_execution_date: DateTime + last_deleted_count: Int + remaining_count: Int + scope: RetentionRuleScope! +} + +type RetentionRuleConnection { + pageInfo: PageInfo! + edges: [RetentionRuleEdge] +} + +type RetentionRuleEdge { + cursor: String! + node: RetentionRule! +} + +type RetentionRuleEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): RetentionRule +} + +interface BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! +} + +interface InternalObject { + id: ID! + entity_type: String! +} + +type Module { + id: ID! + enable: Boolean! + running: Boolean! + warning: Boolean +} + +type Cluster { + instances_number: Int! +} + +type Provider { + name: String! + type: String + strategy: String + provider: String +} + +type UserStatus { + status: String! + message: String! +} + +input SettingsMessageInput { + id: ID + message: String! + activated: Boolean! + dismissible: Boolean! + color: String + recipients: [String!] +} + +type SettingsMessage { + id: ID! + message: String! + activated: Boolean! + dismissible: Boolean! + updated_at: DateTime! + color: String + recipients: [Member!] +} + +enum PlatformCriticalAlertType { + GROUP_WITH_NULL_CONFIDENCE_LEVEL +} + +type PlatformCriticalAlertDetails { + groups: [Group!]! +} + +type PlatformCriticalAlert { + message: String! + type: PlatformCriticalAlertType! + details: PlatformCriticalAlertDetails +} + +type PlatformProtectedSubConfig { + enabled: Boolean! + protected_ids: [String!]! +} + +type PlatformProtectedSensitiveConfig { + enabled: Boolean! + markings: PlatformProtectedSubConfig! + groups: PlatformProtectedSubConfig! + roles: PlatformProtectedSubConfig! + rules: PlatformProtectedSubConfig! + ce_ee_toggle: PlatformProtectedSubConfig! + file_indexing: PlatformProtectedSubConfig! + platform_organization: PlatformProtectedSubConfig! +} + +type Settings implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String!]! + platform_organization: Organization + platform_title: String + platform_favicon: String + platform_email: String + platform_cluster: Cluster! + platform_modules: [Module!] + platform_url: String + platform_providers: [Provider!]! + platform_user_statuses: [UserStatus!]! + platform_language: String + platform_theme: String + platform_theme_dark_background: String + platform_theme_dark_paper: String + platform_theme_dark_nav: String + platform_theme_dark_primary: String + platform_theme_dark_secondary: String + platform_theme_dark_accent: String + platform_theme_dark_logo: String + platform_theme_dark_logo_collapsed: String + platform_theme_dark_logo_login: String + platform_theme_light_background: String + platform_theme_light_paper: String + platform_theme_light_nav: String + platform_theme_light_primary: String + platform_theme_light_secondary: String + platform_theme_light_accent: String + platform_theme_light_logo: String + platform_theme_light_logo_collapsed: String + platform_theme_light_logo_login: String + platform_map_tile_server_dark: String + platform_map_tile_server_light: String + platform_openbas_url: String + platform_openbas_disable_display: Boolean + platform_openerm_url: String + platform_openmtd_url: String + platform_ai_enabled: Boolean! + platform_ai_type: String + platform_ai_model: String + platform_ai_has_token: Boolean! + platform_login_message: String + platform_consent_message: String + platform_consent_confirm_text: String + platform_banner_text: String + platform_banner_level: String + platform_session_idle_timeout: Int + platform_session_timeout: Int + platform_whitemark: Boolean + platform_demo: Boolean + platform_reference_attachment: Boolean + platform_feature_flags: [Module!] + platform_critical_alerts: [PlatformCriticalAlert!]! + platform_trash_enabled: Boolean! + platform_protected_sensitive_config: PlatformProtectedSensitiveConfig! + created_at: DateTime! + updated_at: DateTime! + enterprise_edition: DateTime + activity_listeners: [Member!] + otp_mandatory: Boolean + password_policy_min_length: Int + password_policy_max_length: Int + password_policy_min_symbols: Int + password_policy_min_numbers: Int + password_policy_min_words: Int + password_policy_min_lowercase: Int + password_policy_min_uppercase: Int + platform_messages: [SettingsMessage!] + messages_administration: [SettingsMessage!] + analytics_google_analytics_v4: String + editContext: [EditUserContext!] +} + +enum GroupsOrdering { + name + default_assignation + no_creators + restrict_delete + auto_new_marking + created_at + updated_at + group_confidence_level + _score +} + +type GroupConnection { + pageInfo: PageInfo! + edges: [GroupEdge] +} + +type GroupEdge { + cursor: String! + node: Group! +} + +input DefaultMarkingInput { + entity_type: String! + values: [String!] +} + +type DefaultMarking { + entity_type: String + values: [MarkingDefinition!] +} + +type Group implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + name: String! + default_assignation: Boolean + no_creators: Boolean + restrict_delete: Boolean + auto_new_marking: Boolean + description: String + default_dashboard: Workspace + members(first: Int, after: ID, orderBy: UsersOrdering, orderMode: OrderingMode, search: String): UserConnection + created_at: DateTime + updated_at: DateTime + roles(orderBy: RolesOrdering, orderMode: OrderingMode): RoleConnection + allowed_marking: [MarkingDefinition!] + default_marking: [DefaultMarking!] + not_shareable_marking_types: [String!]! + max_shareable_marking: [MarkingDefinition!]! + default_hidden_types: [String!] + group_confidence_level: ConfidenceLevel + editContext: [EditUserContext!] +} + +input GroupAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + default_assignation: Boolean + no_creators: Boolean + restrict_delete: Boolean + auto_new_marking: Boolean + clientMutationId: String + group_confidence_level: ConfidenceLevelInput! +} + +enum UnitSystem { + auto + Metric + Imperial +} + +enum UsersOrdering { + name + user_email + firstname + lastname + language + external + created_at + updated_at + _score +} + +type UserConnection { + pageInfo: PageInfo! + edges: [UserEdge!]! +} + +type CreatorConnection { + pageInfo: PageInfo! + edges: [CreatorEdge] +} + +type AssigneeConnection { + pageInfo: PageInfo! + edges: [AssigneeEdge!]! +} + +type ParticipantConnection { + pageInfo: PageInfo! + edges: [ParticipantEdge!]! +} + +type MemberConnection { + pageInfo: PageInfo! + edges: [MemberEdge!]! +} + +type UserEdge { + cursor: String! + node: User! +} + +type CreatorEdge { + cursor: String! + node: Creator! +} + +type AssigneeEdge { + cursor: String! + node: Assignee! +} + +type ParticipantEdge { + cursor: String! + node: Participant! +} + +type MemberEdge { + cursor: String! + node: Member! +} + +type Assignee { + id: ID! + name: String! + entity_type: String! +} + +type Participant { + id: ID! + name: String! + entity_type: String! +} + +type Member { + id: ID! + name: String! + entity_type: String! + effective_confidence_level: EffectiveConfidenceLevel + group_confidence_level: ConfidenceLevel +} + +type MemberAccess { + id: ID! + name: String! + entity_type: String! + access_right: String! +} + +input MemberAccessInput { + id: ID! + access_right: String! +} + +type OtpElement { + secret: String! + uri: String! +} + +type Creator { + id: ID! + name: String! + entity_type: String! + representative: Representative! +} + +type ConfidenceLevel { + max_confidence: Int + overrides: [ConfidenceLevelOverride!]! +} + +type ConfidenceLevelOverride { + entity_type: String! + max_confidence: Int! +} + +type EffectiveConfidenceLevelOverride { + entity_type: String! + max_confidence: Int! + source: EffectiveConfidenceLevelSource +} + +type EffectiveConfidenceLevel { + max_confidence: Int! + overrides: [EffectiveConfidenceLevelOverride!]! + source: EffectiveConfidenceLevelSource +} + +type EffectiveConfidenceLevelSource { + type: EffectiveConfidenceLevelSourceType! + object: EffectiveConfidenceLevelSourceObject +} + +enum EffectiveConfidenceLevelSourceType { + User + Group + Bypass +} + +union EffectiveConfidenceLevelSourceObject = Group | User + +type User implements BasicObject & InternalObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + user_email: String! + api_token: String! + personal_notifiers: [Notifier!] + individual_id: String + name: String! + description: String + firstname: String + otp_activated: Boolean + stateless_session: Boolean + otp_qr: String + otp_mandatory: Boolean + lastname: String + theme: String + language: String + external: Boolean + roles(orderBy: RolesOrdering, orderMode: OrderingMode): [Role!]! + capabilities: [Capability]! + default_hidden_types: [String!]! + user_confidence_level: ConfidenceLevel + effective_confidence_level: EffectiveConfidenceLevel + no_creators: Boolean + restrict_delete: Boolean + groups(orderBy: GroupsOrdering, orderMode: OrderingMode): GroupConnection + objectOrganization(orderBy: OrganizationsOrdering, orderMode: OrderingMode): OrganizationConnection + created_at: DateTime! + updated_at: DateTime! + sessions: [SessionDetail] + default_time_field: String + account_status: String! + account_lock_after_date: DateTime + administrated_organizations: [Organization!]! + unit_system: UnitSystem + submenu_show_icons: Boolean + submenu_auto_collapse: Boolean + monochrome_labels: Boolean + editContext: [EditUserContext!] +} + +type MeUser implements BasicObject & InternalObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String!]! + user_email: String! + name: String! + description: String + firstname: String + otp_activated: Boolean + otp_qr: String + lastname: String + theme: String + language: String + external: Boolean + individual_id: String + api_token: String! + personal_notifiers: [Notifier!] + objectOrganization: MeOrganizationConnection + capabilities: [Capability!]! + default_hidden_types: [String]! + user_confidence_level: ConfidenceLevel + effective_confidence_level: EffectiveConfidenceLevel + no_creators: Boolean + restrict_delete: Boolean + allowed_marking: [MarkingDefinition!] + default_marking: [DefaultMarking!] + max_shareable_marking: [MarkingDefinition!] + otp_mandatory: Boolean + groups(orderBy: GroupsOrdering, orderMode: OrderingMode): GroupConnection + default_dashboards: [Workspace!]! + default_dashboard: Workspace + default_time_field: String + account_status: String! + account_lock_after_date: DateTime + administrated_organizations: [Organization!]! + unit_system: UnitSystem + submenu_show_icons: Boolean + submenu_auto_collapse: Boolean + monochrome_labels: Boolean + can_manage_sensitive_config: Boolean + draftContext: DraftWorkspace +} + +type SessionDetail { + id: ID! + created: DateTime + ttl: Int + originalMaxAge: Int +} + +type UserSession { + user: Creator + sessions: [SessionDetail] +} + +input UserAddInput { + "*Constraints:*\n* Minimal length: `5`\n* Must match format: `email`\n" + user_email: String! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + password: String! + firstname: String + lastname: String + description: String + language: String + theme: String + objectOrganization: [ID!] + account_status: String + account_lock_after_date: DateTime + unit_system: String + submenu_show_icons: Boolean + submenu_auto_collapse: Boolean + monochrome_labels: Boolean + groups: [ID!] + user_confidence_level: ConfidenceLevelInput +} + +input ConfidenceLevelInput { + max_confidence: Int + overrides: [ConfidenceLevelOverrideInput!]! +} + +input ConfidenceLevelOverrideInput { + entity_type: String! + max_confidence: Int! +} + +input UserLoginInput { + email: String! + password: String! +} + +input UserOTPLoginInput { + code: String! +} + +input UserOTPActivationInput { + secret: String! + code: String! +} + +enum RolesOrdering { + name + created_at + updated_at + _score +} + +type RoleConnection { + pageInfo: PageInfo! + edges: [RoleEdge!] +} + +type RoleEdge { + cursor: String! + node: Role! +} + +type Role implements BasicObject & InternalObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + name: String! + description: String + created_at: DateTime! + updated_at: DateTime! + capabilities: [Capability] + editContext: [EditUserContext!] + can_manage_sensitive_config: Boolean +} + +input RoleAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + clientMutationId: String +} + +type CapabilityConnection { + pageInfo: PageInfo! + edges: [CapabilityEdge] +} + +type CapabilityEdge { + cursor: String! + node: Capability! +} + +type Capability implements BasicObject & InternalObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + name: String! + description: String + attribute_order: Int + created_at: DateTime! + updated_at: DateTime! + editContext: [EditUserContext!] +} + +enum ConnectorType { + EXTERNAL_IMPORT + INTERNAL_IMPORT_FILE + INTERNAL_ENRICHMENT + INTERNAL_ANALYSIS + INTERNAL_EXPORT_FILE + STREAM +} + +input ExportAskInput { + format: String! + exportType: String! + contentMaxMarkings: [String] + fileMarkings: [String] +} + +input StixCoreObjectsExportAskInput { + format: String! + exportType: String! + contentMaxMarkings: [String] + fileMarkings: [String] + search: String + exportContext: ExportContext + orderBy: StixCoreObjectsOrdering + orderMode: OrderingMode + filters: FilterGroup + selectedIds: [String] +} + +input StixCoreRelationshipsExportAskInput { + format: String! + exportType: String! + contentMaxMarkings: [String] + fileMarkings: [String] + exportContext: ExportContext + search: String + orderBy: StixCoreRelationshipsOrdering + orderMode: OrderingMode + selectedIds: [String] + fromOrToId: [String] + elementWithTargetTypes: [String] + fromId: [String] + fromRole: String + fromTypes: [String] + toId: [String] + toRole: String + toTypes: [String] + relationship_type: [String] + filters: FilterGroup +} + +input StixCyberObservablesExportAskInput { + format: String! + exportType: String! + exportContext: ExportContext + contentMaxMarkings: [String] + fileMarkings: [String] + search: String + orderBy: StixCyberObservablesOrdering + orderMode: OrderingMode + filters: FilterGroup + selectedIds: [String] +} + +input RegisterConnectorInput { + id: ID! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + type: ConnectorType! + scope: [String!] + auto: Boolean + only_contextual: Boolean + playbook_compatible: Boolean +} + +type RabbitMQConnection { + host: String! + vhost: String! + use_ssl: Boolean! + port: Int! + user: String! + pass: String! +} + +input ConnectorInfoInput { + run_and_terminate: Boolean! + buffering: Boolean! + queue_threshold: Float! + queue_messages_size: Float! + next_run_datetime: DateTime + last_run_datetime: DateTime +} + +type ConnectorInfo { + run_and_terminate: Boolean! + buffering: Boolean! + queue_threshold: Float! + queue_messages_size: Float! + next_run_datetime: DateTime + last_run_datetime: DateTime +} + +type ConnectorConfig { + connection: RabbitMQConnection! + listen: String! + listen_routing: String! + listen_exchange: String! + push: String! + push_routing: String! + push_exchange: String! +} + +type ConnectorMetadata { + configuration: String! +} + +type ConnectorConfiguration { + id: ID! + name: String! + configuration: String! +} + +type ConnectorQueueDetails { + messages_number: Float! + messages_size: Float! +} + +type Connector implements BasicObject & InternalObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + name: String! + active: Boolean + auto: Boolean + only_contextual: Boolean + playbook_compatible: Boolean + connector_trigger_filters: String + connector_type: String + connector_scope: [String!] + connector_state: String + connector_schema: String + connector_schema_ui: String + connector_state_reset: Boolean + connector_user_id: ID + connector_user: User + connector_queue_details: ConnectorQueueDetails! + connector_info: ConnectorInfo + updated_at: DateTime + created_at: DateTime + config: ConnectorConfig + works(status: String): [Work] + built_in: Boolean + configurations: [ConnectorConfiguration!] +} + +type RuleExecutionError { + timestamp: DateTime + source: String + error: String +} + +type RuleManager { + id: ID! + activated: Boolean! + lastEventId: String + errors: [RuleExecutionError] +} + +type DisplayStep { + source: String + source_color: String + relation: String + target: String + target_color: String + identifier: String + identifier_color: String + action: String +} + +type Display { + if: [DisplayStep] + then: [DisplayStep] +} + +type Rule { + id: ID! + name: String! + description: String! + activated: Boolean! + category: String + display: Display +} + +type InferenceAttribute { + field: String! + value: String! +} + +type Inference { + rule: Rule! + explanation: [StixObjectOrStixRelationship]! + attributes: [InferenceAttribute] +} + +enum DraftOperation { + create + update + delete +} + +type DraftVersion { + draft_id: String! + draft_operation: DraftOperation! +} + +interface StixObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + creators: [Creator!] + x_opencti_inferences: [Inference] +} + +enum StixMetaObjectsOrdering { + entity_type + created + modified + spec_version + created_at + updated_at + _score +} + +type StixMetaObjectConnection { + pageInfo: PageInfo! + edges: [StixMetaObjectEdge] +} + +type StixMetaObjectEdge { + cursor: String! + node: StixMetaObject! +} + +interface StixMetaObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + created: DateTime + modified: DateTime +} + +enum MarkingDefinitionsOrdering { + definition_type + definition + x_opencti_order + x_opencti_color + created + modified + created_at + updated_at + _score +} + +type MarkingDefinitionConnection { + pageInfo: PageInfo! + edges: [MarkingDefinitionEdge!]! +} + +type MarkingDefinitionEdge { + cursor: String! + node: MarkingDefinition! +} + +type MarkingDefinition implements BasicObject & StixObject & StixMetaObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + created: DateTime + modified: DateTime + definition_type: String + definition: String + x_opencti_order: Int! + x_opencti_color: String + creators: [Creator!] + toStix: String + editContext: [EditUserContext!] +} + +input MarkingDefinitionAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + definition_type: String! + definition: String! + x_opencti_order: Int! + x_opencti_color: String + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean +} + +type MarkingDefinitionShort { + id: ID! + standard_id: String! + entity_type: String! + representative: Representative + definition_type: String + definition: String + x_opencti_order: Int! + x_opencti_color: String +} + +enum LabelsOrdering { + value + color + created + modified + created_at + updated_at + _score +} + +type LabelConnection { + pageInfo: PageInfo! + edges: [LabelEdge!]! +} + +type LabelEdge { + cursor: String! + node: Label! +} + +type Label implements BasicObject & StixObject & StixMetaObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + created: DateTime + modified: DateTime + value: String + color: String + creators: [Creator!] + toStix: String + editContext: [EditUserContext!] +} + +input LabelAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + value: String! + color: String + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean +} + +enum ExternalReferencesOrdering { + source_name + url + hash + external_id + created + modified + created_at + updated_at + creator + _score +} + +type ExternalReferenceConnection { + pageInfo: PageInfo! + edges: [ExternalReferenceEdge!]! +} + +type ExternalReferenceEdge { + cursor: String! + node: ExternalReference! +} + +type ExternalReference implements BasicObject & StixObject & StixMetaObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + created: DateTime + modified: DateTime + source_name: String! + description: String + url: String + hash: String + external_id: String + references(types: [String]): StixObjectOrStixRelationshipConnection + fileId: String + creators: [Creator!] + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection! + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection! + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input ExternalReferenceAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + source_name: String! + description: String + url: String + hash: String + file: Upload + external_id: String + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean +} + +enum KillChainPhasesOrdering { + x_opencti_order + kill_chain_name + phase_name + created + modified + created_at + updated_at + _score +} + +type KillChainPhaseConnection { + pageInfo: PageInfo! + edges: [KillChainPhaseEdge!]! +} + +type KillChainPhaseEdge { + cursor: String! + node: KillChainPhase! +} + +type KillChainPhase implements BasicObject & StixObject & StixMetaObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + created: DateTime + modified: DateTime + kill_chain_name: String! + phase_name: String! + x_opencti_order: Int + creators: [Creator!] + editContext: [EditUserContext!] +} + +input KillChainPhaseAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + kill_chain_name: String! + phase_name: String! + x_opencti_order: Int! + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean +} + +type Representative { + main: String! + secondary: String +} + +enum StixCoreObjectsOrdering { + name + entity_type + created + modified + created_at + updated_at + start_time + stop_time + published + valid_from + valid_until + first_seen + last_seen + indicator_pattern + x_opencti_workflow_id + createdBy + creator + objectMarking + observable_value + subject + value + opinions_metrics_mean + opinions_metrics_min + opinions_metrics_max + opinions_metrics_total + _score +} + +type StixCoreObjectConnection { + pageInfo: PageInfo! + edges: [StixCoreObjectEdge!]! +} + +type StixCoreObjectEdge { + cursor: String! + node: StixCoreObject! +} + +union OrganizationOrIndividual = Organization | Individual + +interface StixCoreObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + opinions_metrics: OpinionsMetrics +} + +enum StixDomainObjectsOrdering { + name + entity_type + created + modified + created_at + updated_at + published + valid_from + valid_until + indicator_pattern + x_opencti_workflow_id + createdBy + creator + objectMarking + _score + first_seen + last_seen + attribute_count + x_opencti_negative + confidence + first_observed + last_observed + number_observed + incident_type + severity + priority + rating + context + attribute_abstract + opinion + pattern_type + report_types + note_types + channel_types + x_opencti_base_severity + event_types + x_opencti_organization_type + submitted + product + result_name + operatingSystem + x_opencti_cvss_base_severity +} + +type StixDomainObjectConnection { + pageInfo: PageInfo! + edges: [StixDomainObjectEdge] +} + +type StixDomainObjectEdge { + cursor: String! + node: StixDomainObject! +} + +interface StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input StixDomainObjectAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + confidence: Int + pattern_type: String + context: String + pattern: String + aliases: [String] + x_opencti_aliases: [String] + type: String! + createdBy: String + objectMarking: [String] + objectLabel: [String] + killChainPhases: [String] + externalReferences: [String] + objects: [String] + clientMutationId: String + created: DateTime + modified: DateTime + update: Boolean +} + +enum AttackPatternsOrdering { + x_mitre_id + name + created + modified + created_at + updated_at + x_opencti_workflow_id + _score +} + +type AttackPatternConnection { + pageInfo: PageInfo! + edges: [AttackPatternEdge!]! +} + +type AttackPatternEdge { + cursor: String! + node: AttackPattern! +} + +type AttackPattern implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + x_mitre_platforms: [String!] + x_mitre_permissions_required: [String] + x_mitre_detection: String + x_mitre_id: String + killChainPhases: [KillChainPhase!] + coursesOfAction(first: Int, after: ID, orderBy: CoursesOfActionOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): CourseOfActionConnection + parentAttackPatterns(first: Int, after: ID, orderBy: AttackPatternsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): AttackPatternConnection + subAttackPatterns(first: Int, after: ID, orderBy: AttackPatternsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): AttackPatternConnection + isSubAttackPattern: Boolean + dataComponents: DataComponentConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input AttackPatternAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + revoked: Boolean + lang: String + confidence: Int + x_mitre_platforms: [String!] + x_mitre_permissions_required: [String] + x_mitre_detection: String + x_mitre_id: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + killChainPhases: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +type AttackPatternForMatrix { + attack_pattern_id: String! + name: String! + description: String + x_mitre_id: String + subAttackPatternsIds: [String!] + subAttackPatternsSearchText: String + killChainPhasesIds: [String!] +} + +type AttackPatternsByKillChain { + kill_chain_id: String! + kill_chain_name: String! + phase_name: String! + x_opencti_order: Int! + attackPatterns: [AttackPatternForMatrix!] +} + +type AttackPatternsMatrix { + attackPatternsOfPhases: [AttackPatternsByKillChain!] +} + +enum CampaignsOrdering { + name + first_seen + last_seen + role_played + created + modified + created_at + updated_at + objectMarking + x_opencti_workflow_id + confidence + _score +} + +type CampaignConnection { + pageInfo: PageInfo! + edges: [CampaignEdge] +} + +type CampaignEdge { + cursor: String! + node: Campaign! +} + +type Campaign implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + first_seen: DateTime + last_seen: DateTime + objective: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input CampaignAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + revoked: Boolean + lang: String + confidence: Int + first_seen: DateTime + last_seen: DateTime + objective: String + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum ContainersOrdering { + name + published + created + modified + created_at + updated_at + createdBy + objectMarking + x_opencti_workflow_id + creator + entity_type + _score +} + +type ContainerConnection { + pageInfo: PageInfo! + edges: [ContainerEdge] +} + +type ContainerEdge { + cursor: String! + node: Container! +} + +interface Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + creators: [Creator!] + workflowEnabled: Boolean + status: Status +} + +enum NotesOrdering { + attribute_abstract + created + modified + created_at + updated_at + createdBy + x_opencti_workflow_id + objectMarking + note_types + creator + _score +} + +type NoteConnection { + pageInfo: PageInfo! + edges: [NoteEdge!]! +} + +type NoteEdge { + cursor: String! + node: Note! +} + +type Note implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + attribute_abstract: String + content: String! + authors: [String] + note_types: [String] + likelihood: Int + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input NoteAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + attribute_abstract: String + + "*Constraints:*\n* Minimal length: `2`\n" + content: String! + authors: [String] + note_types: [String] + likelihood: Int + revoked: Boolean + lang: String + createdBy: String + confidence: Int + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + objects: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +input NoteUserAddInput { + stix_id: String + x_opencti_stix_ids: [String] + attribute_abstract: String + + "*Constraints:*\n* Minimal length: `2`\n" + content: String! + note_types: [String] + likelihood: Int + revoked: Boolean + lang: String + confidence: Int + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + objects: [String] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean +} + +enum ObservedDatasOrdering { + first_observed + last_observed + number_observed + created + modified + created_at + updated_at + createdBy + x_opencti_workflow_id + objectMarking + confidence + _score +} + +type ObservedDataConnection { + pageInfo: PageInfo! + edges: [ObservedDataEdge] +} + +type ObservedDataEdge { + cursor: String! + node: ObservedData! +} + +type ObservedData implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + first_observed: DateTime! + last_observed: DateTime! + number_observed: Int! + name: String! + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input ObservedDataAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + first_observed: DateTime! + last_observed: DateTime! + number_observed: Int! + revoked: Boolean + lang: String + confidence: Int + createdBy: String + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + objects: [String]! + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum OpinionsOrdering { + opinion + created + modified + created_at + updated_at + createdBy + objectMarking + x_opencti_workflow_id + confidence + creator + _score +} + +type OpinionConnection { + pageInfo: PageInfo! + edges: [OpinionEdge] +} + +type OpinionEdge { + cursor: String! + node: Opinion! +} + +type Opinion implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + explanation: String + authors: [String] + opinion: String! + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input OpinionAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n" + opinion: String! + explanation: String + authors: [String] + revoked: Boolean + lang: String + confidence: Int + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + objects: [String] + created: DateTime + modified: DateTime + update: Boolean + x_opencti_workflow_id: String + clientMutationId: String + file: Upload +} + +input OpinionUserAddInput { + stix_id: String + x_opencti_stix_ids: [String] + opinion: String! + explanation: String + authors: [String] + revoked: Boolean + lang: String + confidence: Int + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + objects: [String] + created: DateTime + modified: DateTime + update: Boolean + clientMutationId: String +} + +enum ReportsOrdering { + name + created + modified + published + created_at + updated_at + createdBy + creator + objectMarking + report_types + x_opencti_workflow_id + _score +} + +type ReportConnection { + pageInfo: PageInfo! + edges: [ReportEdge] +} + +type ReportEdge { + cursor: String! + node: Report! +} + +type Report implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + name: String! + description: String + content: String + content_mapping: String + report_types: [String] + x_opencti_reliability: String + published: DateTime + objectParticipant: [Participant!] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + deleteWithElementsCount: Int +} + +input ReportAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + content: String + content_mapping: String + published: DateTime! + report_types: [String] + x_opencti_reliability: String + revoked: Boolean + lang: String + confidence: Int + createdBy: String + objectOrganization: [String] + objectMarking: [String] + objectAssignee: [String] + objectParticipant: [String] + objectLabel: [String] + externalReferences: [String] + objects: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum CoursesOfActionOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + objectMarking + x_mitre_id + _score +} + +type CourseOfActionConnection { + pageInfo: PageInfo! + edges: [CourseOfActionEdge] +} + +type CourseOfActionEdge { + cursor: String! + node: CourseOfAction! +} + +type CourseOfAction implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + x_opencti_aliases: [String] + x_mitre_id: String + x_opencti_threat_hunting: String + x_opencti_log_sources: [String] + attackPatterns: AttackPatternConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input CourseOfActionAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + x_opencti_aliases: [String] + x_mitre_id: String + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum IdentitiesOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + _score +} + +type IdentityConnection { + pageInfo: PageInfo! + edges: [IdentityEdge] +} + +type IdentityEdge { + cursor: String! + node: Identity! +} + +enum IdentityType { + Sector + Organization + Individual + System +} + +interface Identity { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + avatar: OpenCtiFile + identity_class: String! + name: String! + description: String + roles: [String] + contact_information: String + x_opencti_aliases: [String] + x_opencti_reliability: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input IdentityAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + type: IdentityType! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + x_opencti_workflow_id: String + clientMutationId: String + created: DateTime + modified: DateTime + update: Boolean +} + +enum IndividualsOrdering { + name + firstname + lastname + created + modified + x_opencti_workflow_id + objectMarking + _score +} + +type IndividualConnection { + pageInfo: PageInfo! + edges: [IndividualEdge] +} + +type IndividualEdge { + cursor: String! + node: Individual! +} + +type Individual implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Identity { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + identity_class: String! + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + x_opencti_reliability: String + x_opencti_firstname: String + x_opencti_lastname: String + organizations: OrganizationConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + isUser: Boolean +} + +input IndividualAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + x_opencti_firstname: String + x_opencti_lastname: String + x_opencti_reliability: String + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectOrganization: [String] + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum SectorsOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + objectMarking + _score +} + +type SectorConnection { + pageInfo: PageInfo! + edges: [SectorEdge] +} + +type SectorEdge { + cursor: String! + types: [String] + node: Sector! +} + +type Sector implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Identity { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + identity_class: String! + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + x_opencti_reliability: String + parentSectors: SectorConnection + subSectors: SectorConnection + isSubSector: Boolean + targetedOrganizations: StixCoreRelationshipConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input SectorAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum SystemsOrdering { + name + confidence + firstname + lastname + created + modified + x_opencti_workflow_id + _score +} + +type SystemConnection { + pageInfo: PageInfo! + edges: [SystemEdge] +} + +type SystemEdge { + cursor: String! + node: System! +} + +type System implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Identity { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + identity_class: String! + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + x_opencti_reliability: String + x_opencti_firstname: String + x_opencti_lastname: String + organizations: OrganizationConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input SystemAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + x_opencti_firstname: String + x_opencti_lastname: String + x_opencti_reliability: String + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectOrganization: [String] + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum InfrastructuresOrdering { + name + infrastructure_types + first_seen + last_seen + created + modified + created_at + updated_at + x_opencti_workflow_id + confidence + createdBy + objectMarking + creator + _score +} + +type InfrastructureConnection { + pageInfo: PageInfo! + edges: [InfrastructureEdge] +} + +type InfrastructureEdge { + cursor: String! + node: Infrastructure! +} + +type Infrastructure implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + aliases: [String] + description: String + infrastructure_types: [String] + first_seen: DateTime + last_seen: DateTime + killChainPhases: [KillChainPhase!] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input InfrastructureAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + infrastructure_types: [String] + first_seen: DateTime + last_seen: DateTime + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectOrganization: [String] + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + killChainPhases: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum IntrusionSetsOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + resource_level + primary_motivation + confidence + _score + objectMarking +} + +type IntrusionSetConnection { + pageInfo: PageInfo! + edges: [IntrusionSetEdge] +} + +type IntrusionSetEdge { + cursor: String! + node: IntrusionSet! +} + +type IntrusionSet implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + first_seen: DateTime + last_seen: DateTime + goals: [String] + resource_level: String + primary_motivation: String + secondary_motivations: [String] + locations: LocationConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input IntrusionSetAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + first_seen: DateTime + last_seen: DateTime + goals: [String] + resource_level: String + primary_motivation: String + secondary_motivations: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + x_opencti_workflow_id: String + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean + file: Upload +} + +enum LocationsOrdering { + name + latitude + longitude + created + modified + created_at + updated_at + x_opencti_workflow_id + _score +} + +type LocationConnection { + pageInfo: PageInfo! + edges: [LocationEdge] +} + +type LocationEdge { + cursor: String! + types: [String] + node: Location! +} + +interface Location { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + avatar: OpenCtiFile + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input LocationAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + type: String! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + clientMutationId: String + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + update: Boolean +} + +enum PositionsOrdering { + name + postal_address + postal_code + created + modified + created_at + updated_at + x_opencti_workflow_id + _score +} + +type PositionConnection { + pageInfo: PageInfo! + edges: [PositionEdge] +} + +type PositionEdge { + cursor: String! + node: Position! +} + +type Position implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Location { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + street_address: String + postal_code: String + city: City + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input PositionAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + street_address: String + postal_code: String + confidence: Int + revoked: Boolean + lang: String + x_opencti_aliases: [String] + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum CitiesOrdering { + name + aliases + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + _score +} + +type CityConnection { + pageInfo: PageInfo! + edges: [CityEdge] +} + +type CityEdge { + cursor: String! + node: City! +} + +type City implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Location { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + country: Country + administrativeArea: AdministrativeArea + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input CityAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + confidence: Int + revoked: Boolean + lang: String + x_opencti_aliases: [String] + createdBy: String + objectOrganization: [String] + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum CountriesOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + _score +} + +type CountryConnection { + pageInfo: PageInfo! + edges: [CountryEdge!]! +} + +type CountryEdge { + cursor: String! + node: Country! +} + +type Country implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Location { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + region: Region + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input CountryAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + confidence: Int + revoked: Boolean + lang: String + x_opencti_aliases: [String] + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum RegionsOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + _score +} + +type RegionConnection { + pageInfo: PageInfo! + edges: [RegionEdge] +} + +type RegionEdge { + cursor: String! + node: Region! +} + +type Region implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Location { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + parentRegions: RegionConnection + subRegions: RegionConnection + countries: CountryConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input RegionAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + confidence: Int + revoked: Boolean + lang: String + x_opencti_aliases: [String] + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum MalwaresOrdering { + name + malware_types + first_seen + last_seen + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + is_family + confidence + _score +} + +type MalwareConnection { + pageInfo: PageInfo! + edges: [MalwareEdge] +} + +type MalwareEdge { + cursor: String! + node: Malware! +} + +type Malware implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + malware_types: [String] + is_family: Boolean + first_seen: DateTime + last_seen: DateTime + architecture_execution_envs: [String] + implementation_languages: [String] + capabilities: [String] + killChainPhases: [KillChainPhase!] + samples: [StixCyberObservable!] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input MalwareAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + malware_types: [String] + aliases: [String] + is_family: Boolean + first_seen: DateTime + last_seen: DateTime + architecture_execution_envs: [String] + implementation_languages: [String] + capabilities: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + killChainPhases: [String] + samples: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum ThreatActorsOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + confidence + sophistication + resource_level + _score + threat_actor_types + objectMarking +} + +type ThreatActorGroupConnection { + pageInfo: PageInfo! + edges: [ThreatActorGroupEdge] +} + +type ThreatActorGroupEdge { + cursor: String! + node: ThreatActorGroup! +} + +interface ThreatActor implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + threat_actor_types: [String] + first_seen: DateTime + last_seen: DateTime + roles: [String] + goals: [String] + sophistication: String + resource_level: String + primary_motivation: String + secondary_motivations: [String] + personal_motivations: [String] + locations: LocationConnection + countries: CountryConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +type ThreatActorEdge { + cursor: String! + node: ThreatActor! +} + +type ThreatActorConnection { + pageInfo: PageInfo! + edges: [ThreatActorEdge] +} + +type ThreatActorGroup implements BasicObject & StixObject & StixCoreObject & StixDomainObject & ThreatActor { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + threat_actor_types: [String] + first_seen: DateTime + last_seen: DateTime + roles: [String] + goals: [String] + sophistication: String + resource_level: String + primary_motivation: String + secondary_motivations: [String] + personal_motivations: [String] + locations: LocationConnection + countries: CountryConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input ThreatActorGroupAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + threat_actor_types: [String] + first_seen: DateTime + last_seen: DateTime + roles: [String] + goals: [String] + sophistication: String + resource_level: String + primary_motivation: String + secondary_motivations: [String] + personal_motivations: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectAssignee: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum ToolsOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + confidence + _score +} + +type ToolConnection { + pageInfo: PageInfo! + edges: [ToolEdge] +} + +type ToolEdge { + cursor: String! + node: Tool! +} + +type Tool implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + tool_types: [String] + tool_version: String + killChainPhases: [KillChainPhase!] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input ToolAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + tool_types: [String] + tool_version: String + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + killChainPhases: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum VulnerabilitiesOrdering { + name + x_opencti_cvss_base_score + x_opencti_cvss_base_severity + x_opencti_cvss_attack_vector + created + modified + created_at + updated_at + x_opencti_workflow_id + creator + confidence + _score +} + +type VulnerabilityConnection { + pageInfo: PageInfo! + edges: [VulnerabilityEdge] +} + +type VulnerabilityEdge { + cursor: String! + node: Vulnerability! +} + +type Vulnerability implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + x_opencti_aliases: [String] + x_opencti_cvss_base_score: Float + x_opencti_cvss_base_severity: String + x_opencti_cvss_attack_vector: String + x_opencti_cvss_integrity_impact: String + x_opencti_cvss_availability_impact: String + x_opencti_cvss_confidentiality_impact: String + x_opencti_cisa_kev: Boolean + x_opencti_epss_score: Float + x_opencti_epss_percentile: Float + softwares(first: Int, after: ID, orderBy: StixCyberObservablesOrdering, orderMode: OrderingMode): StixCyberObservableConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input VulnerabilityAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + x_opencti_aliases: [String] + x_opencti_cvss_base_score: Float + x_opencti_cvss_base_severity: String + x_opencti_cvss_attack_vector: String + x_opencti_cvss_integrity_impact: String + x_opencti_cvss_availability_impact: String + x_opencti_cvss_confidentiality_impact: String + x_opencti_cisa_kev: Boolean + x_opencti_epss_score: Float + x_opencti_epss_percentile: Float + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum IncidentsOrdering { + name + first_seen + last_seen + incident_type + severity + source + created + modified + created_at + updated_at + x_opencti_workflow_id + objectMarking + confidence + objectAssignee + creator + _score +} + +type IncidentConnection { + pageInfo: PageInfo! + edges: [IncidentEdge] +} + +type IncidentEdge { + cursor: String! + node: Incident! +} + +type Incident implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + first_seen: DateTime + last_seen: DateTime + objective: String + incident_type: String + severity: String + source: String + objectParticipant: [Participant!] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input IncidentAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + confidence: Int + revoked: Boolean + lang: String + objective: String + first_seen: DateTime + last_seen: DateTime + aliases: [String] + incident_type: String + severity: String + source: String + createdBy: String + objectOrganization: [String] + objectMarking: [String] + objectAssignee: [String] + objectParticipant: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +enum StixCyberObservablesOrdering { + entity_type + created_at + updated_at + observable_value + objectMarking + createdBy + creator + _score +} + +type StixCyberObservableConnection { + pageInfo: PageInfo! + edges: [StixCyberObservableEdge!]! +} + +type StixCyberObservableEdge { + cursor: String! + node: StixCyberObservable! +} + +interface StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +type AutonomousSystem implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + number: Int + name: String + rir: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input AutonomousSystemAddInput { + number: Int! + name: String + rir: String + file: Upload +} + +type Directory implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + path: String! + path_enc: String + ctime: DateTime + mtime: DateTime + atime: DateTime + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input DirectoryAddInput { + path: String! + path_enc: String + ctime: DateTime + mtime: DateTime + atime: DateTime + file: Upload +} + +type DomainName implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + observable_value: String! + x_opencti_score: Int + x_opencti_description: String + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input DomainNameAddInput { + value: String! + file: Upload +} + +type EmailAddr implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + display_name: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input EmailAddrAddInput { + value: String + display_name: String + file: Upload +} + +type EmailMessage implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + is_multipart: Boolean + attribute_date: DateTime + content_type: String + message_id: String + subject: String + received_lines: [String] + body: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input EmailMessageAddInput { + is_multipart: Boolean + attribute_date: DateTime + content_type: String + message_id: String + subject: String + received_lines: [String] + body: String + file: Upload +} + +type EmailMimePartType implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + body: String + content_type: String + content_disposition: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input EmailMimePartTypeAddInput { + body: String + content_type: String + content_disposition: String + file: Upload +} + +input HashInput { + "*Constraints:*\n* Minimal length: `3`\n" + algorithm: String! + + "*Constraints:*\n* Minimal length: `5`\n" + hash: String! +} + +type Hash { + algorithm: String! + hash: String +} + +type StixFileEdge { + cursor: String! + node: StixFile! +} + +type StixFileConnection { + pageInfo: PageInfo! + edges: [StixFileEdge] +} + +interface HashedObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + hashes: [Hash] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +type Artifact implements BasicObject & StixObject & StixCoreObject & StixCyberObservable & HashedObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + hashes: [Hash] + mime_type: String + payload_bin: String + url: String + encryption_algorithm: String + decryption_key: String + x_opencti_additional_names: [String] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input ArtifactAddInput { + hashes: [HashInput] + mime_type: String + payload_bin: String + url: String + encryption_algorithm: String + decryption_key: String + x_opencti_additional_names: [String] + file: Upload +} + +type StixFile implements BasicObject & StixObject & StixCoreObject & StixCyberObservable & HashedObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + hashes: [Hash] + extensions: String + size: Int + name: String + name_enc: String + magic_number_hex: String + mime_type: String + ctime: DateTime + mtime: DateTime + atime: DateTime + x_opencti_additional_names: [String] + obsContent: Artifact + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input StixFileAddInput { + hashes: [HashInput] + size: Int + name: String + name_enc: String + magic_number_hex: String + mime_type: String + ctime: DateTime + mtime: DateTime + atime: DateTime + x_opencti_additional_names: [String] + obsContent: ID + file: Upload +} + +type X509Certificate implements BasicObject & StixObject & StixCoreObject & StixCyberObservable & HashedObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + hashes: [Hash] + is_self_signed: Boolean + version: String + serial_number: String + signature_algorithm: String + issuer: String + subject: String + subject_public_key_algorithm: String + subject_public_key_modulus: String + subject_public_key_exponent: Int + validity_not_before: DateTime + validity_not_after: DateTime + basic_constraints: String + name_constraints: String + policy_constraints: String + key_usage: String + extended_key_usage: String + subject_key_identifier: String + authority_key_identifier: String + subject_alternative_name: String + issuer_alternative_name: String + subject_directory_attributes: String + crl_distribution_points: String + inhibit_any_policy: String + private_key_usage_period_not_before: DateTime + private_key_usage_period_not_after: DateTime + certificate_policies: String + policy_mappings: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input X509CertificateAddInput { + hashes: [HashInput] + is_self_signed: Boolean + version: String + serial_number: String + signature_algorithm: String + issuer: String + subject: String + subject_public_key_algorithm: String + subject_public_key_modulus: String + subject_public_key_exponent: Int + validity_not_before: DateTime + validity_not_after: DateTime + basic_constraints: String + name_constraints: String + policy_constraints: String + key_usage: String + extended_key_usage: String + subject_key_identifier: String + authority_key_identifier: String + subject_alternative_name: String + issuer_alternative_name: String + subject_directory_attributes: String + crl_distribution_points: String + inhibit_any_policy: String + private_key_usage_period_not_before: DateTime + private_key_usage_period_not_after: DateTime + certificate_policies: String + policy_mappings: String + file: Upload +} + +type IPv4Addr implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + countries: CountryConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input IPv4AddrAddInput { + value: String + belongsTo: [String] + resolvesTo: [String] + file: Upload +} + +type IPv6Addr implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + countries: CountryConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input IPv6AddrAddInput { + value: String + file: Upload +} + +type MacAddr implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input MacAddrAddInput { + value: String + file: Upload +} + +type Mutex implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + name: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input MutexAddInput { + name: String + file: Upload +} + +type NetworkTraffic implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + extensions: String + start: DateTime + end: DateTime + is_active: Boolean + src_port: Int + dst_port: Int + protocols: [String] + src_byte_count: Int + dst_byte_count: Int + src_packets: Int + dst_packets: Int + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input NetworkTrafficAddInput { + start: DateTime + end: DateTime + is_active: Boolean + networkSrc: String + networkDst: String + src_port: Int + dst_port: Int + protocols: [String] + src_byte_count: Int + dst_byte_count: Int + src_packets: Int + dst_packets: Int + file: Upload +} + +type Process implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + extensions: String + is_hidden: Boolean + pid: Int + created_time: DateTime + cwd: String + command_line: String + environment_variables: [String] + aslr_enabled: Boolean + dep_enabled: Boolean + priority: String + owner_sid: String + window_title: String + startup_info: [Dictionary] + integrity_level: String + service_name: String + descriptions: [String] + display_name: String + group_name: String + start_type: String + serviceDlls: StixFileConnection + service_type: String + service_status: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input ProcessAddInput { + is_hidden: Boolean + pid: Int + created_time: DateTime + cwd: String + x_opencti_description: String + command_line: String! + environment_variables: [String] + aslr_enabled: Boolean + dep_enabled: Boolean + priority: String + owner_sid: String + window_title: String + startup_info: [DictionaryInput] + integrity_level: String + service_name: String + descriptions: [String] + display_name: String + group_name: String + start_type: String + serviceDlls: [String] + service_type: String + service_status: String + file: Upload +} + +type Software implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + name: String + cpe: String + swid: String + languages: [String] + vendor: String + version: String + vulnerabilities: VulnerabilityConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +type SoftwareConnection { + pageInfo: PageInfo! + edges: [SoftwareEdge!]! +} + +type SoftwareEdge { + cursor: String! + node: Software! +} + +input SoftwareAddInput { + name: String + cpe: String + swid: String + languages: [String] + vendor: String + version: String + file: Upload +} + +type Url implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input UrlAddInput { + value: String + file: Upload +} + +type UserAccount implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + extensions: String + user_id: String + credential: String + account_login: String + account_type: String + display_name: String + is_service_account: Boolean + is_privileged: Boolean + can_escalate_privs: Boolean + is_disabled: Boolean + account_created: DateTime + account_expires: DateTime + credential_last_changed: DateTime + account_first_login: DateTime + account_last_login: DateTime + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input UserAccountAddInput { + user_id: String + credential: String + account_login: String + account_type: String + display_name: String + is_service_account: Boolean + is_privileged: Boolean + can_escalate_privs: Boolean + is_disabled: Boolean + account_created: DateTime + account_expires: DateTime + credential_last_changed: DateTime + account_first_login: DateTime + account_last_login: DateTime + file: Upload +} + +type WindowsRegistryKey implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + attribute_key: String + modified_time: DateTime + number_of_subkeys: Int + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input WindowsRegistryKeyAddInput { + attribute_key: String + modified_time: DateTime + file: Upload + number_of_subkeys: Int +} + +type WindowsRegistryValueType implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + name: String + data: String + data_type: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input WindowsRegistryValueTypeAddInput { + name: String + data: String + data_type: String + file: Upload +} + +type CryptographicKey implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input CryptographicKeyAddInput { + value: String + file: Upload +} + +type CryptocurrencyWallet implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input CryptocurrencyWalletAddInput { + value: String + file: Upload +} + +type Hostname implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input HostnameAddInput { + value: String + file: Upload +} + +type Text implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input TextAddInput { + value: String + file: Upload +} + +type UserAgent implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input UserAgentAddInput { + value: String + file: Upload +} + +type BankAccount implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + iban: String + bic: String + account_number: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input BankAccountAddInput { + iban: String + bic: String + account_number: String + file: Upload +} + +type TrackingNumber implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!], elementId: [String]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup, filterMode: FilterMode): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, filterMode: FilterMode, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, filterMode: FilterMode): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input TrackingNumberAddInput { + value: String + file: Upload +} + +type Credential implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!], elementId: [String]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup, filterMode: FilterMode): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, filterMode: FilterMode, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, filterMode: FilterMode): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input CredentialAddInput { + value: String + file: Upload +} + +type PhoneNumber implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + value: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input PhoneNumberAddInput { + value: String + file: Upload +} + +type PaymentCard implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + card_number: String + expiration_date: DateTime + cvv: Int + holder_name: String + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input PaymentCardAddInput { + card_number: String! + expiration_date: DateTime + cvv: Int + holder_name: String + file: Upload +} + +type MediaContent implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectLabel: [Label!] + objectOrganization: [Organization!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + title: String + description: String + content: String + media_category: String + url: String + publication_date: DateTime + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input MediaContentAddInput { + title: String + content: String + media_category: String + url: String! + publication_date: DateTime + file: Upload +} + +type Persona implements BasicObject & StixObject & StixCoreObject & StixCyberObservable { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectLabel: [Label!] + objectOrganization: [Organization!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + x_opencti_score: Int + x_opencti_description: String + observable_value: String! + indicators(first: Int): IndicatorConnection + persona_name: String! + persona_type: String! + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] +} + +input PersonaAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + persona_name: String! + persona_type: String! +} + +interface BasicRelationship { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + fromRole: String + toRole: String + created_at: DateTime! + updated_at: DateTime! + creators: [Creator!] +} + +type InternalRelationship implements BasicRelationship { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + fromRole: String + toRole: String + created_at: DateTime! + updated_at: DateTime! + from: InternalObject + to: InternalObject + creators: [Creator!] +} + +input InternalRelationshipAddInput { + relationship_type: String! + fromId: ID + toId: ID +} + +enum StixObjectOrStixRelationshipsOrdering { + name + entity_type + created_at + updated_at + createdBy + objectMarking + objectLabel + observable_value + start_time + created + modified + relationship_type + creator + _score +} + +type StixObjectOrStixRelationshipConnection { + pageInfo: PageInfo! + edges: [StixObjectOrStixRelationshipEdge] +} + +type StixObjectOrStixRelationshipRefConnection { + pageInfo: PageInfo! + edges: [StixObjectOrStixRelationshipRefEdge] +} + +type StixObjectOrStixRelationshipEdge { + cursor: String! + node: StixObjectOrStixRelationship! +} + +type StixObjectOrStixRelationshipRefEdge { + cursor: String! + types: [String]! + node: StixObjectOrStixRelationship! +} + +union StixObjectOrStixRelationshipOrCreator = MarkingDefinition | Label | KillChainPhase | ExternalReference | AttackPattern | Campaign | Channel | Event | Narrative | Note | ObservedData | Opinion | Report | Grouping | CourseOfAction | Individual | Organization | Sector | System | Indicator | Infrastructure | IntrusionSet | Language | City | AdministrativeArea | Country | Region | Position | Malware | MalwareAnalysis | ThreatActorGroup | ThreatActorIndividual | Tool | Vulnerability | Incident | AutonomousSystem | Directory | DomainName | EmailAddr | EmailMessage | EmailMimePartType | Artifact | StixFile | X509Certificate | IPv4Addr | IPv6Addr | MacAddr | Mutex | NetworkTraffic | Process | Software | Url | UserAccount | WindowsRegistryKey | WindowsRegistryValueType | CryptographicKey | CryptocurrencyWallet | Hostname | Text | UserAgent | BankAccount | Credential | TrackingNumber | PhoneNumber | PaymentCard | MediaContent | Persona | StixCoreRelationship | StixSightingRelationship | StixRefRelationship | Task | DataComponent | DataSource | CaseIncident | CaseRfi | CaseRft | Feedback | CaseTemplate | EntitySetting | ManagerConfiguration | Creator | Group | Workspace | CsvMapper | Status | PublicDashboard + +union StixObjectOrStixRelationship = MarkingDefinition | Label | KillChainPhase | ExternalReference | AttackPattern | Campaign | Channel | Event | Narrative | Note | ObservedData | Opinion | Report | Grouping | CourseOfAction | Individual | Organization | Sector | System | Indicator | Infrastructure | IntrusionSet | Language | City | AdministrativeArea | Country | Region | Position | Malware | MalwareAnalysis | ThreatActorGroup | ThreatActorIndividual | Tool | Vulnerability | Incident | AutonomousSystem | Directory | DomainName | EmailAddr | EmailMessage | EmailMimePartType | Artifact | StixFile | X509Certificate | IPv4Addr | IPv6Addr | MacAddr | Mutex | NetworkTraffic | Process | Software | Url | UserAccount | WindowsRegistryKey | WindowsRegistryValueType | CryptographicKey | CryptocurrencyWallet | Hostname | Text | UserAgent | BankAccount | Credential | TrackingNumber | PhoneNumber | PaymentCard | MediaContent | Persona | StixCoreRelationship | StixSightingRelationship | StixRefRelationship | DataComponent | DataSource | CaseIncident | CaseRfi | CaseRft | Feedback | CaseTemplate | Task | EntitySetting | ManagerConfiguration | Workspace | CsvMapper | PublicDashboard + +union StixCoreObjectOrStixCoreRelationship = AttackPattern | Campaign | Channel | Event | Note | ObservedData | Opinion | Report | Grouping | CourseOfAction | Individual | Organization | Sector | Indicator | Infrastructure | IntrusionSet | Language | City | AdministrativeArea | Country | Region | Position | Malware | MalwareAnalysis | Narrative | ThreatActorGroup | ThreatActorIndividual | Tool | Vulnerability | Incident | AutonomousSystem | Directory | DomainName | EmailAddr | EmailMessage | EmailMimePartType | Artifact | StixFile | X509Certificate | IPv4Addr | IPv6Addr | MacAddr | Mutex | NetworkTraffic | Process | Software | Url | UserAccount | WindowsRegistryKey | WindowsRegistryValueType | CryptographicKey | CryptocurrencyWallet | Hostname | Text | UserAgent | BankAccount | Credential | TrackingNumber | PhoneNumber | PaymentCard | MediaContent | Persona | StixCoreRelationship | DataComponent | DataSource | CaseIncident | CaseRfi | CaseRft | Feedback | CaseTemplate | Task | EntitySetting | ManagerConfiguration | Workspace | PublicDashboard + +enum StixRelationshipsOrdering { + entity_type + relationship_type + confidence + start_time + stop_time + created + modified + created_at + updated_at + objectMarking + objectLabel + killChainPhase + toName + toValidFrom + toValidUntil + toObservableValue + toPatternType + x_opencti_workflow_id + createdBy + creator + _score +} + +type StixRelationshipConnection { + pageInfo: PageInfo! + edges: [StixRelationshipEdge] +} + +type StixRelationshipEdge { + cursor: String! + node: StixRelationship! +} + +interface StixRelationship { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + fromRole: String + toRole: String + created_at: DateTime! + updated_at: DateTime! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + from: StixObjectOrStixRelationshipOrCreator + to: StixObjectOrStixRelationshipOrCreator + x_opencti_inferences: [Inference] + spec_version: String! + created: DateTime + modified: DateTime + confidence: Int + relationship_type: String! + createdBy: Identity + objectMarking: [MarkingDefinition!] + toStix: String + draftVersion: DraftVersion + creators: [Creator!] +} + +type StixRelationshipSchema { + key: String! + values: [String!]! +} + +type StixRelationshipRefSchemaValue { + name: String! + toTypes: [String!]! +} + +type StixRelationshipRefSchema { + key: String! + values: [StixRelationshipRefSchemaValue!]! +} + +enum StixCoreRelationshipsOrdering { + entity_type + relationship_type + confidence + start_time + stop_time + created + modified + created_at + updated_at + objectMarking + objectLabel + killChainPhase + toName + toValidFrom + toValidUntil + toObservableValue + toPatternType + x_opencti_workflow_id + createdBy + creator + _score +} + +type StixCoreRelationshipConnection { + pageInfo: PageInfo! + edges: [StixCoreRelationshipEdge!]! +} + +type StixCoreRelationshipEdge { + cursor: String! + node: StixCoreRelationship! +} + +type StixCoreRelationship implements BasicRelationship & StixRelationship { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + fromRole: String + toRole: String + created_at: DateTime! + updated_at: DateTime! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + from: StixObjectOrStixRelationshipOrCreator + fromId: String! + fromType: String! + to: StixObjectOrStixRelationshipOrCreator + toId: String! + toType: String! + x_opencti_inferences: [Inference] + spec_version: String! + created: DateTime + modified: DateTime + confidence: Int + relationship_type: String! + createdBy: Identity + objectMarking: [MarkingDefinition!] + draftVersion: DraftVersion + description: String + start_time: DateTime + stop_time: DateTime + revoked: Boolean! + lang: String + objectLabel: [Label!] + objectOrganization: [Organization!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + killChainPhases: [KillChainPhase!] + creators: [Creator!] + toStix: String + editContext: [EditUserContext!] + status: Status + workflowEnabled: Boolean +} + +input StixCoreRelationshipAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + fromId: StixRef! + toId: StixRef! + created: DateTime + modified: DateTime + confidence: Int + relationship_type: String! + createdBy: String + objectMarking: [String] + description: String + start_time: DateTime + stop_time: DateTime + revoked: Boolean + lang: String + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + killChainPhases: [String] + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean +} + +enum StixSightingRelationshipsOrdering { + confidence + x_opencti_negative + first_seen + last_seen + created + modified + created_at + updated_at + objectMarking + objectLabel + toName + toValidFrom + toValidUntil + toPatternType + toCreatedAt + attribute_count + x_opencti_workflow_id + _score +} + +type StixSightingRelationshipConnection { + pageInfo: PageInfo! + edges: [StixSightingRelationshipsEdge] +} + +type StixSightingRelationshipsEdge { + cursor: String! + node: StixSightingRelationship! +} + +type StixSightingRelationship implements BasicRelationship & StixRelationship { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + fromRole: String + toRole: String + created_at: DateTime! + updated_at: DateTime! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + from: StixObjectOrStixRelationshipOrCreator + fromId: String! + fromType: String! + to: StixObjectOrStixRelationshipOrCreator + toId: String! + toType: String! + x_opencti_inferences: [Inference] + spec_version: String! + created: DateTime + modified: DateTime + confidence: Int + relationship_type: String! + createdBy: Identity + objectMarking: [MarkingDefinition!] + draftVersion: DraftVersion + description: String + first_seen: DateTime + last_seen: DateTime + attribute_count: Int! + x_opencti_negative: Boolean! + objectLabel: [Label!] + objectOrganization: [Organization!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + creators: [Creator!] + toStix: String + editContext: [EditUserContext!] + status: Status + workflowEnabled: Boolean +} + +input StixSightingRelationshipAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + fromId: StixRef! + toId: StixRef! + created: DateTime + modified: DateTime + confidence: Int + createdBy: String + objectMarking: [String] + description: String + first_seen: DateTime + last_seen: DateTime + attribute_count: Int! + x_opencti_negative: Boolean + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + clientMutationId: String + update: Boolean + x_opencti_workflow_id: String +} + +enum StixRefRelationshipsOrdering { + relationship_type + entity_type + confidence + start_time + stop_time + created + modified + created_at + updated_at + toName + toValidFrom + toValidUntil + toPatternType + toCreatedAt + _score +} + +type StixRefRelationshipConnection { + pageInfo: PageInfo! + edges: [StixRefRelationshipEdge] +} + +type StixRefRelationshipEdge { + cursor: String! + node: StixRefRelationship! +} + +type StixRefRelationship implements BasicRelationship & StixRelationship { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + fromRole: String + toRole: String + created_at: DateTime! + updated_at: DateTime! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + from: StixObjectOrStixRelationshipOrCreator + to: StixObjectOrStixRelationshipOrCreator + x_opencti_inferences: [Inference] + spec_version: String! + created: DateTime + modified: DateTime + confidence: Int + relationship_type: String! + createdBy: Identity + objectMarking: [MarkingDefinition!] + draftVersion: DraftVersion + start_time: DateTime + stop_time: DateTime + datable: Boolean + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + notes(first: Int): NoteConnection + reports(first: Int): ReportConnection + opinions(first: Int): OpinionConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + toStix: String + creators: [Creator!] + editContext: [EditUserContext!] +} + +type DefinitionRefRelationship { + entity: StixObjectOrStixRelationshipOrCreator! + from: [String!] + to: [String!] +} + +input StixRefRelationshipAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + fromId: StixRef + toId: StixRef + relationship_type: String! + confidence: Int + createdBy: String + start_time: DateTime + stop_time: DateTime + objectMarking: [String] + objectLabel: [String] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean + file: Upload +} + +input StixRefRelationshipsAddInput { + relationship_type: String! + fromIds: [StixRef] + toIds: [StixRef!]! +} + +type Query { + stix(id: String!): String + enrichmentConnectors(type: String!): [Connector] + about: AppInfo + logsWorkerConfig: LogsWorkerConfig + rabbitMQMetrics(prefix: String): RabbitMQMetrics + elasticSearchMetrics: ElasticSearchMetrics + logs(first: Int, after: ID, orderBy: LogsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): LogConnection + audits(first: Int, after: ID, types: [String!], orderBy: LogsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): LogConnection + auditsNumber(dateAttribute: String, types: [String], startDate: DateTime, endDate: DateTime, onlyInferred: Boolean, filters: FilterGroup, search: String): Number + auditsTimeSeries(field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, types: [String], filters: FilterGroup, search: String): [TimeSeries] + auditsDistribution(field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + auditsMultiTimeSeries(operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, timeSeriesParameters: [AuditsTimeSeriesParameters]): [MultiTimeSeries] + subType(id: String!): SubType + subTypes(first: Int, after: ID, orderBy: SubTypesOrdering, orderMode: OrderingMode, type: String, includeParents: Boolean, search: String): SubTypeConnection! + file(id: String!): File + importFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + filesMetrics: FilesMetrics + indexedFiles(first: Int, after: ID, search: String): IndexedFileConnection + indexedFilesCount(search: String): Int + indexedFilesMetrics: FilesMetrics + settings: Settings! + group(id: String!): Group + groups(first: Int, after: ID, orderBy: GroupsOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): GroupConnection + roles(first: Int, after: ID, orderBy: RolesOrdering, orderMode: OrderingMode, search: String): RoleConnection + me: MeUser! + otpGeneration: OtpElement + user(id: String!): User + creators(entityTypes: [String!]): CreatorConnection + assignees(entityTypes: [String!]): AssigneeConnection + participants(entityTypes: [String!]): ParticipantConnection + members(first: Int, search: String, filters: FilterGroup, filterMode: FilterMode, entityTypes: [MemberType!]): MemberConnection + systemMembers: MemberConnection + users(first: Int, after: ID, orderBy: UsersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): UserConnection + sessions: [UserSession] + role(id: String!): Role + capabilities(first: Int): CapabilityConnection + connector(id: String!): Connector + connectors: [Connector!] + connectorsForWorker: [Connector] + connectorsForExport: [Connector] + connectorsForImport: [Connector] + connectorsForAnalysis: [Connector] + connectorsForNotification: [Connector] + work(id: ID!): Work + works(first: Int, after: ID, orderBy: WorksOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): WorkConnection + runtimeAttributes(first: Int, search: String, orderMode: OrderingMode, attributeName: String!): AttributeConnection + schemaAttributeNames(elementType: [String]!): AttributeConnection + retentionRule(id: String!): RetentionRule + retentionRules(first: Int, after: ID, search: String, orderBy: RetentionRuleOrdering, orderMode: OrderingMode): RetentionRuleConnection + taxiiCollection(id: String!): TaxiiCollection + taxiiCollections(first: Int, after: ID, orderBy: TaxiiCollectionOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): TaxiiCollectionConnection + streamCollection(id: String!): StreamCollection + feed(id: String!): Feed + feeds(first: Int, after: ID, orderBy: FeedOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FeedConnection + streamCollections(first: Int, after: ID, orderBy: StreamCollectionOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): StreamCollectionConnection! + statusTemplate(id: String!): StatusTemplate + statusTemplates(first: Int, after: ID, orderBy: StatusTemplateOrdering, orderMode: OrderingMode, search: String): StatusTemplateConnection + status(id: String!): Status + statuses(first: Int, after: ID, orderBy: StatusOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): StatusConnection + backgroundTask(id: String!): BackgroundTask + backgroundTasks(first: Int, after: ID, orderBy: BackgroundTasksOrdering, orderMode: OrderingMode, includeAuthorities: Boolean, filters: FilterGroup, search: String): BackgroundTaskConnection + rule(id: String!): Rule + rules: [Rule] + ruleManagerInfo: RuleManager + synchronizer(id: String!): Synchronizer + synchronizers(first: Int, after: ID, orderBy: SynchronizersOrdering, orderMode: OrderingMode, search: String): SynchronizerConnection + synchronizerFetch(input: SynchronizerFetchInput): [RemoteStreamCollection] + stixMetaObject(id: String!): StixMetaObject + stixMetaObjects(first: Int, after: ID, types: [String], orderBy: StixMetaObjectsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): StixMetaObjectConnection + markingDefinition(id: String!): MarkingDefinition + markingDefinitions(first: Int, after: ID, orderBy: MarkingDefinitionsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): MarkingDefinitionConnection + label(id: String!): Label + labels(first: Int, after: ID, orderBy: LabelsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): LabelConnection + externalReference(id: String!): ExternalReference + externalReferences(first: Int, after: ID, orderBy: ExternalReferencesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): ExternalReferenceConnection + killChainPhase(id: String!): KillChainPhase + killChainPhases(first: Int, after: ID, orderBy: KillChainPhasesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): KillChainPhaseConnection + stixCoreObjectRaw(id: String!): String + stixCoreObject(id: String!): StixCoreObject + stixCoreObjectAnalysis(id: ID!, contentSource: String!, contentType: AnalysisContentType!): Analysis + stixCoreObjects(first: Int, after: ID, types: [String], orderBy: StixCoreObjectsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): StixCoreObjectConnection + globalSearch(first: Int, after: ID, search: String, types: [String], orderBy: StixCoreObjectsOrdering, orderMode: OrderingMode, filters: FilterGroup): StixCoreObjectConnection + stixCoreObjectsExportFiles(first: Int, exportContext: ExportContext!): FileConnection + stixCoreObjectsTimeSeries(authorId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, types: [String], filters: FilterGroup, search: String): [TimeSeries] + stixCoreObjectsMultiTimeSeries(startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, timeSeriesParameters: [StixCoreObjectsTimeSeriesParameters]): [MultiTimeSeries] + stixCoreObjectsNumber(dateAttribute: String, types: [String], startDate: DateTime, endDate: DateTime, onlyInferred: Boolean, filters: FilterGroup, search: String): Number + stixCoreObjectsMultiNumber(dateAttribute: String, startDate: DateTime, endDate: DateTime, onlyInferred: Boolean, numberParameters: [StixCoreObjectsNumberParameters]): [Number] + stixCoreObjectsDistribution(objectId: [String], relationship_type: [String], toTypes: [String], elementWithTargetTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreObjectsMultiDistribution(field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, distributionParameters: StixCoreObjectsDistributionParameters): [MultiDistribution] + filtersRepresentatives(filters: FilterGroup!): [RepresentativeWithId!]! + stixDomainObject(id: String!): StixDomainObject + stixDomainObjects(first: Int, after: ID, types: [String], orderBy: StixDomainObjectsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): StixDomainObjectConnection + bookmarks(first: Int, after: ID, types: [String], filters: FilterGroup): StixDomainObjectConnection + stixDomainObjectsExportFiles(first: Int, exportContext: ExportContext!): FileConnection + stixDomainObjectsTimeSeries(authorId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, types: [String], onlyInferred: Boolean, filters: FilterGroup, search: String): [TimeSeries] + stixDomainObjectsNumber(dateAttribute: String, types: [String], endDate: DateTime, onlyInferred: Boolean, filters: FilterGroup, search: String): Number + stixDomainObjectsDistribution(objectId: [String], relationship_type: [String], toTypes: [String], elementWithTargetTypes: [String], field: String!, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + attackPattern(id: String): AttackPattern + attackPatterns(first: Int, after: ID, orderBy: AttackPatternsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): AttackPatternConnection + attackPatternsMatrix: AttackPatternsMatrix + campaign(id: String): Campaign + campaigns(first: Int, after: ID, orderBy: CampaignsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CampaignConnection + campaignsTimeSeries(objectId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!, relationship_type: [String]): [TimeSeries] + container(id: String): Container + containers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ContainerConnection + containersObjectsOfObject(id: String!, types: [String], filters: FilterGroup, search: String): StixObjectOrStixRelationshipConnection + containersNumber(objectId: String, endDate: DateTime): Number + note(id: String): Note + notes(first: Int, after: ID, orderBy: NotesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): NoteConnection + notesNumber(objectId: String, endDate: DateTime): Number + notesTimeSeries(objectId: String, authorId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!): [TimeSeries] + notesDistribution(objectId: String, field: String!, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String): [Distribution] + noteContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + observedData(id: String): ObservedData + observedDatas(first: Int, after: ID, orderBy: ObservedDatasOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ObservedDataConnection + observedDatasTimeSeries(objectId: String, authorId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!): [TimeSeries] + observedDatasNumber(objectId: String, endDate: DateTime): Number + observedDatasDistribution(objectId: String, field: String!, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String): [Distribution] + observedDataContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + opinion(id: String): Opinion + opinions(first: Int, after: ID, orderBy: OpinionsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): OpinionConnection + opinionsTimeSeries(objectId: String, authorId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!): [TimeSeries] + opinionsNumber(objectId: String, endDate: DateTime): Number + opinionsDistribution(objectId: String, field: String!, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String): [Distribution] + opinionContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + myOpinion(id: String!): Opinion + report(id: String): Report + reports(first: Int, after: ID, orderBy: ReportsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ReportConnection + reportsTimeSeries(objectId: String, authorId: String, reportType: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!, filters: FilterGroup, search: String): [TimeSeries] + reportsNumber(reportType: String, objectId: String, authorId: String, endDate: DateTime, filters: FilterGroup, search: String): Number + reportsDistribution(objectId: String, authorId: String, field: String!, operation: StatsOperation!, limit: Int, order: String, startDate: DateTime, endDate: DateTime, dateAttribute: String, filters: FilterGroup, search: String): [Distribution] + reportContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + courseOfAction(id: String): CourseOfAction + coursesOfAction(first: Int, after: ID, orderBy: CoursesOfActionOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CourseOfActionConnection + identity(id: String!): Identity + identities(first: Int, after: ID, types: [String], orderBy: IdentitiesOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup, toStix: Boolean): IdentityConnection + individual(id: String!): Individual + individuals(first: Int, after: ID, orderBy: IndividualsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): IndividualConnection + sector(id: String): Sector + sectors(first: Int, after: ID, orderBy: SectorsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): SectorConnection + system(id: String): System + systems(first: Int, after: ID, orderBy: SystemsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): SystemConnection + infrastructure(id: String!): Infrastructure + infrastructures(first: Int, after: ID, orderBy: InfrastructuresOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): InfrastructureConnection + intrusionSet(id: String): IntrusionSet + intrusionSets(first: Int, after: ID, orderBy: IntrusionSetsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): IntrusionSetConnection + location(id: String!): Location + locations(first: Int, after: ID, types: [String], orderBy: LocationsOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup, toStix: Boolean): LocationConnection + city(id: String): City + cities(first: Int, after: ID, orderBy: CitiesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CityConnection + country(id: String): Country + countries(first: Int, after: ID, orderBy: CountriesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CountryConnection + region(id: String!): Region + regions(first: Int, after: ID, orderBy: RegionsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): RegionConnection + position(id: String!): Position + positions(first: Int, after: ID, orderBy: PositionsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): PositionConnection + malware(id: String): Malware + malwares(first: Int, after: ID, orderBy: MalwaresOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): MalwareConnection + threatActor(id: String): ThreatActor + threatActors(first: Int, after: ID, orderBy: ThreatActorsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ThreatActorConnection + threatActorGroup(id: String): ThreatActorGroup + threatActorsGroup(first: Int, after: ID, orderBy: ThreatActorsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ThreatActorGroupConnection + tool(id: String): Tool + tools(first: Int, after: ID, orderBy: ToolsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ToolConnection + vulnerability(id: String): Vulnerability + vulnerabilities(first: Int, after: ID, orderBy: VulnerabilitiesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): VulnerabilityConnection + incident(id: String): Incident + incidents(first: Int, after: ID, orderBy: IncidentsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): IncidentConnection + incidentsTimeSeries(objectId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!, relationship_type: [String]): [TimeSeries] + stixCyberObservable(id: String!): StixCyberObservable + stixCyberObservables(first: Int, after: ID, types: [String], orderBy: StixCyberObservablesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): StixCyberObservableConnection + stixCyberObservablesExportFiles(first: Int, exportContext: ExportContext!): FileConnection + stixCyberObservablesNumber(dateAttribute: String, types: [String], authorId: String, endDate: DateTime, filters: FilterGroup, search: String): Number + stixCyberObservablesTimeSeries(types: [String], filters: FilterGroup, search: String): [TimeSeries] + stixCyberObservablesDistribution(objectId: String, field: String!, dateAttribute: String, operation: String!, filters: FilterGroup, search: String): [Distribution] + stixRelationship(id: String): StixRelationship + stixRelationships(first: Int, after: ID, orderBy: StixRelationshipsOrdering, orderMode: OrderingMode, fromOrToId: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, startDate: DateTime, endDate: DateTime, confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup, stix: Boolean): StixRelationshipConnection + stixRelationshipsTimeSeries(field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup): [TimeSeries] + stixRelationshipsMultiTimeSeries(operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, timeSeriesParameters: [StixRelationshipsTimeSeriesParameters]): [MultiTimeSeries] + stixRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup, aggregateOnConnections: Boolean): [Distribution] + stixRelationshipsNumber(dateAttribute: String, authorId: String, noDirection: Boolean, endDate: DateTime, onlyInferred: Boolean, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup): Number + schemaRelationsTypesMapping: [StixRelationshipSchema!]! + schemaRelationsRefTypesMapping: [StixRelationshipRefSchema!]! + filterKeysSchema: [FilterKeysSchema!]! + stixCoreRelationship(id: String): StixCoreRelationship + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, startDate: DateTime, endDate: DateTime, confidences: [Int], search: String, filters: FilterGroup, stix: Boolean): StixCoreRelationshipConnection + stixCoreRelationshipsTimeSeries(field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup): [TimeSeries] + stixCoreRelationshipsMultiTimeSeries(operation: StatsOperation!, startDate: DateTime!, endDate: DateTime, interval: String!, onlyInferred: Boolean, timeSeriesParameters: [StixCoreRelationshipsTimeSeriesParameters]): [MultiTimeSeries] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup, aggregateOnConnections: Boolean): [Distribution] + stixCoreRelationshipsNumber(dateAttribute: String, authorId: String, noDirection: Boolean, endDate: DateTime, onlyInferred: Boolean, fromOrToId: [String], elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup, dynamicFrom: FilterGroup, dynamicTo: FilterGroup): Number + stixCoreRelationshipsExportFiles(first: Int, exportContext: ExportContext!): FileConnection + stixSightingRelationship(id: String): StixSightingRelationship + stixSightingRelationships(first: Int, after: ID, orderBy: StixSightingRelationshipsOrdering, orderMode: OrderingMode, fromOrToId: String, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, search: String, filters: FilterGroup, toStix: Boolean): StixSightingRelationshipConnection + stixSightingRelationshipsTimeSeries(fromOrToId: String, fromId: StixRef, toId: StixRef, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!, fromTypes: [String], toTypes: [String], search: String, filters: FilterGroup): [TimeSeries] + stixSightingRelationshipsDistribution(fromOrToId: String, fromId: StixRef, toId: StixRef, field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, limit: Int, order: String, fromTypes: [String], toTypes: [String], search: String, filters: FilterGroup): [Distribution] + stixSightingRelationshipsNumber(dateAttribute: String, fromOrToId: String, fromId: StixRef, toId: StixRef, endDate: DateTime, fromTypes: [String], toTypes: [String], search: String, filters: FilterGroup): Number + stixRefRelationship(id: String): StixRefRelationship + stixRefRelationships(first: Int, after: ID, orderBy: StixRefRelationshipsOrdering, orderMode: OrderingMode, fromOrToId: String, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: [String], startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, search: String, filters: FilterGroup, toStix: Boolean): StixRefRelationshipConnection + stixNestedRefRelationships(first: Int, after: ID, orderBy: StixRefRelationshipsOrdering, orderMode: OrderingMode, fromOrToId: String, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: [String], startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, search: String, filters: FilterGroup, toStix: Boolean): StixRefRelationshipConnection + stixSchemaRefRelationships(id: String, toType: String): DefinitionRefRelationship + stixRefRelationshipsDistribution(field: String!, operation: StatsOperation!, relationship_type: [String], isTo: Boolean, toRole: String, toTypes: [String], startDate: DateTime, endDate: DateTime, dateAttribute: String, limit: Int, order: String): [Distribution] + stixRefRelationshipsNumber(types: [String!], fromId: StixRef, endDate: DateTime): Number + stixObjectOrStixRelationship(id: String!): StixObjectOrStixRelationship + stixObjectOrStixRelationships(first: Int, after: ID, search: String, filters: FilterGroup): StixObjectOrStixRelationshipConnection + stixCoreObjectOrStixCoreRelationship(id: String!): StixCoreObjectOrStixCoreRelationship + channel(id: String!): Channel + channels(first: Int, after: ID, orderBy: ChannelsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): ChannelConnection + language(id: String!): Language + languages(first: Int, after: ID, orderBy: LanguagesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): LanguageConnection + event(id: String!): Event + events(first: Int, after: ID, orderBy: EventsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): EventConnection + grouping(id: String!): Grouping + groupings(first: Int, after: ID, orderBy: GroupingsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): GroupingConnection + groupingsTimeSeries(objectId: String, authorId: String, groupingType: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!, filters: FilterGroup, search: String): [TimeSeries] + groupingsNumber(groupingContext: String, objectId: String, authorId: String, endDate: DateTime, filters: FilterGroup): Number + groupingsDistribution(objectId: String, authorId: String, field: String!, operation: StatsOperation!, limit: Int, order: String, startDate: DateTime, endDate: DateTime, dateAttribute: String, filters: FilterGroup, search: String): [Distribution] + groupingContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + narrative(id: String!): Narrative + narratives(first: Int, after: ID, orderBy: NarrativesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): NarrativeConnection + triggerKnowledge(id: String!): Trigger + triggersKnowledge(first: Int, after: ID, orderBy: TriggersOrdering, orderMode: OrderingMode, filters: FilterGroup, includeAuthorities: Boolean, search: String): TriggerConnection + triggersKnowledgeCount(filters: FilterGroup, includeAuthorities: Boolean, search: String): Int + triggerActivity(id: String!): Trigger + triggersActivity(first: Int, after: ID, orderBy: TriggersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): TriggerConnection + notification(id: String!): Notification + notifications(first: Int, after: ID, orderBy: NotificationsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): NotificationConnection + myNotifications(first: Int, after: ID, orderBy: NotificationsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): NotificationConnection + myUnreadNotificationsCount: Int + dataComponent(id: String!): DataComponent + dataComponents(first: Int, after: ID, orderBy: DataComponentsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): DataComponentConnection + dataSource(id: String!): DataSource + dataSources(first: Int, after: ID, orderBy: DataSourcesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): DataSourceConnection + vocabulary(id: String!): Vocabulary + vocabularyCategories: [VocabularyDefinition!]! + vocabularies(category: VocabularyCategory, first: Int, after: ID, orderBy: VocabularyOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): VocabularyConnection + administrativeArea(id: String!): AdministrativeArea + administrativeAreas(first: Int, after: ID, orderBy: AdministrativeAreasOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): AdministrativeAreaConnection + task(id: String!): Task + tasks(first: Int, after: ID, orderBy: TasksOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): TaskConnection + taskContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + taskTemplate(id: String!): TaskTemplate + taskTemplates(first: Int, after: ID, orderBy: TaskTemplatesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): TaskTemplateConnection + case(id: String!): Case + cases(first: Int, after: ID, orderBy: CasesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CaseConnection + caseTemplate(id: String!): CaseTemplate + caseTemplates(first: Int, after: ID, orderBy: CaseTemplatesOrdering, orderMode: OrderingMode, search: String): CaseTemplateConnection + caseIncident(id: String!): CaseIncident + caseIncidents(first: Int, after: ID, orderBy: CaseIncidentsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CaseIncidentConnection + caseIncidentContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + caseRfi(id: String!): CaseRfi + caseRfis(first: Int, after: ID, orderBy: CaseRfisOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CaseRfiConnection + caseRfiContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + caseRft(id: String!): CaseRft + caseRfts(first: Int, after: ID, orderBy: CaseRftsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): CaseRftConnection + caseRftContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + feedback(id: String!): Feedback + feedbacks(first: Int, after: ID, orderBy: FeedbacksOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): FeedbackConnection + feedbackContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + entitySetting(id: String!): EntitySetting + entitySettingByType(targetType: String!): EntitySetting + entitySettings(first: Int, after: ID, orderBy: EntitySettingsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): EntitySettingConnection + workspace(id: String!): Workspace + workspaces(first: Int, after: ID, orderBy: WorkspacesOrdering, orderMode: OrderingMode, filters: FilterGroup, includeAuthorities: Boolean, search: String): WorkspaceConnection + malwareAnalysis(id: String!): MalwareAnalysis + malwareAnalyses(first: Int, after: ID, orderBy: MalwareAnalysesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): MalwareAnalysisConnection + managerConfiguration(id: String!): ManagerConfiguration + managerConfigurationByManagerId(managerId: String!): ManagerConfiguration + notificationNotifiers: [Notifier!]! + notifier(id: String!): Notifier + notifierTest(input: NotifierTestInput!): String + notifiers(first: Int, after: ID, orderBy: NotifierOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): NotifierConnection + threatActorIndividual(id: String!): ThreatActorIndividual + threatActorsIndividuals(first: Int, after: ID, orderBy: ThreatActorsIndividualOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): ThreatActorIndividualConnection + threatActorIndividualContainsStixObjectOrStixRelationship(id: String!, stixObjectOrStixRelationshipId: String!): Boolean + playbook(id: String!): Playbook + playbooks(first: Int, after: ID, orderBy: PlaybooksOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): PlaybookConnection + playbookComponents: [PlaybookComponent]! + playbooksForEntity(id: String!): [Playbook] + ingestionRss(id: String!): IngestionRss + ingestionRsss(first: Int, after: ID, orderBy: IngestionRssOrdering, orderMode: OrderingMode, filters: FilterGroup, includeAuthorities: Boolean, search: String): IngestionRssConnection + ingestionTaxii(id: String!): IngestionTaxii + ingestionTaxiis(first: Int, after: ID, orderBy: IngestionTaxiiOrdering, orderMode: OrderingMode, filters: FilterGroup, includeAuthorities: Boolean, search: String): IngestionTaxiiConnection + ingestionCsv(id: String!): IngestionCsv + ingestionCsvs(first: Int, after: ID, orderBy: IngestionCsvOrdering, orderMode: OrderingMode, filters: FilterGroup, includeAuthorities: Boolean, search: String): IngestionCsvConnection + indicator(id: String!): Indicator + indicators(first: Int, after: ID, orderBy: IndicatorsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): IndicatorConnection + indicatorsTimeSeries(objectId: String, field: String!, operation: StatsOperation!, startDate: DateTime!, endDate: DateTime!, interval: String!, filters: FilterGroup): [TimeSeries] + indicatorsNumber(pattern_type: String, objectId: String, endDate: DateTime): Number + indicatorsDistribution(objectId: String, field: String!, operation: StatsOperation!, limit: Int, order: String, startDate: DateTime, endDate: DateTime, dateAttribute: String): [Distribution] + decayRule(id: String!): DecayRule + decayRules(first: Int, after: ID, orderBy: DecayRuleOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): DecayRuleConnection + organization(id: String!): Organization + organizations(first: Int, after: ID, orderBy: OrganizationsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, toStix: Boolean): OrganizationConnection + csvMapper(id: String!): CsvMapper + csvMappers(first: Int, after: ID, orderBy: CsvMapperOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): CsvMapperConnection + csvMapperTest(configuration: String!, content: String!): CsvMapperTestResult + csvMapperSchemaAttributes: [CsvMapperSchemaAttributes!]! + publicDashboard(id: String!): PublicDashboard + publicDashboards(first: Int, after: ID, orderBy: PublicDashboardsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): PublicDashboardConnection + publicDashboardByUriKey(uri_key: String!): PublicDashboard + publicStixCoreObjectsNumber(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): Number + publicStixRelationshipsNumber(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): Number + publicStixCoreObjectsMultiTimeSeries(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): [MultiTimeSeries] + publicStixRelationshipsMultiTimeSeries(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): [MultiTimeSeries] + publicStixCoreObjectsDistribution(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): [PublicDistribution] + publicStixRelationshipsDistribution(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): [PublicDistribution] + publicBookmarks(uriKey: String!, widgetId: String!): StixDomainObjectConnection + publicStixCoreObjects(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): StixCoreObjectConnection + publicStixRelationships(uriKey: String!, widgetId: String!, startDate: DateTime, endDate: DateTime): StixRelationshipConnection + obasStixCoreObjectSimulationsResult(id: ID!): StixObjectSimulationsResult + obasScenarioElementsDistribution(id: ID!, type: ScenarioType, filters: FilterGroup): [Distribution] + deleteOperation(id: String!): DeleteOperation + deleteOperations(first: Int, after: ID, orderBy: DeleteOperationOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): DeleteOperationConnection + supportPackage(id: String!): SupportPackage + supportPackages(first: Int, after: ID, orderBy: SupportPackageOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): SupportPackageConnection + exclusionList(id: String!): ExclusionList + exclusionLists(first: Int, after: ID, orderBy: ExclusionListOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): ExclusionListConnection + draftWorkspace(id: String!): DraftWorkspace + draftWorkspaces(first: Int, after: ID, orderBy: DraftWorkspacesOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): DraftWorkspaceConnection + draftWorkspaceEntities(draftId: String!, types: [String], first: Int, after: ID, orderBy: StixCoreObjectsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): StixCoreObjectConnection + draftWorkspaceRelationships(draftId: String!, types: [String], first: Int, after: ID, orderBy: StixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String): StixRelationshipConnection +} + +type Subscription { + me: MeUser + settings(id: ID!): Settings + settingsMessages(id: ID!): Settings + group(id: ID!): Group + user(id: ID!): User + label(id: ID!): Label + statusTemplate(id: ID!): StatusTemplate + markingDefinition(id: ID!): MarkingDefinition + killChainPhase(id: ID!): KillChainPhase + stixCoreObject(id: ID!): StixCoreObject + internalObject(id: ID!): InternalObject @deprecated(reason: "[>=6.3 & <6.6]. Not used in the platform.") + stixDomainObject(id: ID!): StixDomainObject + stixCyberObservable(id: ID!): StixCyberObservable + stixCoreRelationship(id: ID!): StixCoreRelationship + stixSightingRelationship(id: ID!): StixSightingRelationship + stixRefRelationship(id: ID!): StixRefRelationship + externalReference(id: ID!): ExternalReference + notification: Notification + notificationsNumber: NotificationCount + entitySetting(id: ID!): EntitySetting + workspace(id: ID!): Workspace + managerConfiguration(id: ID!): ManagerConfiguration + aiBus(id: ID!): AIBus +} + +type WorkEditMutations { + delete: ID! + ping: ID! + reportExpectation(error: WorkErrorInput): ID! + addExpectations(expectations: Int): ID! + toReceived(message: String): ID! + toProcessed(message: String, inError: Boolean): ID! +} + +type SettingsEditMutations { + fieldPatch(input: [EditInput]!): Settings + contextPatch(input: EditContext): Settings + contextClean: Settings + editMessage(input: SettingsMessageInput!): Settings + deleteMessage(input: String!): Settings +} + +type SubTypeEditMutations { + statusAdd(input: StatusAddInput!): SubType + statusFieldPatch(statusId: String!, input: [EditInput]!): SubType + statusDelete(statusId: String!): SubType +} + +type GroupEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): Group + contextPatch(input: EditContext): Group + contextClean: Group + relationAdd(input: InternalRelationshipAddInput!): InternalRelationship + relationDelete(fromId: StixRef, toId: StixRef, relationship_type: String!): Group + editDefaultMarking(input: DefaultMarkingInput!): Group +} + +type UserEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): User + contextPatch(input: EditContext): User + contextClean: User + tokenRenew: User + relationAdd(input: InternalRelationshipAddInput!): InternalRelationship + relationDelete(toId: StixRef!, relationship_type: String!): User + organizationAdd(organizationId: ID!): User + organizationDelete(organizationId: ID!): User +} + +type RoleEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): Role + contextPatch(input: EditContext): Role + contextClean: Role + relationAdd(input: InternalRelationshipAddInput!): InternalRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Role +} + +type AttributeEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): Attribute +} + +type TaxiiCollectionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): TaxiiCollection +} + +type StreamCollectionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): StreamCollection + addGroup(id: ID!): StreamCollection + deleteGroup(id: ID!): StreamCollection +} + +type SynchronizerEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): Synchronizer +} + +type StixEditMutations { + delete: ID + merge(stixObjectsIds: [String]!): StixObject +} + +type MarkingDefinitionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): MarkingDefinition + contextPatch(input: EditContext): MarkingDefinition + contextClean: MarkingDefinition +} + +type LabelEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): Label + contextPatch(input: EditContext): Label + contextClean: Label +} + +type ExternalReferenceEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): ExternalReference + contextPatch(input: EditContext): ExternalReference + contextClean: ExternalReference + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(fromId: StixRef!, relationship_type: String!): ExternalReference + askEnrichment(connectorId: ID!): Work + importPush(file: Upload!, fileMarkings: [String], version: DateTime, noTriggerImport: Boolean): File +} + +type KillChainPhaseEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): KillChainPhase + contextPatch(input: EditContext): KillChainPhase + contextClean: KillChainPhase + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): KillChainPhase +} + +enum AnalysisContentType { + fields + file +} + +union Analysis = MappingAnalysis + +input MappingAnalysisInput { + mappedEntities: [MappedEntityInput] +} + +type MappingAnalysis { + analysisType: String! + analysisStatus: State + analysisDate: DateTime + mappedEntities: [MappedEntity!] +} + +input MappedEntityInput { + matchedString: String! + matchedEntityId: String! +} + +type MappedEntity { + matchedString: String! + matchedEntity: StixCoreObject! + isEntityInContainer: Boolean! +} + +type StixCoreObjectEditMutations { + delete: ID + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationsAdd(input: StixRefRelationshipsAddInput!, commitMessage: String, references: [String]): StixCoreObject + relationDelete(toId: StixRef!, relationship_type: String!, commitMessage: String, references: [String]): StixCoreObject + restrictionOrganizationAdd(organizationId: ID!): StixCoreObject + restrictionOrganizationDelete(organizationId: ID!): StixCoreObject + askEnrichment(connectorId: ID!): Work + askAnalysis(contentSource: String!, contentType: AnalysisContentType!, connectorId: ID): Work + analysisPush(file: Upload!, contentSource: String!, contentType: AnalysisContentType!, analysisType: String!): File + analysisClear(contentSource: String!, contentType: AnalysisContentType!): Boolean + importPush(file: Upload!, fileMarkings: [String], version: DateTime, noTriggerImport: Boolean, fromTemplate: Boolean): File + exportAsk(input: ExportAskInput!): [File!] + exportPush(file: Upload!): Boolean +} + +input StixDomainObjectFileEditInput { + id: String! + description: String + order: Int + inCarousel: Boolean +} + +type StixDomainObjectEditMutations { + delete: ID + changeType(newType: String!): StixDomainObject + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): StixDomainObject + contextPatch(input: EditContext): StixDomainObject + contextClean: StixDomainObject + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationsAdd(input: StixRefRelationshipsAddInput!): StixDomainObject + relationDelete(toId: StixRef!, relationship_type: String): StixDomainObject + importPush(file: Upload!, fileMarkings: [String], version: DateTime, noTriggerImport: Boolean, fromTemplate: Boolean): File + exportAsk(input: ExportAskInput!): [File!] + exportPush(file: Upload!, file_markings: [String]!): Boolean + stixDomainObjectFileEdit(input: StixDomainObjectFileEditInput): StixDomainObject +} + +type AttackPatternEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): AttackPattern + contextPatch(input: EditContext): AttackPattern + contextClean: AttackPattern + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): AttackPattern +} + +type CampaignEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Campaign + contextPatch(input: EditContext): Campaign + contextClean: Campaign + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Campaign +} + +type ContainerEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Container + contextPatch(input: EditContext): Container + contextClean: Container + editAuthorizedMembers(input: [MemberAccessInput!]): Container + relationAdd(input: StixRefRelationshipAddInput!, commitMessage: String, references: [String]): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!, commitMessage: String, references: [String]): Container + investigationAdd: Workspace + knowledgeAddFromInvestigation(workspaceId: ID!): Container +} + +type NoteEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Note + contextPatch(input: EditContext): Note + contextClean: Note + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Note +} + +type ObservedDataEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): ObservedData + contextPatch(input: EditContext): ObservedData + contextClean: ObservedData + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): ObservedData +} + +type OpinionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Opinion + contextPatch(input: EditContext): Opinion + contextClean: Opinion + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Opinion +} + +type ReportEditMutations { + delete(purgeElements: Boolean): ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Report + contextPatch(input: EditContext): Report + contextClean: Report + relationAdd(input: StixRefRelationshipAddInput!, commitMessage: String, references: [String]): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!, commitMessage: String, references: [String]): Report +} + +type CourseOfActionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): CourseOfAction + contextPatch(input: EditContext): CourseOfAction + contextClean: CourseOfAction + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): CourseOfAction +} + +type IdentityEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Identity + contextPatch(input: EditContext): Identity + contextClean: Identity + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Identity +} + +type IndividualEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Individual + contextPatch(input: EditContext): Individual + contextClean: Individual + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Individual +} + +type SectorEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Sector + contextPatch(input: EditContext): Sector + contextClean: Sector + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Sector +} + +type SystemEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): System + contextPatch(input: EditContext): System + contextClean: System + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): System +} + +type InfrastructureEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Infrastructure + contextPatch(input: EditContext): Infrastructure + contextClean: Infrastructure + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Infrastructure +} + +type IntrusionSetEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): IntrusionSet + contextPatch(input: EditContext): IntrusionSet + contextClean: IntrusionSet + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): IntrusionSet +} + +type LocationEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Location + contextPatch(input: EditContext): Location + contextClean: Location + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Location +} + +type CityEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): City + contextPatch(input: EditContext): City + contextClean: City + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): City +} + +type CountryEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Country + contextPatch(input: EditContext): Country + contextClean: Country + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Country +} + +type RegionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Region + contextPatch(input: EditContext): Region + contextClean: Region + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Region +} + +type PositionEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Position + contextPatch(input: EditContext): Position + contextClean: Position + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Position +} + +type MalwareEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Malware + contextPatch(input: EditContext): Malware + contextClean: Malware + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Malware +} + +type ThreatActorGroupEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): ThreatActorGroup + contextPatch(input: EditContext): ThreatActorGroup + contextClean: ThreatActorGroup + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): ThreatActorGroup +} + +type ToolEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Tool + contextPatch(input: EditContext): Tool + contextClean: Tool + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Tool +} + +type VulnerabilityEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Vulnerability + contextPatch(input: EditContext): Vulnerability + contextClean: Vulnerability + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Vulnerability +} + +type IncidentEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): Incident + contextPatch(input: EditContext): Incident + contextClean: Incident + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationDelete(toId: StixRef!, relationship_type: String!): Incident +} + +type StixCyberObservableEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): StixCyberObservable + contextPatch(input: EditContext): StixCyberObservable + contextClean: StixCyberObservable + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationsAdd(input: StixRefRelationshipsAddInput!): StixCyberObservable + relationDelete(toId: StixRef!, relationship_type: String!): StixCyberObservable + promoteToIndicator: Indicator + importPush(file: Upload!, fileMarkings: [String], version: DateTime, noTriggerImport: Boolean): File + exportAsk(format: String!, exportType: String!, maxMarkingDefinition: String): [File!] + exportPush(file: Upload!): Boolean + promote: StixCyberObservable @deprecated(reason: "[>=6.2 & <6.5]. Use `promoteToIndicator`.") +} + +type StixRelationshipEditMutations { + delete: ID +} + +type StixCoreRelationshipEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): StixCoreRelationship + contextPatch(input: EditContext): StixCoreRelationship + contextClean: StixCoreRelationship + relationAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + relationsAdd(input: StixRefRelationshipsAddInput!, commitMessage: String, references: [String]): StixCoreRelationship + relationDelete(toId: StixRef!, relationship_type: String!, commitMessage: String, references: [String]): StixCoreRelationship + restrictionOrganizationAdd(organizationId: ID!): StixCoreRelationship + restrictionOrganizationDelete(organizationId: ID!): StixCoreRelationship +} + +type StixSightingRelationshipEditMutations { + delete: ID + fieldPatch(input: [EditInput]!, commitMessage: String, references: [String]): StixSightingRelationship + contextPatch(input: EditContext): StixSightingRelationship + contextClean: StixSightingRelationship + relationAdd(input: StixRefRelationshipAddInput!): StixSightingRelationship + relationsAdd(input: StixRefRelationshipsAddInput!, commitMessage: String, references: [String]): StixSightingRelationship + relationDelete(toId: StixRef!, relationship_type: String!, commitMessage: String, references: [String]): StixSightingRelationship + restrictionOrganizationAdd(organizationId: ID!): StixSightingRelationship + restrictionOrganizationDelete(organizationId: ID!): StixSightingRelationship +} + +type StixRefRelationshipEditMutations { + delete: ID + fieldPatch(input: [EditInput]!): StixRefRelationship + contextPatch(input: EditContext): StixRefRelationship +} + +type Mutation { + deleteImport(fileName: String): ID + uploadImport(file: Upload!, fileMarkings: [String]): File + uploadPending(file: Upload!, entityId: String, labels: [String], errorOnExisting: Boolean, refreshEntity: Boolean): File + askJobImport(fileName: ID!, connectorId: String, configuration: String, bypassEntityId: String, bypassValidation: Boolean): File + resetFileIndexing: Boolean + synchronizerAdd(input: SynchronizerAddInput!): Synchronizer + synchronizerEdit(id: ID!): SynchronizerEditMutations + synchronizerStart(id: ID!): Synchronizer + synchronizerStop(id: ID!): Synchronizer + synchronizerTest(input: SynchronizerAddInput): String + workAdd(connectorId: String!, friendlyName: String): Work! + workEdit(id: ID!): WorkEditMutations + workDelete(connectorId: String!): Boolean + deleteBackgroundTask(id: ID!): ID! + listTaskAdd(input: ListTaskAddInput!): BackgroundTask! + queryTaskAdd(input: QueryTaskAddInput!): BackgroundTask! + retentionRuleAdd(input: RetentionRuleAddInput!): RetentionRule! + retentionRuleCheck(input: RetentionRuleAddInput): Int! + retentionRuleEdit(id: ID!): RetentionRuleEditMutations + ruleSetActivation(id: ID!, enable: Boolean!): Rule! + ruleManagerClean(eventId: ID): RuleManager! + frontendErrorLog(message: String!, codeStack: String, componentStack: String): Boolean + token(input: UserLoginInput): String + otpActivation(input: UserOTPActivationInput): MeUser + otpDeactivation: MeUser + otpUserDeactivation(id: ID!): MeUser + otpLogin(input: UserOTPLoginInput): Boolean + settingsEdit(id: ID!): SettingsEditMutations + subTypeEdit(id: ID!): SubTypeEditMutations + statusTemplateAdd(input: StatusTemplateAddInput!): StatusTemplate! + statusTemplateDelete(id: ID!): ID! + statusTemplateFieldPatch(id: ID!, input: [EditInput!]!): StatusTemplate! + statusTemplateContextPatch(id: ID!, input: EditContext!): StatusTemplate! + statusTemplateContextClean(id: ID!): StatusTemplate! + groupAdd(input: GroupAddInput!): Group + groupEdit(id: ID!): GroupEditMutations + userAdd(input: UserAddInput!): User + userEdit(id: ID!): UserEditMutations + meTokenRenew: MeUser + meEdit(input: [EditInput]!, password: String): MeUser + bookmarkAdd(id: ID!, type: String!): StixDomainObject + bookmarkDelete(id: ID!): ID + logout: ID + roleAdd(input: RoleAddInput!): Role + sessionKill(id: ID!): ID + userSessionsKill(id: ID!): [ID] + roleEdit(id: ID!): RoleEditMutations + pingConnector(id: ID!, state: String, connectorInfo: ConnectorInfoInput): Connector + registerConnector(input: RegisterConnectorInput): Connector + resetStateConnector(id: ID!): Connector + deleteConnector(id: ID!): ID! + updateConnectorTrigger(id: ID!, input: [EditInput]!): Connector + feedAdd(input: FeedAddInput!): Feed + feedDelete(id: ID!): ID! + feedEdit(id: ID!, input: FeedAddInput!): Feed! + taxiiCollectionAdd(input: TaxiiCollectionAddInput!): TaxiiCollection + taxiiCollectionEdit(id: ID!): TaxiiCollectionEditMutations + streamCollectionAdd(input: StreamCollectionAddInput!): StreamCollection + streamCollectionEdit(id: ID!): StreamCollectionEditMutations + stixEdit(id: ID!): StixEditMutations + markingDefinitionAdd(input: MarkingDefinitionAddInput!): MarkingDefinition + markingDefinitionEdit(id: ID!): MarkingDefinitionEditMutations + labelAdd(input: LabelAddInput!): Label + labelEdit(id: ID!): LabelEditMutations + externalReferenceAdd(input: ExternalReferenceAddInput!): ExternalReference + externalReferenceEdit(id: ID!): ExternalReferenceEditMutations + killChainPhaseAdd(input: KillChainPhaseAddInput!): KillChainPhase + killChainPhaseEdit(id: ID!): KillChainPhaseEditMutations + stixCoreObjectEdit(id: ID!): StixCoreObjectEditMutations + stixCoreObjectsExportAsk(input: StixCoreObjectsExportAskInput!): [File!] + stixCoreObjectsExportPush(entity_id: String, entity_type: String!, file: Upload!, file_markings: [String]!, listFilters: String): Boolean + stixBundlePush(connectorId: String!, bundle: String!): Boolean + stixDomainObjectAdd(input: StixDomainObjectAddInput!): StixDomainObject + stixDomainObjectEdit(id: ID!): StixDomainObjectEditMutations + stixDomainObjectsExportAsk(format: String!, exportType: String!, contentMaxMarkings: [String], fileMarkings: [String], search: String, exportContext: ExportContext, relationship_type: [String], orderBy: StixDomainObjectsOrdering, orderMode: OrderingMode, filters: FilterGroup, selectedIds: [String]): [File!] + stixDomainObjectsDelete(id: [ID]!): [ID]! + stixDomainObjectsExportPush(entity_id: String, entity_type: String!, file: Upload!, file_markings: [String]!, listFilters: String): Boolean + attackPatternAdd(input: AttackPatternAddInput!): AttackPattern + attackPatternEdit(id: ID!): AttackPatternEditMutations + campaignAdd(input: CampaignAddInput!): Campaign + campaignEdit(id: ID!): CampaignEditMutations + containerEdit(id: ID!): ContainerEditMutations + noteAdd(input: NoteAddInput!): Note + userNoteAdd(input: NoteUserAddInput!): Note + noteEdit(id: ID!): NoteEditMutations + observedDataAdd(input: ObservedDataAddInput!): ObservedData + observedDataEdit(id: ID!): ObservedDataEditMutations + opinionAdd(input: OpinionAddInput!): Opinion + userOpinionAdd(input: OpinionUserAddInput!): Opinion + opinionEdit(id: ID!): OpinionEditMutations + reportAdd(input: ReportAddInput!): Report + reportEdit(id: ID!): ReportEditMutations + courseOfActionAdd(input: CourseOfActionAddInput!): CourseOfAction + courseOfActionEdit(id: ID!): CourseOfActionEditMutations + identityAdd(input: IdentityAddInput!): Identity + identityEdit(id: ID!): IdentityEditMutations + individualAdd(input: IndividualAddInput!): Individual + individualEdit(id: ID!): IndividualEditMutations + sectorAdd(input: SectorAddInput!): Sector + sectorEdit(id: ID!): SectorEditMutations + systemAdd(input: SystemAddInput!): System + systemEdit(id: ID!): SystemEditMutations + infrastructureAdd(input: InfrastructureAddInput!): Infrastructure + infrastructureEdit(id: ID!): InfrastructureEditMutations + intrusionSetAdd(input: IntrusionSetAddInput!): IntrusionSet + intrusionSetEdit(id: ID!): IntrusionSetEditMutations + locationAdd(input: LocationAddInput!): Location + locationEdit(id: ID!): LocationEditMutations + cityAdd(input: CityAddInput!): City + cityEdit(id: ID!): CityEditMutations + countryAdd(input: CountryAddInput!): Country + countryEdit(id: ID!): CountryEditMutations + regionAdd(input: RegionAddInput!): Region + regionEdit(id: ID!): RegionEditMutations + positionAdd(input: PositionAddInput!): Position + positionEdit(id: ID!): PositionEditMutations + malwareAdd(input: MalwareAddInput!): Malware + malwareEdit(id: ID!): MalwareEditMutations + threatActorGroupAdd(input: ThreatActorGroupAddInput!): ThreatActorGroup + threatActorGroupEdit(id: ID!): ThreatActorGroupEditMutations + toolAdd(input: ToolAddInput!): Tool + toolEdit(id: ID!): ToolEditMutations + vulnerabilityAdd(input: VulnerabilityAddInput!): Vulnerability + vulnerabilityEdit(id: ID!): VulnerabilityEditMutations + incidentAdd(input: IncidentAddInput!): Incident + incidentEdit(id: ID!): IncidentEditMutations + stixCyberObservableAdd(type: String!, stix_id: StixId, x_opencti_score: Int, x_opencti_description: String, createIndicator: Boolean, createdBy: String, objectMarking: [String], objectLabel: [String], objectOrganization: [String], externalReferences: [String], clientMutationId: String, update: Boolean, AutonomousSystem: AutonomousSystemAddInput, Directory: DirectoryAddInput, DomainName: DomainNameAddInput, EmailAddr: EmailAddrAddInput, EmailMessage: EmailMessageAddInput, EmailMimePartType: EmailMimePartTypeAddInput, Artifact: ArtifactAddInput, StixFile: StixFileAddInput, X509Certificate: X509CertificateAddInput, IPv4Addr: IPv4AddrAddInput, IPv6Addr: IPv6AddrAddInput, MacAddr: MacAddrAddInput, Mutex: MutexAddInput, NetworkTraffic: NetworkTrafficAddInput, Process: ProcessAddInput, Software: SoftwareAddInput, Url: UrlAddInput, UserAccount: UserAccountAddInput, WindowsRegistryKey: WindowsRegistryKeyAddInput, WindowsRegistryValueType: WindowsRegistryValueTypeAddInput, CryptographicKey: CryptographicKeyAddInput, CryptocurrencyWallet: CryptocurrencyWalletAddInput, Hostname: HostnameAddInput, Text: TextAddInput, UserAgent: UserAgentAddInput, BankAccount: BankAccountAddInput, Credential: CredentialAddInput, TrackingNumber: TrackingNumberAddInput, PhoneNumber: PhoneNumberAddInput, PaymentCard: PaymentCardAddInput, MediaContent: MediaContentAddInput, Persona: PersonaAddInput): StixCyberObservable + stixCyberObservableEdit(id: ID!): StixCyberObservableEditMutations + stixCyberObservablesExportAsk(input: StixCyberObservablesExportAskInput!): [File!] + stixCyberObservablesExportPush(entity_id: String, entity_type: String!, file: Upload!, file_markings: [String]!, listFilters: String): Boolean + artifactImport(file: Upload!, x_opencti_description: String, createdBy: String, objectMarking: [String], objectLabel: [String]): Artifact + stixRelationshipEdit(id: ID!): StixRelationshipEditMutations + stixCoreRelationshipAdd(input: StixCoreRelationshipAddInput, reversedReturn: Boolean): StixCoreRelationship + stixCoreRelationshipEdit(id: ID!): StixCoreRelationshipEditMutations + stixCoreRelationshipsExportAsk(input: StixCoreRelationshipsExportAskInput!): [File!] + stixCoreRelationshipDelete(fromId: StixRef!, toId: StixRef!, relationship_type: String!): Boolean! + stixCoreRelationshipsExportPush(entity_id: String, entity_type: String!, file: Upload!, file_markings: [String]!, listFilters: String): Boolean + stixRefRelationshipAdd(input: StixRefRelationshipAddInput!): StixRefRelationship + stixRefRelationshipEdit(id: ID!): StixRefRelationshipEditMutations + stixSightingRelationshipAdd(input: StixSightingRelationshipAddInput!): StixSightingRelationship + stixSightingRelationshipEdit(id: ID!): StixSightingRelationshipEditMutations + channelAdd(input: ChannelAddInput!): Channel + channelDelete(id: ID!): ID + channelFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): Channel + channelContextPatch(id: ID!, input: EditContext!): Channel + channelContextClean(id: ID!): Channel + channelRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + channelRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Channel + languageAdd(input: LanguageAddInput!): Language + languageDelete(id: ID!): ID + languageFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): Language + languageContextPatch(id: ID!, input: EditContext!): Language + languageContextClean(id: ID!): Language + languageRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + languageRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Language + eventAdd(input: EventAddInput!): Event + eventDelete(id: ID!): ID + eventFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): Event + eventContextPatch(id: ID!, input: EditContext!): Event + eventContextClean(id: ID!): Event + eventRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + eventRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Event + groupingAdd(input: GroupingAddInput!): Grouping + groupingDelete(id: ID!): ID + groupingFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): Grouping + groupingContextPatch(id: ID!, input: EditContext): Grouping + groupingContextClean(id: ID!): Grouping + groupingRelationAdd(id: ID!, input: StixRefRelationshipAddInput): StixRefRelationship + groupingRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Grouping + narrativeAdd(input: NarrativeAddInput!): Narrative + narrativeDelete(id: ID!): ID + narrativeFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): Narrative + narrativeContextPatch(id: ID!, input: EditContext!): Narrative + narrativeContextClean(id: ID!): Narrative + narrativeRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + narrativeRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Narrative + triggerKnowledgeDelete(id: ID!): ID + triggerKnowledgeFieldPatch(id: ID!, input: [EditInput!]!): Trigger + triggerKnowledgeLiveAdd(input: TriggerLiveAddInput!): Trigger + triggerKnowledgeDigestAdd(input: TriggerDigestAddInput!): Trigger + triggerActivityDelete(id: ID!): ID + triggerActivityFieldPatch(id: ID!, input: [EditInput!]!): Trigger + triggerActivityLiveAdd(input: TriggerActivityLiveAddInput!): Trigger + triggerActivityDigestAdd(input: TriggerActivityDigestAddInput!): Trigger + notificationDelete(id: ID!): ID + notificationMarkRead(id: ID!, read: Boolean!): Notification + dataComponentAdd(input: DataComponentAddInput!): DataComponent + dataComponentDelete(id: ID!): ID + dataComponentFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): DataComponent + dataComponentContextPatch(id: ID!, input: EditContext!): DataComponent + dataComponentContextClean(id: ID!): DataComponent + dataComponentRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + dataComponentRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): DataComponent + dataSourceAdd(input: DataSourceAddInput!): DataSource + dataSourceDelete(id: ID!): ID + dataSourceFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): DataSource + dataSourceContextPatch(id: ID!, input: EditContext!): DataSource + dataSourceContextClean(id: ID!): DataSource + dataSourceRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + dataSourceRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): DataSource + dataSourceDataComponentAdd(id: ID!, dataComponentId: ID!): DataSource + dataSourceDataComponentDelete(id: ID!, dataComponentId: ID!): DataSource + vocabularyAdd(input: VocabularyAddInput!): Vocabulary + vocabularyFieldPatch(id: ID!, input: [EditInput!]!): Vocabulary + vocabularyDelete(id: ID!): ID + administrativeAreaAdd(input: AdministrativeAreaAddInput!): AdministrativeArea + administrativeAreaDelete(id: ID!): ID + administrativeAreaFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): AdministrativeArea + administrativeAreaContextPatch(id: ID!, input: EditContext!): AdministrativeArea + administrativeAreaContextClean(id: ID!): AdministrativeArea + administrativeAreaRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + administrativeAreaRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): AdministrativeArea + taskAdd(input: TaskAddInput!): Task + taskDelete(id: ID!): ID + taskFieldPatch(id: ID!, input: [EditInput!]!, commitMessage: String, references: [String]): Task + taskRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + taskRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Task + taskTemplateAdd(input: TaskTemplateAddInput!): TaskTemplate + taskTemplateDelete(id: ID!): ID + taskTemplateFieldPatch(id: ID!, input: [EditInput!]!, commitMessage: String, references: [String]): TaskTemplate + caseDelete(id: ID!): ID + caseSetTemplate(id: ID!, caseTemplatesId: [ID!]!): Case + caseTemplateAdd(input: CaseTemplateAddInput!): CaseTemplate + caseTemplateDelete(id: ID!): ID + caseTemplateFieldPatch(id: ID!, input: [EditInput!]!, commitMessage: String, references: [String]): CaseTemplate + caseTemplateRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): CaseTemplate + caseTemplateRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): CaseTemplate + caseIncidentAdd(input: CaseIncidentAddInput!): CaseIncident + caseIncidentDelete(id: ID!): ID + caseRfiAdd(input: CaseRfiAddInput!): CaseRfi + caseRfiDelete(id: ID!): ID + caseRftAdd(input: CaseRftAddInput!): CaseRft + caseRftDelete(id: ID!): ID + feedbackAdd(input: FeedbackAddInput!): Feedback + feedbackDelete(id: ID!): ID + feedbackEditAuthorizedMembers(id: ID!, input: [MemberAccessInput!]): Feedback + entitySettingsFieldPatch(ids: [ID!]!, input: [EditInput!]!, commitMessage: String, references: [String]): [EntitySetting] + workspaceAdd(input: WorkspaceAddInput!): Workspace + workspaceDuplicate(input: WorkspaceDuplicateInput!): Workspace + workspaceDelete(id: ID!): ID + workspaceFieldPatch(id: ID!, input: [EditInput!]!): Workspace + workspaceEditAuthorizedMembers(id: ID!, input: [MemberAccessInput!]!): Workspace + workspaceContextPatch(id: ID!, input: EditContext!): Workspace + workspaceContextClean(id: ID!): Workspace + workspaceConfigurationImport(file: Upload!): String! + workspaceWidgetConfigurationImport(id: ID!, input: ImportConfigurationInput!): Workspace + malwareAnalysisAdd(input: MalwareAnalysisAddInput!): MalwareAnalysis + malwareAnalysisDelete(id: ID!): ID + malwareAnalysisFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): MalwareAnalysis + malwareAnalysisContextPatch(id: ID!, input: EditContext!): MalwareAnalysis + malwareAnalysisContextClean(id: ID!): MalwareAnalysis + malwareAnalysisRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + malwareAnalysisRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): MalwareAnalysis + managerConfigurationFieldPatch(id: ID!, input: [EditInput!]!, commitMessage: String, references: [String]): ManagerConfiguration + notifierDelete(id: ID!): ID + notifierFieldPatch(id: ID!, input: [EditInput!]!): Notifier + notifierAdd(input: NotifierAddInput!): Notifier + threatActorIndividualAdd(input: ThreatActorIndividualAddInput!): ThreatActorIndividual + threatActorIndividualDelete(id: ID!): ID + threatActorIndividualFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): ThreatActorIndividual + threatActorIndividualContextPatch(id: ID!, input: EditContext): ThreatActorIndividual + threatActorIndividualContextClean(id: ID!): ThreatActorIndividual + threatActorIndividualRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + threatActorIndividualRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): ThreatActorIndividual + playbookAdd(input: PlaybookAddInput!): Playbook + playbookAddNode(id: ID!, input: PlaybookAddNodeInput!): String! + playbookReplaceNode(id: ID!, nodeId: ID!, input: PlaybookAddNodeInput!): String! + playbookInsertNode(id: ID!, parentNodeId: ID!, parentPortId: ID!, childNodeId: ID!, input: PlaybookAddNodeInput!): PlaybookInsertResult! + playbookAddLink(id: ID!, input: PlaybookAddLinkInput!): String! + playbookDelete(id: ID!): ID + playbookDeleteNode(id: ID!, nodeId: ID!): Playbook + playbookDeleteLink(id: ID!, linkId: ID!): Playbook + playbookUpdatePositions(id: ID!, positions: String!): ID + playbookFieldPatch(id: ID!, input: [EditInput!]!, commitMessage: String, references: [String]): Playbook + playbookStepExecution(execution_id: ID!, event_id: ID!, execution_start: DateTime!, data_instance_id: ID!, playbook_id: ID!, previous_step_id: ID!, step_id: ID!, previous_bundle: String!, bundle: String!): Boolean + playbookExecute(id: ID!, entityId: String!): Boolean + ingestionRssAdd(input: IngestionRssAddInput!): IngestionRss + ingestionRssDelete(id: ID!): ID + ingestionRssFieldPatch(id: ID!, input: [EditInput!]!): IngestionRss + ingestionTaxiiAdd(input: IngestionTaxiiAddInput!): IngestionTaxii + ingestionTaxiiDelete(id: ID!): ID + ingestionTaxiiFieldPatch(id: ID!, input: [EditInput!]!): IngestionTaxii + ingestionCsvTester(input: IngestionCsvAddInput!): CsvMapperTestResult + ingestionCsvAdd(input: IngestionCsvAddInput!): IngestionCsv + ingestionCsvDelete(id: ID!): ID + ingestionCsvFieldPatch(id: ID!, input: [EditInput!]!): IngestionCsv + indicatorAdd(input: IndicatorAddInput!): Indicator + indicatorDelete(id: ID!): ID + indicatorFieldPatch(id: ID!, input: [EditInput!]!, commitMessage: String, references: [String]): Indicator + indicatorContextPatch(id: ID!, input: EditContext): Indicator + indicatorContextClean(id: ID!): Indicator + indicatorRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + indicatorRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Indicator + decayRuleAdd(input: DecayRuleAddInput!): DecayRule + decayRuleDelete(id: ID!): ID + decayRuleFieldPatch(id: ID!, input: [EditInput!]!): DecayRule + organizationAdd(input: OrganizationAddInput!): Organization + organizationDelete(id: ID!): ID + organizationFieldPatch(id: ID!, input: [EditInput]!, commitMessage: String, references: [String]): Organization + organizationContextPatch(id: ID!, input: EditContext!): Organization + organizationContextClean(id: ID!): Organization + organizationRelationAdd(id: ID!, input: StixRefRelationshipAddInput!): StixRefRelationship + organizationRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): Organization + organizationEditAuthorizedAuthorities(id: ID!, input: [String!]!): Organization + organizationAdminAdd(id: ID!, memberId: String!): Organization + organizationAdminRemove(id: ID!, memberId: String!): Organization + csvMapperAdd(input: CsvMapperAddInput!): CsvMapper + csvMapperDelete(id: ID!): ID + csvMapperFieldPatch(id: ID!, input: [EditInput!]!): CsvMapper + publicDashboardAdd(input: PublicDashboardAddInput!): PublicDashboard + publicDashboardDelete(id: ID!): ID + publicDashboardFieldPatch(id: ID!, input: [EditInput!]!): PublicDashboard + aiContainerGenerateReport(id: ID!, containerId: String!, paragraphs: Int, tone: Tone, format: Format, language: String): String + aiThreatGenerateReport(id: ID!, threatId: String!, paragraphs: Int, tone: Tone, format: Format): String + aiVictimGenerateReport(id: ID!, victimId: String!, paragraphs: Int, tone: Tone, format: Format): String + aiSummarizeFiles(id: ID!, elementId: String!, paragraphs: Int, tone: Tone, format: Format, language: String, fileIds: [String]): String + aiConvertFilesToStix(id: ID!, elementId: String!, fileIds: [String]): String + aiConvertIndicator(id: ID!, indicatorId: String!, format: IndicatorFormat!): String + aiImproveWriting(id: ID!, content: String!, format: Format): String + aiFixSpelling(id: ID!, content: String!, format: Format): String + aiMakeShorter(id: ID!, content: String!, format: Format): String + aiMakeLonger(id: ID!, content: String!, format: Format): String + aiChangeTone(id: ID!, content: String!, format: Format, tone: Tone): String + aiSummarize(id: ID!, content: String!, format: Format): String + aiExplain(id: ID!, content: String!): String + obasContainerGenerateScenario(id: ID!, interval: Int, selection: Selection, simulationType: SimulationType, useAI: Boolean, filters: FilterGroup): String + obasThreatGenerateScenario(id: ID!, interval: Int, selection: Selection, simulationType: SimulationType, useAI: Boolean, filters: FilterGroup): String + obasVictimGenerateScenario(id: ID!, interval: Int, selection: Selection, simulationType: SimulationType, useAI: Boolean, filters: FilterGroup): String + deleteOperationRestore(id: ID!): ID + deleteOperationConfirm(id: ID!): ID + supportPackageAdd(input: SupportPackageAddInput!): SupportPackage + supportPackageForceZip(input: SupportPackageForceZipInput!): SupportPackage + supportPackageDelete(id: ID!): ID + exclusionListContentAdd(input: ExclusionListContentAddInput!): ExclusionList + exclusionListFileAdd(input: ExclusionListFileAddInput!): ExclusionList + exclusionListDelete(id: ID!): ID + draftWorkspaceAdd(input: DraftWorkspaceAddInput!): DraftWorkspace + draftWorkspaceValidate(id: ID!): Work + draftWorkspaceDelete(id: ID!): ID +} + +type Channel implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + channel_types: [String] + aliases: [String] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum ChannelsOrdering { + name + channel_types + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + confidence + _score +} + +type ChannelConnection { + pageInfo: PageInfo! + edges: [ChannelEdge] +} + +type ChannelEdge { + cursor: String! + node: Channel! +} + +input ChannelAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + channel_types: [String] + aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +type Language implements BasicObject & StixCoreObject & StixDomainObject & StixObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + aliases: [String] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum LanguagesOrdering { + name + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + _score +} + +type LanguageConnection { + pageInfo: PageInfo! + edges: [LanguageEdge] +} + +type LanguageEdge { + cursor: String! + node: Language! +} + +input LanguageAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean +} + +type Event implements BasicObject & StixCoreObject & StixDomainObject & StixObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + event_types: [String] + start_time: DateTime + stop_time: DateTime + aliases: [String] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum EventsOrdering { + name + event_types + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + start_time + stop_time + _score +} + +type EventConnection { + pageInfo: PageInfo! + edges: [EventEdge] +} + +type EventEdge { + cursor: String! + node: Event! +} + +input EventAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + event_types: [String!] + start_time: DateTime + stop_time: DateTime + aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + x_opencti_workflow_id: String + update: Boolean + file: Upload +} + +type Grouping implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + name: String! + description: String + content: String + content_mapping: String + context: String! + x_opencti_aliases: [String] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum GroupingsOrdering { + name + created + modified + context + created_at + updated_at + createdBy + objectMarking + x_opencti_workflow_id + creator + _score +} + +type GroupingConnection { + pageInfo: PageInfo! + edges: [GroupingEdge] +} + +type GroupingEdge { + cursor: String! + node: Grouping! +} + +input GroupingAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + content: String + content_mapping: String + + "*Constraints:*\n* Minimal length: `2`\n" + context: String! + x_opencti_aliases: [String] + revoked: Boolean + lang: String + confidence: Int + createdBy: String + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + objects: [String] + created: DateTime + modified: DateTime + clientMutationId: String + x_opencti_workflow_id: String + update: Boolean + file: Upload +} + +type Narrative implements BasicObject & StixCoreObject & StixDomainObject & StixObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + narrative_types: [String] + aliases: [String] + parentNarratives: NarrativeConnection + subNarratives: NarrativeConnection + isSubNarrative: Boolean + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum NarrativesOrdering { + name + narrative_types + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + _score +} + +type NarrativeConnection { + pageInfo: PageInfo! + edges: [NarrativeEdge!]! +} + +type NarrativeEdge { + cursor: String! + node: Narrative! +} + +input NarrativeAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + narrative_types: [String!] + aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean + file: Upload + x_opencti_workflow_id: String +} + +type ResolvedInstanceFilter { + id: String! + valid: Boolean! + value: String +} + +enum DigestPeriod { + hour + day + week + month +} + +enum TriggersOrdering { + name + created + event_types + trigger_type + notifiers + _score +} + +enum TriggerType { + live + digest +} + +enum TriggerEventType { + create + update + delete +} + +input TriggerLiveAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + event_types: [TriggerEventType!]! + notifiers: [StixRef!] + instance_trigger: Boolean! + filters: String + recipients: [String!] +} + +input TriggerDigestAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + trigger_ids: [String!]! + period: DigestPeriod! + trigger_time: String + notifiers: [StixRef!]! + recipients: [String!] +} + +type Trigger implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + created: DateTime + modified: DateTime + created_at: DateTime + updated_at: DateTime + name: String! + description: String + trigger_type: TriggerType! + event_types: [String!] + filters: String + notifiers: [Notifier!] + trigger_ids: [String] + triggers: [Trigger] + recipients: [Member!] + period: DigestPeriod + trigger_time: String + isDirectAdministrator: Boolean + currentUserAccessRight: String + instance_trigger: Boolean +} + +type TriggerConnection { + pageInfo: PageInfo! + edges: [TriggerEdge!]! +} + +type TriggerEdge { + cursor: String! + node: Trigger! +} + +enum TriggerActivityEventType { + authentication + read + mutation + file + command +} + +input TriggerActivityLiveAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + notifiers: [StixRef!] + filters: String + recipients: [String!]! +} + +input TriggerActivityDigestAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + trigger_ids: [String!]! + period: DigestPeriod! + trigger_time: String + notifiers: [StixRef!]! + recipients: [String!]! +} + +enum NotificationsOrdering { + name + created + _score +} + +type NotificationCount { + user_id: String + count: Int +} + +type NotificationEvent { + message: String! + instance_id: String + operation: String! +} + +type NotificationContent { + title: String! + events: [NotificationEvent!]! +} + +type Notification implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + created: DateTime + name: String! + notification_type: String! + parent_types: [String]! + notification_content: [NotificationContent!]! + is_read: Boolean! + user_id: String + created_at: DateTime + updated_at: DateTime +} + +type NotificationConnection { + pageInfo: PageInfo! + edges: [NotificationEdge] +} + +type NotificationEdge { + cursor: String! + node: Notification! +} + +type DataComponent implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + aliases: [String] + dataSource: DataSource + attackPatterns: AttackPatternConnection +} + +enum DataComponentsOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + confidence + _score +} + +type DataComponentConnection { + pageInfo: PageInfo! + edges: [DataComponentEdge] +} + +type DataComponentEdge { + cursor: String! + node: DataComponent! +} + +input DataComponentAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + dataSource: String + file: Upload + x_opencti_workflow_id: String +} + +type DataSource implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + aliases: [String] + x_mitre_platforms: [String!] + collection_layers: [String!] + dataComponents: DataComponentConnection +} + +enum DataSourcesOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + confidence + _score +} + +type DataSourceConnection { + pageInfo: PageInfo! + edges: [DataSourceEdge] +} + +type DataSourceEdge { + cursor: String! + node: DataSource! +} + +input DataSourceAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + objectOrganization: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + x_mitre_platforms: [String!] + collection_layers: [String!] + dataComponents: [String] + file: Upload + x_opencti_workflow_id: String +} + +enum VocabularyCategory { + account_type_ov + attack_motivation_ov + attack_resource_level_ov + case_severity_ov + case_priority_ov + channel_types_ov + collection_layers_ov + event_type_ov + grouping_context_ov + implementation_language_ov + incident_response_types_ov + incident_type_ov + incident_severity_ov + indicator_type_ov + infrastructure_type_ov + integrity_level_ov + malware_capabilities_ov + malware_result_ov + malware_type_ov + platforms_ov + opinion_ov + organization_type_ov + pattern_type_ov + permissions_ov + processor_architecture_ov + reliability_ov + report_types_ov + request_for_information_types_ov + request_for_takedown_types_ov + service_status_ov + service_type_ov + start_type_ov + threat_actor_group_type_ov + threat_actor_group_role_ov + threat_actor_group_sophistication_ov + threat_actor_individual_type_ov + threat_actor_individual_role_ov + threat_actor_individual_sophistication_ov + tool_types_ov + note_types_ov + gender_ov + marital_status_ov + hair_color_ov + eye_color_ov + persona_type_ov +} + +type VocabularyFieldDefinition { + key: String! + required: Boolean! + multiple: Boolean! +} + +type VocabularyDefinition { + key: VocabularyCategory! + description: String + entity_types: [String!]! + fields: [VocabularyFieldDefinition!]! +} + +type Vocabulary implements BasicObject & StixObject & StixMetaObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + creators: [Creator!] + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + created: DateTime + modified: DateTime + category: VocabularyDefinition! + name: String! + description: String + usages: Int! + aliases: [String!] + builtIn: Boolean + order: Int +} + +enum VocabularyOrdering { + name + category + description + order + _score +} + +type VocabularyConnection { + pageInfo: PageInfo! + edges: [VocabularyEdge!]! +} + +type VocabularyEdge { + cursor: String! + node: Vocabulary! +} + +input VocabularyAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `1`\n* Must match format: `not-blank`\n" + name: String! + description: String + category: VocabularyCategory! + order: Int + created: DateTime + modified: DateTime + aliases: [String!] + update: Boolean +} + +type AdministrativeArea implements BasicObject & StixCoreObject & StixDomainObject & StixObject & Location { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + latitude: Float + longitude: Float + precision: Float + x_opencti_aliases: [String] + cases(first: Int): CaseConnection + country: Country + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum AdministrativeAreasOrdering { + name + created + modified + created_at + updated_at + objectMarking + objectLabel + x_opencti_workflow_id + _score +} + +type AdministrativeAreaConnection { + pageInfo: PageInfo! + edges: [AdministrativeAreaEdge!] +} + +type AdministrativeAreaEdge { + cursor: String! + node: AdministrativeArea! +} + +input AdministrativeAreaAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + latitude: Float + longitude: Float + x_opencti_aliases: [String] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + x_opencti_workflow_id: String + update: Boolean + file: Upload +} + +type Task implements Container & StixDomainObject & StixCoreObject & StixObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + due_date: DateTime +} + +enum TasksOrdering { + name + description + created + modified + context + created_at + updated_at + creator + createdBy + x_opencti_workflow_id + confidence + due_date + objectAssignee + _score +} + +type TaskEdge { + cursor: String! + node: Task! +} + +type TaskConnection { + pageInfo: PageInfo! + edges: [TaskEdge!]! +} + +input TaskAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + created: DateTime + due_date: DateTime + objectAssignee: [String] + objectParticipant: [String] + objectLabel: [String] + objectMarking: [String] + objectOrganization: [String] + createdBy: String + objects: [String] + x_opencti_workflow_id: String + update: Boolean +} + +type TaskTemplate implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + created: DateTime + modified: DateTime + name: String! + description: String +} + +enum TaskTemplatesOrdering { + name + description + created + modified + created_at + updated_at + creator + _score +} + +type TaskTemplateConnection { + pageInfo: PageInfo! + edges: [TaskTemplateEdge!]! +} + +type TaskTemplateEdge { + cursor: String! + node: TaskTemplate! +} + +input TaskTemplateAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String +} + +interface Case implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + content: String + content_mapping: String + tasks: TaskConnection! +} + +enum CasesOrdering { + name + created + modified + context + created_at + updated_at + creator + createdBy + x_opencti_workflow_id + confidence + objectMarking + _score +} + +type CaseConnection { + pageInfo: PageInfo! + edges: [CaseEdge] +} + +type CaseEdge { + cursor: String! + node: Case! +} + +type CaseTemplate implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + created: DateTime + modified: DateTime + name: String! + description: String + tasks: TaskTemplateConnection! +} + +enum CaseTemplatesOrdering { + name + description + created + _score +} + +type CaseTemplateConnection { + pageInfo: PageInfo! + edges: [CaseTemplateEdge!]! +} + +type CaseTemplateEdge { + cursor: String! + node: CaseTemplate! +} + +input CaseTemplateAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + created: DateTime + tasks: [StixRef!]! +} + +type CaseIncident implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container & Case { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + content: String + content_mapping: String + tasks: TaskConnection! + rating: Int + response_types: [String!] + severity: String + priority: String +} + +enum CaseIncidentsOrdering { + name + created + modified + context + severity + priority + created_at + updated_at + creator + createdBy + objectAssignee + x_opencti_workflow_id + confidence + objectMarking + _score +} + +type CaseIncidentConnection { + pageInfo: PageInfo! + edges: [CaseIncidentEdge] +} + +type CaseIncidentEdge { + cursor: String! + node: CaseIncident! +} + +input CaseIncidentAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + severity: String + priority: String + description: String + content: String + content_mapping: String + confidence: Int + revoked: Boolean + lang: String + objects: [String] + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectParticipant: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + response_types: [String!] + caseTemplates: [String!] + x_opencti_workflow_id: String + file: Upload + clientMutationId: String + update: Boolean +} + +type CaseRfi implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container & Case { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + content: String + content_mapping: String + tasks: TaskConnection! + information_types: [String!] + severity: String + priority: String +} + +enum CaseRfisOrdering { + name + created + modified + created_at + updated_at + creator + createdBy + objectAssignee + x_opencti_workflow_id + confidence + objectMarking + severity + priority + _score +} + +type CaseRfiConnection { + pageInfo: PageInfo! + edges: [CaseRfiEdge] +} + +type CaseRfiEdge { + cursor: String! + node: CaseRfi! +} + +input CaseRfiAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + content: String + content_mapping: String + severity: String + priority: String + confidence: Int + revoked: Boolean + lang: String + objects: [String] + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectParticipant: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + file: Upload + clientMutationId: String + update: Boolean + information_types: [String!] + caseTemplates: [String!] +} + +type CaseRft implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container & Case { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + content: String + content_mapping: String + tasks: TaskConnection! + takedown_types: [String!] + severity: String + priority: String +} + +enum CaseRftsOrdering { + name + created + modified + context + created_at + updated_at + creator + createdBy + objectAssignee + x_opencti_workflow_id + confidence + objectMarking + severity + priority + _score +} + +type CaseRftConnection { + pageInfo: PageInfo! + edges: [CaseRftEdge] +} + +type CaseRftEdge { + cursor: String! + node: CaseRft! +} + +input CaseRftAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + content: String + content_mapping: String + severity: String + priority: String + confidence: Int + revoked: Boolean + lang: String + objects: [String] + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectParticipant: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + file: Upload + clientMutationId: String + x_opencti_workflow_id: String + update: Boolean + takedown_types: [String!] + caseTemplates: [String!] +} + +type Feedback implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Container & Case { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + authorized_members: [MemberAccess!] + currentUserAccessRight: String + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + relatedContainers(first: Int, after: ID, orderBy: ContainersOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], viaTypes: [String]): ContainerConnection + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + contentsFromTemplate(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + templates: [Template!] + templateAndUtils(templateId: String!): TemplateAndUtils + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + name: String! + description: String + content: String + content_mapping: String + tasks: TaskConnection! + rating: Int +} + +enum FeedbacksOrdering { + name + created + modified + context + rating + created_at + updated_at + creator + createdBy + x_opencti_workflow_id + confidence + objectMarking + _score +} + +type FeedbackConnection { + pageInfo: PageInfo! + edges: [FeedbackEdge] +} + +type FeedbackEdge { + cursor: String! + node: Feedback! +} + +input FeedbackAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + content: String + content_mapping: String + confidence: Int + revoked: Boolean + lang: String + objects: [String] + createdBy: String + objectMarking: [String] + objectAssignee: [String] + objectOrganization: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + file: Upload + clientMutationId: String + update: Boolean + rating: Int +} + +type DefaultValue { + id: String! + name: String! +} + +type TypeAttribute { + name: String! + type: String! + mandatory: Boolean! + mandatoryType: String! + editDefault: Boolean! + multiple: Boolean + label: String + defaultValues: [DefaultValue!] + scale: String +} + +type ScaleAttribute { + name: String! + scale: String! +} + +type DefaultValueAttribute { + name: String! + type: String! + defaultValues: [DefaultValue!]! +} + +type OverviewWidgetCustomization { + key: String! + width: Int! + label: String! +} + +type EntitySetting implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + target_type: String! + platform_entity_files_ref: Boolean + platform_hidden_type: Boolean + enforce_reference: Boolean + attributes_configuration: String + attributesDefinitions: [TypeAttribute!]! + mandatoryAttributes: [String!]! + scaleAttributes: [ScaleAttribute!]! + defaultValuesAttributes: [DefaultValueAttribute!]! + availableSettings: [String!]! + created_at: DateTime! + updated_at: DateTime! + overview_layout_customization: [OverviewWidgetCustomization!] +} + +enum EntitySettingsOrdering { + target_type + _score +} + +type EntitySettingConnection { + pageInfo: PageInfo! + edges: [EntitySettingEdge!]! +} + +type EntitySettingEdge { + cursor: String! + node: EntitySetting! +} + +type Workspace implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + type: String + name: String! + description: String + owner: Creator + tags: [String] + manifest: String + created_at: DateTime + updated_at: DateTime + editContext: [EditUserContext!] + investigated_entities_ids: [String] + objects(first: Int, after: ID, orderBy: StixObjectOrStixRelationshipsOrdering, orderMode: OrderingMode, filters: FilterGroup, search: String, types: [String], all: Boolean): StixObjectOrStixRelationshipRefConnection + graph_data: String + authorizedMembers: [MemberAccess!]! + currentUserAccessRight: String + toStixReportBundle: String + toConfigurationExport: String! + toWidgetExport(widgetId: ID!): String! + isShared: Boolean +} + +enum WorkspacesOrdering { + name + created_at + updated_at + creator + _score +} + +type WorkspaceConnection { + pageInfo: PageInfo! + edges: [WorkspaceEdge!]! +} + +type WorkspaceEdge { + cursor: String! + node: Workspace! +} + +input WorkspaceAddInput { + type: String! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + tags: [String] + authorized_members: [MemberAccessInput!] + investigated_entities_ids: [String] +} + +input WorkspaceDuplicateInput { + type: String! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + manifest: String + tags: [String] +} + +input ImportConfigurationInput { + importType: String! + file: Upload! + dashboardManifest: String +} + +input ImportWidgetInput { + file: Upload! + dashboardManifest: String +} + +type MalwareAnalysis implements BasicObject & StixCoreObject & StixDomainObject & StixObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + x_opencti_inferences: [Inference] + draftVersion: DraftVersion + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean + product: String! + version: String + hostVm: Software + operatingSystem: Software + installedSoftware: SoftwareConnection + configuration_version: String + modules: [String!] + analysis_engine_version: String + analysis_definition_version: String + submitted: DateTime + analysis_started: DateTime + analysis_ended: DateTime + result_name: String! + result: String + analysisSco: StixCyberObservableConnection + sample: StixCyberObservable +} + +enum MalwareAnalysesOrdering { + result_name + product + operatingSystem + creator + createdBy + objectLabel + submitted + objectMarking + x_opencti_workflow_id + confidence + _score +} + +type MalwareAnalysisConnection { + pageInfo: PageInfo! + edges: [MalwareAnalysisEdge!] +} + +type MalwareAnalysisEdge { + cursor: String! + node: MalwareAnalysis! +} + +input MalwareAnalysisAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + product: String! + version: String + hostVm: String + operatingSystem: String + installedSoftware: [String] + configuration_version: String + modules: [String] + analysis_engine_version: String + analysis_definition_version: String + submitted: DateTime + analysis_started: DateTime + analysis_ended: DateTime + result_name: String! + result: String + analysisSco: [String] + analysisSample: String + created: DateTime + modified: DateTime + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectAssignee: [String] + externalReferences: [String] + objectOrganization: [String] + objectLabel: [String] + clientMutationId: String + x_opencti_workflow_id: String + update: Boolean + file: Upload +} + +type ManagerConfiguration implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + manager_id: String! + manager_running: Boolean + last_run_start_date: DateTime + last_run_end_date: DateTime + manager_setting: JSON +} + +enum NotifierOrdering { + name + created + connector + _score +} + +type NotifierParameter { + key: String + value: String +} + +type NotifierConnector { + id: ID! + name: String! + connector_type: String + connector_schema: String + connector_schema_ui: String + built_in: Boolean +} + +type Notifier implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + created: DateTime + modified: DateTime + name: String! + description: String + notifier_connector: NotifierConnector! + notifier_connector_id: String! + notifier_configuration: String! + authorized_members: [MemberAccess!] +} + +type NotifierConnection { + pageInfo: PageInfo! + edges: [NotifierEdge] +} + +type NotifierEdge { + cursor: String! + node: Notifier! +} + +input NotifierTestInput { + notifier_test_id: String! + notifier_connector_id: String! + notifier_configuration: String! +} + +input NotifierAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + notifier_connector_id: String! + notifier_configuration: String! + authorized_members: [MemberAccessInput!] +} + +type Measure { + index: Int + measure: Float + date_seen: DateTime +} + +input MeasureInput { + measure: Float + date_seen: DateTime +} + +type ThreatActorIndividual implements BasicObject & StixObject & StixCoreObject & StixDomainObject & ThreatActor { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + name: String! + description: String + aliases: [String] + threat_actor_types: [String] + first_seen: DateTime + last_seen: DateTime + roles: [String] + goals: [String] + sophistication: String + resource_level: String + primary_motivation: String + secondary_motivations: [String] + personal_motivations: [String] + locations: LocationConnection + countries: CountryConnection + date_of_birth: DateTime + gender: String + job_title: String + marital_status: String + eye_color: String + hair_color: String + height: [Measure!] + weight: [Measure!] + bornIn: Country + ethnicity: Country + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum ThreatActorsIndividualOrdering { + name + created + modified + created_at + updated_at + x_opencti_workflow_id + sophistication + resource_level + confidence + _score + objectMarking + threat_actor_types +} + +type ThreatActorIndividualConnection { + pageInfo: PageInfo! + edges: [ThreatActorIndividualEdge] +} + +type ThreatActorIndividualEdge { + cursor: String! + node: ThreatActorIndividual! +} + +input ThreatActorIndividualAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + aliases: [String] + threat_actor_types: [String] + first_seen: DateTime + last_seen: DateTime + roles: [String] + goals: [String] + sophistication: String + resource_level: String + primary_motivation: String + secondary_motivations: [String] + personal_motivations: [String] + date_of_birth: DateTime + gender: String + job_title: String + marital_status: String + eye_color: String + hair_color: String + height: [MeasureInput!] + weight: [MeasureInput!] + confidence: Int + revoked: Boolean + lang: String + createdBy: String + objectMarking: [String] + objectOrganization: [String] + objectAssignee: [String] + objectLabel: [String] + bornIn: String + ethnicity: String + externalReferences: [String] + created: DateTime + modified: DateTime + clientMutationId: String + x_opencti_workflow_id: String + update: Boolean + file: Upload +} + +type PlayBookExecutionStep { + id: ID! + message: String + status: String + in_timestamp: String + out_timestamp: String + duration: Int + bundle_or_patch: String + error: String +} + +type PlayBookExecution { + id: ID! + playbook_id: ID! + execution_start: String + steps: [PlayBookExecutionStep!] +} + +type Playbook implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + name: String! + description: String + playbook_running: Boolean + playbook_definition: String + last_executions: [PlayBookExecution!] + queue_messages: Int! +} + +type PlaybookComponentPort { + id: ID! + type: String! +} + +type PlaybookComponent { + id: ID! + name: String! + description: String! + icon: String! + is_entry_point: Boolean + is_internal: Boolean + configuration_schema: String + ports: [PlaybookComponentPort!]! +} + +type PlaybookInsertResult { + nodeId: String! + linkId: String! +} + +enum PlaybooksOrdering { + name + playbook_running + _score +} + +type PlaybookConnection { + pageInfo: PageInfo! + edges: [PlaybookEdge!]! +} + +type PlaybookEdge { + cursor: String! + node: Playbook! +} + +input PlaybookAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String +} + +input PositionInput { + x: Float! + y: Float! +} + +input PlaybookAddNodeInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + component_id: String! + position: PositionInput! + configuration: String +} + +input PlaybookAddLinkInput { + from_node: String! + from_port: String! + to_node: String! +} + +type IngestionRss implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + created_at: DateTime + updated_at: DateTime + name: String! + description: String + uri: String! + user: Creator + defaultCreatedBy: Identity + defaultMarkingDefinitions: [MarkingDefinition] + report_types: [String!] + current_state_date: DateTime + ingestion_running: Boolean +} + +enum IngestionRssOrdering { + name + created_at + updated_at + uri + _score +} + +type IngestionRssConnection { + pageInfo: PageInfo! + edges: [IngestionRssEdge!]! +} + +type IngestionRssEdge { + cursor: String! + node: IngestionRss! +} + +input IngestionRssAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + + "*Constraints:*\n* Minimal length: `5`\n" + uri: String! + current_state_date: DateTime + ingestion_running: Boolean + user_id: String + created_by_ref: String + object_marking_refs: [String!] + report_types: [String!] +} + +enum TaxiiVersion { + v1 + v2 + v21 +} + +enum IngestionAuthType { + none + basic + bearer + certificate +} + +type IngestionTaxii implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + created_at: DateTime + updated_at: DateTime + name: String! + description: String + uri: String! + collection: String! + version: TaxiiVersion! + authentication_type: IngestionAuthType! + authentication_value: String + user_id: String + user: Creator + current_state_cursor: String + added_after_start: DateTime + ingestion_running: Boolean + last_execution_date: DateTime + confidence_to_score: Boolean +} + +enum IngestionTaxiiOrdering { + name + created_at + updated_at + uri + version + _score +} + +type IngestionTaxiiConnection { + pageInfo: PageInfo! + edges: [IngestionTaxiiEdge!]! +} + +type IngestionTaxiiEdge { + cursor: String! + node: IngestionTaxii! +} + +input IngestionTaxiiAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + version: TaxiiVersion! + authentication_type: IngestionAuthType! + authentication_value: String + + "*Constraints:*\n* Minimal length: `5`\n" + uri: String! + + "*Constraints:*\n* Minimal length: `5`\n" + collection: String! + added_after_start: DateTime + ingestion_running: Boolean + confidence_to_score: Boolean + user_id: String +} + +type IngestionCsv implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String]! + created_at: DateTime + updated_at: DateTime + name: String! + description: String + uri: String! + csvMapper: CsvMapper! + authentication_type: IngestionAuthType! + authentication_value: String + user_id: String! + user: Creator + ingestion_running: Boolean + current_state_hash: String + current_state_date: DateTime + markings: [String!] +} + +enum IngestionCsvOrdering { + name + created_at + updated_at + uri + mapper + _score +} + +type IngestionCsvConnection { + pageInfo: PageInfo! + edges: [IngestionCsvEdge!]! +} + +type IngestionCsvEdge { + cursor: String! + node: IngestionCsv! +} + +input IngestionCsvAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + authentication_type: IngestionAuthType! + authentication_value: String + current_state_date: DateTime + + "*Constraints:*\n* Minimal length: `5`\n" + uri: String! + csv_mapper_id: String! + ingestion_running: Boolean + user_id: String! + markings: [String!] +} + +enum IndicatorsOrdering { + pattern_type + pattern_version + pattern + name + indicator_types + valid_from + valid_until + x_opencti_score + x_opencti_detection + confidence + created + modified + created_at + updated_at + x_opencti_workflow_id + objectMarking + creator + createdBy + _score +} + +type IndicatorConnection { + pageInfo: PageInfo! + edges: [IndicatorEdge] +} + +type IndicatorEdge { + cursor: String! + node: Indicator! +} + +type DecayHistory { + updated_at: DateTime! + score: Int! +} + +type IndicatorDecayRule { + decay_rule_id: String + decay_lifetime: Int! + decay_pound: Float! + decay_points: [Int!] + decay_revoke_score: Int! +} + +type DecayLiveDetails { + live_score: Int! + live_points: [DecayHistory!] +} + +type DecayChartData { + live_score_serie: [DecayHistory!] +} + +type ObservablesValues { + type: String + value: String +} + +type Indicator implements BasicObject & StixObject & StixCoreObject & StixDomainObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + pattern_type: String + pattern_version: String + pattern: String + name: String! + description: String + indicator_types: [String] + valid_from: DateTime + valid_until: DateTime + x_opencti_score: Int + x_opencti_detection: Boolean + x_opencti_main_observable_type: String + x_opencti_observable_values: [ObservablesValues!] + x_mitre_platforms: [String] + killChainPhases: [KillChainPhase!] + observables(first: Int): StixCyberObservableConnection + decay_base_score: Int + decay_base_score_date: DateTime + decay_applied_rule: IndicatorDecayRule + decay_history: [DecayHistory!] + decayLiveDetails: DecayLiveDetails + decayChartData: DecayChartData + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +input IndicatorAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId!] + pattern_type: String! + pattern_version: String + pattern: String! + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + indicator_types: [String!] + valid_from: DateTime + valid_until: DateTime + confidence: Int + revoked: Boolean + lang: String + x_opencti_score: Int + x_opencti_detection: Boolean + x_opencti_main_observable_type: String + x_mitre_platforms: [String!] + killChainPhases: [String!] + createdBy: String + objectMarking: [String!] + objectLabel: [String!] + objectOrganization: [String!] + externalReferences: [String!] + created: DateTime + modified: DateTime + clientMutationId: String + update: Boolean + createObservables: Boolean + x_opencti_workflow_id: String + file: Upload + basedOn: [String!] +} + +type DecayRule implements InternalObject & BasicObject { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + created_at: DateTime! + updated_at: DateTime! + name: String! + description: String + order: Int! + active: Boolean! + built_in: Boolean + appliedIndicatorsCount: Int! + decay_lifetime: Int! + decay_pound: Float! + decay_points: [Int!] + decay_revoke_score: Int! + decay_observable_types: [String!] + decaySettingsChartData: DecayData +} + +type DecayData { + live_score_serie: [DecayHistory!] +} + +enum DecayRuleOrdering { + name + order + _score +} + +type DecayRuleConnection { + pageInfo: PageInfo! + edges: [DecayRuleEdge!]! +} + +type DecayRuleEdge { + cursor: String! + node: DecayRule! +} + +input DecayRuleAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + order: Int! + active: Boolean! + decay_lifetime: Int! + decay_pound: Float! + decay_points: [Int!] + decay_revoke_score: Int! + decay_observable_types: [String!] +} + +type Organization implements BasicObject & StixObject & StixCoreObject & StixDomainObject & Identity { + id: ID! + standard_id: String! + entity_type: String! + parent_types: [String]! + representative: Representative! + x_opencti_stix_ids: [StixId] + is_inferred: Boolean! + spec_version: String! + created_at: DateTime! + updated_at: DateTime! + draftVersion: DraftVersion + x_opencti_inferences: [Inference] + createdBy: Identity + numberOfConnectedElement: Int! + objectMarking: [MarkingDefinition!] + objectOrganization: [Organization!] + objectLabel: [Label!] + externalReferences(first: Int): ExternalReferenceConnection + containersNumber: Number + containers(first: Int, entityTypes: [String!]): ContainerConnection + reports(first: Int): ReportConnection + notes(first: Int): NoteConnection + opinions(first: Int): OpinionConnection + observedData(first: Int): ObservedDataConnection + groupings(first: Int): GroupingConnection + cases(first: Int): CaseConnection + stixCoreRelationships(first: Int, after: ID, orderBy: StixCoreRelationshipsOrdering, orderMode: OrderingMode, fromId: StixRef, toId: StixRef, fromTypes: [String], toTypes: [String], relationship_type: String, startTimeStart: DateTime, startTimeStop: DateTime, stopTimeStart: DateTime, stopTimeStop: DateTime, firstSeenStart: DateTime, firstSeenStop: DateTime, lastSeenStart: DateTime, lastSeenStop: DateTime, confidences: [Int], search: String, filters: FilterGroup): StixCoreRelationshipConnection + stixCoreObjectsDistribution(relationship_type: [String], toTypes: [String], field: String!, startDate: DateTime, endDate: DateTime, dateAttribute: String, operation: StatsOperation!, limit: Int, order: String, types: [String], filters: FilterGroup, search: String): [Distribution] + stixCoreRelationshipsDistribution(field: String!, operation: StatsOperation!, startDate: DateTime, endDate: DateTime, dateAttribute: String, isTo: Boolean, limit: Int, order: String, elementWithTargetTypes: [String], fromId: [String], fromRole: String, fromTypes: [String], toId: [String], toRole: String, toTypes: [String], relationship_type: [String], confidences: [Int], search: String, filters: FilterGroup): [Distribution] + opinions_metrics: OpinionsMetrics + revoked: Boolean! + confidence: Int + lang: String + created: DateTime + modified: DateTime + x_opencti_graph_data: String + objectAssignee: [Assignee!] + objectParticipant: [Participant!] + avatar: OpenCtiFile + identity_class: String! + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + x_opencti_reliability: String + x_opencti_organization_type: String + sectors: SectorConnection + members(first: Int, after: ID, orderBy: UsersOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): UserConnection + authorized_authorities: [String] + grantable_groups: [Group!] + subOrganizations: OrganizationConnection + parentOrganizations: OrganizationConnection + default_dashboard: Workspace + default_hidden_types: [String!] + creators: [Creator!] + toStix: String + importFiles(first: Int, prefixMimeType: String, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + pendingFiles(first: Int, after: ID, orderBy: FileOrdering, orderMode: OrderingMode, search: String, filters: FilterGroup): FileConnection + exportFiles(first: Int): FileConnection + editContext: [EditUserContext!] + connectors(onlyAlive: Boolean): [Connector] + jobs(first: Int): [Work] + status: Status + workflowEnabled: Boolean +} + +enum OrganizationsOrdering { + name + confidence + created + created_at + modified + updated_at + x_opencti_organization_type + x_opencti_workflow_id + _score +} + +type OrganizationConnection { + pageInfo: PageInfo! + edges: [OrganizationEdge!]! +} + +type OrganizationEdge { + cursor: String! + node: Organization! +} + +input OrganizationAddInput { + stix_id: StixId + x_opencti_stix_ids: [StixId] + + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + description: String + contact_information: String + roles: [String] + x_opencti_aliases: [String] + confidence: Int + revoked: Boolean + lang: String + x_opencti_organization_type: String + x_opencti_reliability: String + createdBy: String + objectMarking: [String] + objectLabel: [String] + externalReferences: [String] + created: DateTime + modified: DateTime + x_opencti_workflow_id: String + clientMutationId: String + update: Boolean + file: Upload +} + +type MeOrganization { + id: ID! + name: String! +} + +type MeOrganizationEdge { + cursor: String! + node: MeOrganization! +} + +type MeOrganizationConnection { + pageInfo: PageInfo! + edges: [MeOrganizationEdge!]! +} + +type AttributeColumnConfiguration { + separator: String + pattern_date: String + timezone: String +} + +type AttributeColumn { + column_name: String + configuration: AttributeColumnConfiguration +} + +type AttributeBasedOn { + representations: [String] +} + +type AttributeRef { + multiple: Boolean + id: String + ids: [String] +} + +type CsvMapperRepresentationAttribute { + key: String! + column: AttributeColumn + based_on: AttributeBasedOn + ref: AttributeRef + default_values: [DefaultValue!] +} + +enum CsvMapperOperator { + eq + not_eq +} + +type CsvMapperRepresentationTargetColumn { + column_reference: String + operator: CsvMapperOperator + value: String +} + +type CsvMapperRepresentationTarget { + entity_type: String! + column_based: CsvMapperRepresentationTargetColumn +} + +enum CsvMapperRepresentationType { + entity + relationship +} + +type CsvMapperRepresentation { + id: ID! + type: CsvMapperRepresentationType! + target: CsvMapperRepresentationTarget! + attributes: [CsvMapperRepresentationAttribute!]! + from: String + to: String +} + +type CsvMapper implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + name: String! + has_header: Boolean! + separator: String! + skipLineChar: String + representations: [CsvMapperRepresentation!]! + errors: String +} + +enum CsvMapperOrdering { + name + _score +} + +type CsvMapperConnection { + pageInfo: PageInfo! + edges: [CsvMapperEdge!]! +} + +type CsvMapperEdge { + cursor: String! + node: CsvMapper! +} + +type CsvMapperTestResult { + objects: String! + nbRelationships: Int! + nbEntities: Int! +} + +type CsvMapperSchemaAttribute { + name: String! + type: String! + mandatory: Boolean! + mandatoryType: String! + editDefault: Boolean! + multiple: Boolean! + defaultValues: [DefaultValue!] + label: String! + mappings: [CsvMapperSchemaAttribute!] +} + +type CsvMapperSchemaAttributes { + name: String! + attributes: [CsvMapperSchemaAttribute!]! +} + +input AttributeColumnConfigurationInput { + separator: String + pattern_date: String + timezone: String +} + +input AttributeColumnInput { + column_name: String + configuration: AttributeColumnConfigurationInput +} + +input AttributeBasedOnInput { + representations: [String] +} + +input AttributeRefInput { + multiple: Boolean + id: String + ids: [String] +} + +input CsvMapperRepresentationAttributeInput { + key: String + column: AttributeColumnInput + based_on: AttributeBasedOnInput + ref: AttributeRefInput +} + +input CsvMapperRepresentationTargetColumnInput { + column_reference: String + operator: CsvMapperOperator + value: String +} + +input CsvMapperRepresentationTargetInput { + entity_type: String! + column_based: CsvMapperRepresentationTargetColumnInput +} + +input CsvMapperRepresentationInput { + id: ID! + type: CsvMapperRepresentationType! + target: CsvMapperRepresentationTargetInput! + attributes: [CsvMapperRepresentationAttributeInput]! + from: String + to: String +} + +input CsvMapperAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + has_header: Boolean! + separator: String! + representations: String! + skipLineChar: String +} + +type PublicDashboard implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + name: String! + owner: Creator + description: String + dashboard_id: String! + dashboard: Workspace! + user_id: String! + public_manifest: String + private_manifest: String + uri_key: String! + allowed_markings_ids: [String!] + allowed_markings: [MarkingDefinitionShort!] + created_at: DateTime + updated_at: DateTime + editContext: [EditUserContext!] + enabled: Boolean! +} + +type PublicDistribution { + label: String! + entity: StixObjectOrStixRelationshipOrCreator + value: Int + breakdownDistribution: [Distribution] +} + +enum PublicDashboardsOrdering { + name + created_at + updated_at + user_id + enabled + dashboard + uri_key + _score +} + +type PublicDashboardConnection { + pageInfo: PageInfo! + edges: [PublicDashboardEdge!]! +} + +type PublicDashboardEdge { + cursor: String! + node: PublicDashboard! +} + +input PublicDashboardAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! + uri_key: String! + description: String + dashboard_id: String! + allowed_markings_ids: [String!] + enabled: Boolean! +} + +enum Tone { + tactical + operational + strategic +} + +enum Format { + text + html + markdown + json +} + +enum IndicatorFormat { + stix + sigma + yara +} + +type AIBus { + bus_id: String! + content: String! +} + +enum ScenarioType { + container + threat + victim +} + +enum Selection { + multiple + random +} + +enum SimulationType { + technical + simulated + mixed +} + +type SimulationsResult { + unknown: Int + success: Int + failure: Int +} + +type StixObjectSimulationsResult { + prevention: SimulationsResult + detection: SimulationsResult + human: SimulationsResult +} + +type DeletedElement { + id: String! + source_index: String! +} + +type DeleteOperation implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + objectMarking: [MarkingDefinition!] + confidence: Int + created_at: DateTime + deletedBy: Creator + main_entity_type: String! + main_entity_id: String! + main_entity_name: String! + deleted_elements: [DeletedElement!]! +} + +enum DeleteOperationOrdering { + main_entity_name + created_at + deletedBy + objectMarking + _score +} + +type DeleteOperationConnection { + pageInfo: PageInfo! + edges: [DeleteOperationEdge!]! +} + +type DeleteOperationEdge { + cursor: String! + node: DeleteOperation! +} + +type SupportPackage implements InternalObject & BasicObject { + id: ID! + name: String! + standard_id: String! + entity_type: String! + parent_types: [String]! + created_at: DateTime! + package_status: PackageStatus! + package_url: String + package_upload_dir: String + nodes_count: Int! + createdBy: Individual + creators: [Creator!] +} + +type SupportPackageConnection { + pageInfo: PageInfo! + edges: [SupportPackageEdge!]! +} + +type SupportPackageEdge { + cursor: String! + node: SupportPackage! +} + +enum PackageStatus { + IN_PROGRESS + READY + IN_ERROR +} + +enum SupportPackageOrdering { + name + created_at + package_status +} + +input SupportPackageAddInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + name: String! +} + +input SupportPackageForceZipInput { + "*Constraints:*\n* Minimal length: `2`\n* Must match format: `not-blank`\n" + id: String! +} + +type ExclusionList implements InternalObject & BasicObject { + id: ID! + name: String! + description: String + standard_id: String! + entity_type: String! + parent_types: [String]! + created_at: DateTime! + enabled: Boolean! + list_entity_types: [ExclusionListEntityTypes!]! + file_id: String! +} + +type ExclusionListConnection { + pageInfo: PageInfo! + edges: [ExclusionListEdge!] +} + +type ExclusionListEdge { + cursor: String! + node: ExclusionList! +} + +enum ExclusionListOrdering { + name + created_at +} + +enum ExclusionListEntityTypes { + IPV4_ADDR + IPV6_ADDR + DOMAIN_NAME + URL +} + +input ExclusionListContentAddInput { + name: String! + description: String + list_entity_types: [ExclusionListEntityTypes!]! + content: String! +} + +input ExclusionListFileAddInput { + name: String! + description: String + list_entity_types: [ExclusionListEntityTypes!]! + file: Upload! +} + +type DraftWorkspace implements InternalObject & BasicObject { + id: ID! + entity_type: String! + standard_id: String! + parent_types: [String!]! + name: String! + created_at: DateTime! + creators: [Creator!] + entity_id: String +} + +enum DraftWorkspacesOrdering { + name + created_at + creator +} + +type DraftWorkspaceConnection { + pageInfo: PageInfo! + edges: [DraftWorkspaceEdge!]! +} + +type DraftWorkspaceEdge { + cursor: String! + node: DraftWorkspace! +} + +input DraftWorkspaceAddInput { + name: String! + entity_id: String +} \ No newline at end of file diff --git a/src/opencti.py b/src/opencti.py new file mode 100644 index 0000000..c1e6d18 --- /dev/null +++ b/src/opencti.py @@ -0,0 +1,231 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +"""OpenCTI API client.""" +import functools +import pathlib +import secrets +import typing +import urllib.parse + +import gql +import gql.dsl +import gql.transport.requests +import graphql + + +class OpenctiUser(typing.NamedTuple): + """Opencti user. + + Attributes: + id: opencti user id + name: opencti username + user_email: opencti user email + account_status: opencti account status + api_token: opencti user api token + """ + + id: str + name: str + user_email: str + account_status: str + api_token: str + + +class OpenctiGroup(typing.NamedTuple): + """Opencti group. + + Attributes: + id: opencti group id + name: opencti group name + """ + + id: str + name: str + + +class GraphqlError(Exception): + """GraphQL error.""" + + +class OpenctiClient: + """Opencti API client.""" + + def __init__(self, url: str, api_token: str) -> None: + """Construct the Opencti client. + + Args: + url: URL of the Opencti API. + api_token: Opencti API token. + """ + transport = gql.transport.requests.RequestsHTTPTransport( + url=urllib.parse.urljoin(url, "graphql"), + headers={"Authorization": f"Bearer {api_token}"}, + ) + self._client = gql.Client( + transport=transport, + schema=(pathlib.Path(__file__).parent / "opencti.graphql").read_text(), + ) + self._dsl_schema = gql.dsl.DSLSchema( + typing.cast(graphql.GraphQLSchema, self._client.schema) + ) + + @functools.lru_cache(maxsize=10) + def list_users(self, name_starts_with: str | None = None) -> list[OpenctiUser]: + """List OpenCTI users. + + Args: + name_starts_with: list users with name starts with. + + Returns: + list of OpenctiUser objects. + """ + filters = None + if name_starts_with: + filters = { + "mode": "and", + "filters": [ + { + "key": "name", + "values": name_starts_with, + "operator": "starts_with", + "mode": "and", + } + ], + "filterGroups": [], + } + query = gql.dsl.dsl_gql( + gql.dsl.DSLQuery( + self._dsl_schema.Query.users(filters=filters).select( + self._dsl_schema.UserConnection.edges.select( + self._dsl_schema.UserEdge.node.select( + self._dsl_schema.User.id, + self._dsl_schema.User.name, + self._dsl_schema.User.user_email, + self._dsl_schema.User.account_status, + self._dsl_schema.User.api_token, + ), + ), + ) + ) + ) + data = self._client.execute(query) + users = [] + for user in data["users"]["edges"]: + node = user["node"] + users.append( + OpenctiUser( + id=node["id"], + name=node["name"], + user_email=node["user_email"], + account_status=node["account_status"], + api_token=node["api_token"], + ) + ) + return users + + def create_user( + self, + name: str, + user_email: str | None = None, + groups: list[str] | None = None, + ) -> OpenctiUser: + """Create a OpenCTI user. + + Args: + name: User name. + user_email: User's email address. + groups: User's groups. + + Returns: + new user. + """ + self.list_users.cache_clear() + if user_email is None: + user_email = f"{name}@opencti.local" + if groups is None: + groups = [] + query = gql.dsl.dsl_gql( + gql.dsl.DSLMutation( + self._dsl_schema.Mutation.userAdd.args( + input={ + "name": name, + "user_email": user_email, + "first_name": "", + "last_name": "", + "password": secrets.token_urlsafe(32), + "account_status": "Active", + "groups": groups, + } + ).select( + self._dsl_schema.User.id, + self._dsl_schema.User.name, + self._dsl_schema.User.user_email, + self._dsl_schema.User.account_status, + self._dsl_schema.User.api_token, + ) + ) + ) + result = self._client.execute(query) + user = result["userAdd"] + return OpenctiUser( + id=user["id"], + name=user["name"], + user_email=user["user_email"], + account_status=user["account_status"], + api_token=user["api_token"], + ) + + @functools.lru_cache(maxsize=10) + def list_groups(self) -> list[OpenctiGroup]: + """List OpenCTI groups. + + Returns: + list of OpenctiGroup objects. + """ + query = gql.dsl.dsl_gql( + gql.dsl.DSLQuery( + self._dsl_schema.Query.groups.select( + self._dsl_schema.GroupConnection.edges.select( + self._dsl_schema.GroupEdge.node.select( + self._dsl_schema.Group.id, self._dsl_schema.Group.name + ) + ) + ) + ) + ) + data = self._client.execute(query) + groups = [] + for group in data["groups"]["edges"]: + group = group["node"] + groups.append(OpenctiGroup(id=group["id"], name=group["name"])) + return groups + + def set_account_status( + self, + user_id: str, + status: typing.Literal["Active", "Inactive"], + ) -> None: + """Set Opencti account status. + + Args: + user_id: Opencti user id. + status: Opencti account status. + """ + self.list_users.cache_clear() + query = gql.dsl.dsl_gql( + gql.dsl.DSLMutation( + self._dsl_schema.Mutation.userEdit(id=user_id).select( + self._dsl_schema.UserEditMutations.fieldPatch( + input=[ + { + "key": "account_status", + "value": status, + "operation": "replace", + } + ] + ).select(self._dsl_schema.User.id) + ) + ) + ) + self._client.execute(query) diff --git a/tests/conftest.py b/tests/conftest.py index adeaee9..38f4ca9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,30 @@ """Fixtures for charm tests.""" +import pathlib + +import pytest +import yaml + + +def list_connectors() -> list[str]: + """Return a list of opencti connector charms. + + Returns: + list: list of opencti connector charms. + """ + connectors = [] + for file in pathlib.Path("connectors").glob("**/charmcraft.yaml"): + charmcraft_yaml = yaml.safe_load(file.read_text()) + connectors.append(charmcraft_yaml["name"]) + return connectors + + +@pytest.fixture(scope="session", name="connectors") +def connectors_fixture() -> list[str]: + """Return a list of opencti connector charms.""" + return list_connectors() + def pytest_addoption(parser): """Parse additional pytest options. @@ -10,6 +34,8 @@ def pytest_addoption(parser): Args: parser: Pytest parser. """ - parser.addoption("--charm-file", action="store") + parser.addoption("--charm-file", action="append") parser.addoption("--opencti-image", action="store") parser.addoption("--machine-controller", action="store", default="localhost") + for connector in list_connectors(): + parser.addoption(f"--{connector}-image", action="store") diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 18d3ae3..5c370fa 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -5,6 +5,7 @@ import json import logging +import pathlib import secrets import typing @@ -53,7 +54,7 @@ async def machine_controller_fixture( @pytest_asyncio.fixture(scope="module", name="machine_model") async def machine_model_fixture( - machine_controller: Controller, machine_controller_name: str + machine_controller: Controller, machine_controller_name: str, pytestconfig ) -> typing.AsyncGenerator[Model, None]: """The machine model for OpenSearch charm.""" machine_model_name = f"test-opencti-deps-{secrets.token_hex(2)}" @@ -62,7 +63,8 @@ async def machine_model_fixture( await model.set_config(MACHINE_MODEL_CONFIG) yield model await model.disconnect() - await machine_controller.destroy_models(model.uuid) + if not pytestconfig.getoption("--keep-models"): + await machine_controller.destroy_models(model.uuid) @pytest_asyncio.fixture(name="get_unit_ips", scope="module") @@ -99,3 +101,39 @@ async def machine_charm_dependencies_fixture(machine_model: Model): rabbitmq_server = await machine_model.deploy("rabbitmq-server", channel="3.9/stable") await machine_model.create_offer(f"{rabbitmq_server.name}:amqp", "amqp") await machine_model.wait_for_idle(timeout=1200) + + +@pytest.fixture(name="opencti_charm", scope="module") +def opencti_charm_fixture(pytestconfig) -> dict[str, str]: + """Opencti charm file.""" + charm_files = pytestconfig.getoption("--charm-file") + assert charm_files + for charm_file in charm_files: + if "connector" not in pathlib.Path(charm_file).name: + return charm_file + raise ValueError("opencti charm file not provided") + + +@pytest.fixture(name="opencti_connector_charms", scope="module") +def opencti_connector_charms_fixture(connectors, pytestconfig) -> dict[str, str]: + """Get opencti connector charm files.""" + charms = {} + charm_files = pytestconfig.getoption("--charm-file") + for charm_file in charm_files: + name = pathlib.Path(charm_file).name.split("_")[0] + if name in connectors: + charms[name] = charm_file + logger.info("load opencti connector charms: %s", charms) + return charms + + +@pytest.fixture(name="opencti_connector_images", scope="module") +def opencti_connector_images_fixture(connectors, pytestconfig) -> dict[str, str]: + """Get opencti connector charm images.""" + images = {} + for connector in connectors: + image = pytestconfig.getoption(f"--{connector}-image") + if image: + images[connector] = image + logger.info("load opencti connector images: %s", images) + return images diff --git a/tests/integration/test_charm.py b/tests/integration/test_charm.py index 8fc9ece..02f2bb5 100644 --- a/tests/integration/test_charm.py +++ b/tests/integration/test_charm.py @@ -16,6 +16,8 @@ import yaml from juju.model import Model +from opencti import OpenctiClient + @pytest.mark.abort_on_fail @pytest.mark.usefixtures("machine_charm_dependencies") @@ -25,6 +27,7 @@ async def test_deploy_charm( machine_model: Model, machine_controller_name: str, get_unit_ips, + opencti_charm, ): """ arrange: deploy dependencies of the OpenCTI charm. @@ -63,7 +66,7 @@ async def test_deploy_charm( ) await action.wait() opencti = await model.deploy( - f"./{pytestconfig.getoption('--charm-file')}", + f"./{opencti_charm}", resources={ "opencti-image": pytestconfig.getoption("--opencti-image"), }, @@ -128,3 +131,79 @@ async def test_opencti_workers(get_unit_ips, ops_test): ) worker_count = resp.json()["data"]["rabbitMQMetrics"]["consumers"] assert worker_count == str(3) + + +async def test_opencti_client(get_unit_ips, ops_test): + """ + arrange: deploy the OpenCTI charm. + act: use the OpenCTI client to create some users. + assert: users are created normally. + """ + _, stdout, _ = await ops_test.juju( + "ssh", "--container", "opencti", "opencti/0", "pebble", "plan" + ) + plan = yaml.safe_load(stdout) + api_token = plan["services"]["platform"]["environment"]["APP__ADMIN__TOKEN"] + client = OpenctiClient( + url=f"http://{(await get_unit_ips('opencti'))[0]}:8080", api_token=api_token + ) + assert {u.name for u in client.list_users()} == {"admin"} + assert {g.name for g in client.list_groups()} == {"Administrators", "Connectors", "Default"} + client.create_user(name="testing") + user = {u.name: u for u in client.list_users()}["testing"] + client.set_account_status(user.id, "Inactive") + user = {u.name: u for u in client.list_users()}["testing"] + assert user.account_status == "Inactive" + + +async def test_opencti_connectors( + get_unit_ips, ops_test, model, opencti_connector_charms, opencti_connector_images +): + """ + arrange: deploy the OpenCTI charm and OpenCTI connector charm. + act: integrate the OpenCTI connector charm with the OpenCTI charm. + assert: OpenCTI connector should register itself inside the OpenCTI platform + """ + connector = "opencti-export-file-stix-connector" + charm = opencti_connector_charms[connector] + image = opencti_connector_images[connector] + connector_charm = await model.deploy( + f"./{charm}", + resources={ + f"{connector}-image": image, + }, + config={"connector-scope": "application/json"}, + ) + await model.integrate(connector_charm.name, "opencti") + await model.wait_for_idle(status="active") + query = { + "id": "WorkersStatusQuery", + "query": textwrap.dedent( + """\ + query ConnectorsStatusQuery { + ...ConnectorsStatus_data + } + fragment ConnectorsStatus_data on Query { + connectors { + name + active + } + } + """ + ), + "variables": {}, + } + _, stdout, _ = await ops_test.juju( + "ssh", "--container", "opencti", "opencti/0", "pebble", "plan" + ) + plan = yaml.safe_load(stdout) + api_token = plan["services"]["platform"]["environment"]["APP__ADMIN__TOKEN"] + resp = requests.post( + f"http://{(await get_unit_ips('opencti'))[0]}:8080/graphql", + json=query, + headers={"Authorization": f"Bearer {api_token}"}, + timeout=5, + ) + connectors = {c["name"]: c for c in resp.json()["data"]["connectors"]} + assert connector in connectors + assert connectors[connector]["active"] diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index a51531b..d3c4e4e 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -3,12 +3,15 @@ """Fixtures for charm unit tests.""" +import typing import unittest.mock from unittest.mock import MagicMock import pytest +import opencti import src.charm +from opencti import OpenctiGroup, OpenctiUser @pytest.fixture(scope="function", autouse=True) @@ -17,9 +20,105 @@ def juju_version(monkeypatch): monkeypatch.setenv("JUJU_VERSION", "3.3.0") -@pytest.fixture(scope="function") +@pytest.fixture(scope="function", autouse=True) def patch_is_platform_healthy(): """Patch OpenCTICharm.is_platform_healthy function.""" mock = MagicMock(return_value=True) with unittest.mock.patch.object(src.charm.OpenCTICharm, "_is_platform_healthy", mock): yield mock + + +@pytest.fixture(scope="function", autouse=True) +def patch_opencti_client(): + """Patch OpenctiClient class.""" + with unittest.mock.patch.object(opencti, "OpenctiClient", OpenctiClientMock): + yield OpenctiClientMock() + + +class OpenctiClientMock: + """A mock for OpenctiClient.""" + + _users = [ + { + "id": "88ec0c6a-13ce-5e39-b486-354fe4a7084f", + "name": "admin", + "user_email": "admin@example.com", + "account_status": "Active", + "api_token": "a614ebcb-d597-4011-a626-c5302959efa6", + }, + ] + _groups = [ + {"name": "Administrators", "id": "35c94569-bbdd-4535-9def-26b781359a5b"}, + {"name": "Connectors", "id": "f4fb5f8d-91f5-441e-8ef9-93c283476110"}, + {"name": "Default", "id": "1e257543-6bfb-46f2-a25f-5d50bb0819bd"}, + ] + + def __init__(self, *_args, **_kwargs): + """Initialize OpenctiClientMock.""" + + def list_users(self, name_starts_with: str | None = None) -> list[OpenctiUser]: + """List OpenCTI users. + + Args: + name_starts_with: Name starts with this string. + + Returns: + A list of OpenctiUser objects. + """ + return [ + OpenctiUser(**u) for u in self._users if u["name"].startswith(name_starts_with or "") + ] + + def list_groups(self) -> list[OpenctiGroup]: + """List OpenCTI groups. + + Returns: + A list of OpenctiGroup objects. + """ + return [OpenctiGroup(**g) for g in self._groups] + + def create_user( + self, + name: str, + user_email: str | None = None, + groups: list[str] | None = None, # pylint: disable=unused-argument + ) -> OpenctiUser | None: + """Create a user. + + Args: + name: The name of the user. + user_email: The email address of the user. + groups: The groups associated with the user. + + Returns: + The created user. + """ + new_user = { + "name": name, + "id": "00000000-0000-0000-0000-000000000000", + "user_email": user_email or f"{name}@opencti.local", + "account_status": "Active", + "api_token": "00000000-0000-0000-0000-000000000000", + } + self._users.append(new_user) + return OpenctiUser(**new_user) + + def set_account_status( + self, + user_id: str, + status: typing.Literal["Active", "Inactive"], + ) -> None: + """Set OpenCTI account status. + + Args: + user_id: The ID of the user. + status: The status of the user. + + Raises: + RuntimeError: If user doesn't exist. + """ + for user in self._users: + if user["id"] == user_id: + user["account_status"] = status + return + raise RuntimeError(f"Unknown user id: {user_id}") diff --git a/tests/unit/state.py b/tests/unit/state.py index 09dbf8f..5597f11 100644 --- a/tests/unit/state.py +++ b/tests/unit/state.py @@ -256,6 +256,7 @@ def build(self) -> ops.testing.State: Returns: ops.testing.State """ return ops.testing.State( + model=ops.testing.Model("test-opencti"), leader=self._leader, containers=[ ops.testing.Container( # type: ignore @@ -267,3 +268,69 @@ def build(self) -> ops.testing.State: secrets=self._secrets, config=self._config, ) + + +class ConnectorStateBuilder: + """ops.testing.State builder for connector tests.""" + + def __init__(self, container_name: str) -> None: + """Initialize the state builder. + + Args: + container_name: name of the container. + """ + self._integrations: list[ops.testing.RelationBase] = [] + self._config: dict[str, str | int | float | bool] = {} + self._secrets: list[ops.testing.Secret] = [] + self._container_name = container_name + + def add_opencti_connector_integration(self) -> "ConnectorStateBuilder": + """Add opencti-connector integration. + + Returns: self + """ + secret = ops.testing.Secret( + tracked_content={"token": "00000000-0000-0000-0000-000000000000"} + ) + integration = ops.testing.Relation( + remote_app_name="opencti", + endpoint="opencti-connector", + remote_app_data={ + "opencti_token": secret.id, + "opencti_url": "http://opencti-endpoints.test-opencti-connector.svc:8080", + }, + ) + self._secrets.append(secret) + self._integrations.append(integration) + return self + + def set_config(self, name: str, value: str | int) -> "ConnectorStateBuilder": + """Set charm config. + + Args: + name: config name. + value: config value. + + Returns: self + """ + self._config[name] = value + return self + + def build(self) -> ops.testing.State: + """Build state. + + Returns: ops.testing.State + """ + return ops.testing.State( + model=ops.testing.Model("test-opencti-connector"), + leader=True, + containers=[ + ops.testing.Container( # type: ignore + name=self._container_name, + can_connect=True, + ) + ], + relations=self._integrations, + secrets=self._secrets, + config=self._config, + ) diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index 4b50673..08168a2 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -348,3 +348,37 @@ def test_redis_library_workaround(): state_out = ctx.run(ctx.on.config_changed(), state_in) assert state_out.unit_status.name == "blocked" assert state_out.unit_status.message == "invalid redis integration" + + +def test_opencti_connector(patch_opencti_client): + """ + arrange: provide the charm with the required integrations and configurations. + act: simulate a config-changed event. + assert: opencti charm should configure opencti users properly for the connector. + """ + ctx = ops.testing.Context(OpenCTICharm) + opencti_connector_integration = ops.testing.Relation( + endpoint="opencti-connector", + remote_app_data={ + "connector_type": "INTERNAL_EXPORT_FILE", + "connector_charm_name": "test", + }, + ) + state_in = ( + StateBuilder() + .add_required_integrations() + .add_required_configs() + .add_integration(opencti_connector_integration) + .build() + ) + state_out = ctx.run(ctx.on.config_changed(), state_in) + users = {u.name: u for u in patch_opencti_client.list_users()} + assert "charm-connector-test" in users + integration_out = state_out.get_relation(opencti_connector_integration.id) + assert ( + integration_out.local_app_data["opencti_url"] # type: ignore + == "http://opencti-endpoints.test-opencti.svc:8080" + ) + secret_id = integration_out.local_app_data["opencti_token"] # type: ignore + secret = state_out.get_secret(id=secret_id) + assert secret.tracked_content == {"token": "00000000-0000-0000-0000-000000000000"} diff --git a/tests/unit/test_connectors.py b/tests/unit/test_connectors.py new file mode 100644 index 0000000..5e3ee37 --- /dev/null +++ b/tests/unit/test_connectors.py @@ -0,0 +1,742 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +# Learn more about testing at: https://juju.is/docs/sdk/testing + +"""Unit tests for connectors.""" +import importlib + +import ops.testing +import pytest + +from connectors.export_file_stix.src.charm import OpenctiExportFileStixConnectorCharm +from tests.unit.state import ConnectorStateBuilder + + +def _kebab_to_pascal(string: str) -> str: + """Convert names from kebab case to pascal case.""" + words = string.split("-") + return "".join(word.capitalize() for word in words) + + +def _kebab_to_snake(string: str) -> str: + """Convert names from kebab case to snake case.""" + return string.replace("-", "_") + + +_CONNECTOR_TEST_PARAMS = [] + + +def _add_connector_test_params( + *, + name: str, + connector_name: str, + charm_config: dict[str, str | int | bool], + environment: dict[str, str], +) -> None: + """Add a connector test parameter.""" + _CONNECTOR_TEST_PARAMS.append(pytest.param(connector_name, charm_config, environment, id=name)) + + +_add_connector_test_params( + name="abuseipdb-ipblacklist", + connector_name="abuseipdb-ipblacklist", + charm_config={ + "connector-scope": "abuseipdb", + "connector-log-level": "error", + "abuseipdb-url": "https://api.abuseipdb.com/api/v2/blacklist", + "abuseipdb-api-key": "ChangeMe", + "abuseipdb-score": 100, + "abuseipdb-limit": 10000, + "abuseipdb-interval": 2, + }, + environment={ + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "CONNECTOR_NAME": "opencti-abuseipdb-ipblacklist-connector", + "CONNECTOR_SCOPE": "abuseipdb", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "ABUSEIPDB_URL": "https://api.abuseipdb.com/api/v2/blacklist", + "ABUSEIPDB_API_KEY": "ChangeMe", + "ABUSEIPDB_SCORE": "100", + "ABUSEIPDB_LIMIT": "10000", + "ABUSEIPDB_INTERVAL": "2", + }, +) + +_add_connector_test_params( + name="alienvault", + connector_name="alienvault", + charm_config={ + "connector-scope": "alienvault", + "connector-log-level": "error", + "connector-duration-period": "PT30M", + "alienvault-base-url": "https://otx.alienvault.com", + "alienvault-api-key": "ChangeMe", + "alienvault-tlp": "White", + "alienvault-create-observables": True, + "alienvault-create-indicators": True, + "alienvault-pulse-start-timestamp": "2022-05-01T00:00:00", + "alienvault-report-type": "threat-report", + "alienvault-report-status": "New", + "alienvault-guess-malware": False, + "alienvault-guess-cve": False, + "alienvault-excluded-pulse-indicator-types": "FileHash-MD5,FileHash-SHA1", + "alienvault-enable-relationships": True, + "alienvault-enable-attack-patterns-indicates": False, + "alienvault-interval-sec": 1800, + "alienvault-default-x-opencti-score": 50, + "alienvault-x-opencti-score-ip": 60, + "alienvault-x-opencti-score-domain": 70, + "alienvault-x-opencti-score-hostname": 75, + "alienvault-x-opencti-score-email": 70, + "alienvault-x-opencti-score-file": 85, + "alienvault-x-opencti-score-url": 80, + "alienvault-x-opencti-score-mutex": 60, + "alienvault-x-opencti-score-cryptocurrency-wallet": 80, + }, + environment={ + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "CONNECTOR_NAME": "opencti-alienvault-connector", + "CONNECTOR_SCOPE": "alienvault", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_DURATION_PERIOD": "PT30M", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "ALIENVAULT_BASE_URL": "https://otx.alienvault.com", + "ALIENVAULT_API_KEY": "ChangeMe", + "ALIENVAULT_TLP": "White", + "ALIENVAULT_CREATE_OBSERVABLES": "true", + "ALIENVAULT_CREATE_INDICATORS": "true", + "ALIENVAULT_PULSE_START_TIMESTAMP": "2022-05-01T00:00:00", + "ALIENVAULT_REPORT_TYPE": "threat-report", + "ALIENVAULT_REPORT_STATUS": "New", + "ALIENVAULT_GUESS_MALWARE": "false", + "ALIENVAULT_GUESS_CVE": "false", + "ALIENVAULT_EXCLUDED_PULSE_INDICATOR_TYPES": "FileHash-MD5,FileHash-SHA1", + "ALIENVAULT_ENABLE_RELATIONSHIPS": "true", + "ALIENVAULT_ENABLE_ATTACK_PATTERNS_INDICATES": "false", + "ALIENVAULT_INTERVAL_SEC": "1800", + "ALIENVAULT_DEFAULT_X_OPENCTI_SCORE": "50", + "ALIENVAULT_X_OPENCTI_SCORE_IP": "60", + "ALIENVAULT_X_OPENCTI_SCORE_DOMAIN": "70", + "ALIENVAULT_X_OPENCTI_SCORE_HOSTNAME": "75", + "ALIENVAULT_X_OPENCTI_SCORE_EMAIL": "70", + "ALIENVAULT_X_OPENCTI_SCORE_FILE": "85", + "ALIENVAULT_X_OPENCTI_SCORE_URL": "80", + "ALIENVAULT_X_OPENCTI_SCORE_MUTEX": "60", + "ALIENVAULT_X_OPENCTI_SCORE_CRYPTOCURRENCY_WALLET": "80", + }, +) + +_add_connector_test_params( + name="cisa-kev", + connector_name="cisa-kev", + charm_config={ + "connector-scope": "cisa", + "connector-run-and-terminate": False, + "connector-log-level": "error", + "connector-duration-period": "P2D", + "cisa-catalog-url": ( + "https://www.cisa.gov/sites/default/files/feeds/" + "known_exploited_vulnerabilities.json" + ), + "cisa-create-infrastructures": False, + "cisa-tlp": "TLP:CLEAR", + }, + environment={ + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "CONNECTOR_NAME": "opencti-cisa-kev-connector", + "CONNECTOR_SCOPE": "cisa", + "CONNECTOR_RUN_AND_TERMINATE": "false", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_DURATION_PERIOD": "P2D", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "CISA_CATALOG_URL": ( + "https://www.cisa.gov/sites/default/files/feeds/" + "known_exploited_vulnerabilities.json" + ), + "CISA_CREATE_INFRASTRUCTURES": "false", + "CISA_TLP": "TLP:CLEAR", + }, +) + +_add_connector_test_params( + name="crowdstrike", + connector_name="crowdstrike", + charm_config={ + "connector-log-level": "error", + "connector-duration-period": "PT30M", + "crowdstrike-base-url": "https://api.crowdstrike.com", + "crowdstrike-client-id": "ChangeMe", + "crowdstrike-client-secret": "ChangeMe", + "crowdstrike-tlp": "Amber", + "crowdstrike-create-observables": "true", + "crowdstrike-create-indicators": "true", + "crowdstrike-scopes": "actor,report,indicator,yara_master", + "crowdstrike-actor-start-timestamp": 0, + "crowdstrike-report-start-timestamp": 0, + "crowdstrike-report-status": "New", + "crowdstrike-report-include-types": "notice,tipper,intelligence report,periodic report", + "crowdstrike-report-type": "threat-report", + "crowdstrike-report-target-industries": "", + "crowdstrike-report-guess-malware": "false", + "crowdstrike-indicator-start-timestamp": 0, + "crowdstrike-indicator-exclude-types": "hash_ion,hash_md5,hash_sha1", + # undocumented configuration + # "crowdstrike-default-x-opencti-score": 50, + "crowdstrike-indicator-low-score": 40, + "crowdstrike-indicator-low-score-labels": "MaliciousConfidence/Low", + "crowdstrike-indicator-medium-score": 60, + "crowdstrike-indicator-medium-score-labels": "MaliciousConfidence/Medium", + "crowdstrike-indicator-high-score": 80, + "crowdstrike-indicator-high-score-labels": "MaliciousConfidence/High", + "crowdstrike-indicator-unwanted-labels": "", + }, + environment={ + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "CONNECTOR_NAME": "opencti-crowdstrike-connector", + "CONNECTOR_SCOPE": "crowdstrike", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "CONNECTOR_DURATION_PERIOD": "PT30M", + "CROWDSTRIKE_BASE_URL": "https://api.crowdstrike.com", + "CROWDSTRIKE_CLIENT_ID": "ChangeMe", + "CROWDSTRIKE_CLIENT_SECRET": "ChangeMe", + "CROWDSTRIKE_TLP": "Amber", + "CROWDSTRIKE_CREATE_OBSERVABLES": "true", + "CROWDSTRIKE_CREATE_INDICATORS": "true", + "CROWDSTRIKE_SCOPES": "actor,report,indicator,yara_master", + "CROWDSTRIKE_ACTOR_START_TIMESTAMP": "0", + "CROWDSTRIKE_REPORT_START_TIMESTAMP": "0", + "CROWDSTRIKE_REPORT_STATUS": "New", + "CROWDSTRIKE_REPORT_INCLUDE_TYPES": "notice,tipper,intelligence report,periodic report", + "CROWDSTRIKE_REPORT_TYPE": "threat-report", + "CROWDSTRIKE_REPORT_TARGET_INDUSTRIES": "", + "CROWDSTRIKE_REPORT_GUESS_MALWARE": "false", + "CROWDSTRIKE_INDICATOR_START_TIMESTAMP": "0", + "CROWDSTRIKE_INDICATOR_EXCLUDE_TYPES": "hash_ion,hash_md5,hash_sha1", + # "CROWDSTRIKE_DEFAULT_X_OPENCTI_SCORE": "50", + "CROWDSTRIKE_INDICATOR_LOW_SCORE": "40", + "CROWDSTRIKE_INDICATOR_LOW_SCORE_LABELS": "MaliciousConfidence/Low", + "CROWDSTRIKE_INDICATOR_MEDIUM_SCORE": "60", + "CROWDSTRIKE_INDICATOR_MEDIUM_SCORE_LABELS": "MaliciousConfidence/Medium", + "CROWDSTRIKE_INDICATOR_HIGH_SCORE": "80", + "CROWDSTRIKE_INDICATOR_HIGH_SCORE_LABELS": "MaliciousConfidence/High", + "CROWDSTRIKE_INDICATOR_UNWANTED_LABELS": "", + }, +) + + +_add_connector_test_params( + name="cyber-campaign", + connector_name="cyber-campaign", + charm_config={ + "connector-scope": "report", + "connector-run-and-terminate": False, + "connector-log-level": "error", + "cyber-monitor-github-token": "", + "cyber-monitor-from-year": 2018, + "cyber-monitor-interval": 4, + }, + environment={ + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "CONNECTOR_NAME": "opencti-cyber-campaign-connector", + "CONNECTOR_SCOPE": "report", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "CONNECTOR_RUN_AND_TERMINATE": "false", + "CONNECTOR_LOG_LEVEL": "error", + "CYBER_MONITOR_GITHUB_TOKEN": "", + "CYBER_MONITOR_FROM_YEAR": "2018", + "CYBER_MONITOR_INTERVAL": "4", + }, +) + +_add_connector_test_params( + name="export-file-csv", + connector_name="export-file-csv", + charm_config={ + "connector-scope": "text/csv", + "connector-confidence-level": 100, + "connector-log-level": "error", + "export-file-csv-delimiter": ";", + }, + environment={ + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "CONNECTOR_NAME": "opencti-export-file-csv-connector", + "CONNECTOR_SCOPE": "text/csv", + "CONNECTOR_TYPE": "INTERNAL_EXPORT_FILE", + "CONNECTOR_CONFIDENCE_LEVEL": "100", + "CONNECTOR_LOG_LEVEL": "error", + "EXPORT_FILE_CSV_DELIMITER": ";", + }, +) + +_add_connector_test_params( + name="export-file-stix", + connector_name="export-file-stix", + charm_config={ + "connector-scope": "application/vnd.oasis.stix+json", + "connector-confidence-level": 100, + "connector-log-level": "error", + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-export-file-stix-connector", + "CONNECTOR_SCOPE": "application/vnd.oasis.stix+json", + "CONNECTOR_CONFIDENCE_LEVEL": "100", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "INTERNAL_EXPORT_FILE", + }, +) + +_add_connector_test_params( + name="export-file-stix-minimal", + connector_name="export-file-stix", + charm_config={"connector-scope": "application/json"}, + environment={ + "CONNECTOR_LOG_LEVEL": "info", + "CONNECTOR_NAME": "opencti-export-file-stix-connector", + "CONNECTOR_SCOPE": "application/json", + "CONNECTOR_TYPE": "INTERNAL_EXPORT_FILE", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + }, +) + +_add_connector_test_params( + name="export-file-txt", + connector_name="export-file-txt", + charm_config={ + "connector-scope": "text/plain", + "connector-confidence-level": 100, + "connector-log-level": "error", + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-export-file-txt-connector", + "CONNECTOR_TYPE": "INTERNAL_EXPORT_FILE", + "CONNECTOR_SCOPE": "text/plain", + "CONNECTOR_CONFIDENCE_LEVEL": "100", + "CONNECTOR_LOG_LEVEL": "error", + }, +) + +_add_connector_test_params( + name="import-document", + connector_name="import-document", + charm_config={ + "connector-validate-before-import": True, + "connector-scope": "application/pdf,text/plain,text/html,text/markdown", + "connector-auto": False, + "connector-only-contextual": False, + "connector-confidence-level": 100, + "connector-log-level": "error", + "import-document-create-indicator": False, + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-import-document-connector", + "CONNECTOR_VALIDATE_BEFORE_IMPORT": "true", + "CONNECTOR_SCOPE": "application/pdf,text/plain,text/html,text/markdown", + "CONNECTOR_AUTO": "false", + "CONNECTOR_ONLY_CONTEXTUAL": "false", + "CONNECTOR_CONFIDENCE_LEVEL": "100", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "INTERNAL_IMPORT_FILE", + "IMPORT_DOCUMENT_CREATE_INDICATOR": "false", + }, +) + +_add_connector_test_params( + name="import-file-stix", + connector_name="import-file-stix", + charm_config={ + "connector-validate-before-import": True, + "connector-scope": "application/json,application/xml", + "connector-auto": False, + "connector-confidence-level": 15, + "connector-log-level": "error", + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-import-file-stix-connector", + "CONNECTOR_VALIDATE_BEFORE_IMPORT": "true", + "CONNECTOR_SCOPE": "application/json,application/xml", + "CONNECTOR_AUTO": "false", + "CONNECTOR_CONFIDENCE_LEVEL": "15", + "CONNECTOR_TYPE": "INTERNAL_IMPORT_FILE", + "CONNECTOR_LOG_LEVEL": "error", + }, +) + +_add_connector_test_params( + name="malwarebazaar", + connector_name="malwarebazaar", + charm_config={ + "connector-log-level": "error", + "malwarebazaar-recent-additions-api-url": "https://mb-api.abuse.ch/api/v1/", + "malwarebazaar-recent-additions-cooldown-seconds": 300, + "malwarebazaar-recent-additions-include-tags": "exe,dll,docm,docx,doc,xls,xlsx,xlsm,js", + "malwarebazaar-recent-additions-include-reporters": "", + "malwarebazaar-recent-additions-labels": "malware-bazaar", + "malwarebazaar-recent-additions-labels-color": "#54483b", + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-malwarebazaar-connector", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "MALWAREBAZAAR_RECENT_ADDITIONS_API_URL": "https://mb-api.abuse.ch/api/v1/", + "MALWAREBAZAAR_RECENT_ADDITIONS_COOLDOWN_SECONDS": "300", + "MALWAREBAZAAR_RECENT_ADDITIONS_INCLUDE_TAGS": "exe,dll,docm,docx,doc,xls,xlsx,xlsm,js", + "MALWAREBAZAAR_RECENT_ADDITIONS_INCLUDE_REPORTERS": "", + "MALWAREBAZAAR_RECENT_ADDITIONS_LABELS": "malware-bazaar", + "MALWAREBAZAAR_RECENT_ADDITIONS_LABELS_COLOR": "#54483b", + }, +) + +_add_connector_test_params( + name="misp-feed", + connector_name="misp-feed", + charm_config={ + "connector-scope": "misp-feed", + "connector-run-and-terminate": False, + "connector-log-level": "error", + "misp-feed-url": "https://changeme.com/misp-feed", + "misp-feed-ssl-verify": True, + "misp-feed-import-from-date": "2000-01-01", + "misp-feed-create-reports": True, + "misp-feed-report-type": "misp-event", + "misp-feed-create-indicators": True, + "misp-feed-create-observables": True, + "misp-feed-create-object-observables": True, + "misp-feed-create-tags-as-labels": True, + "misp-feed-guess-threat-from-tags": False, + "misp-feed-author-from-tags": False, + "misp-feed-import-to-ids-no-score": True, + "misp-feed-import-unsupported-observables-as-text": False, + "misp-feed-import-unsupported-observables-as-text-transparent": True, + "misp-feed-import-with-attachments": False, + "misp-feed-interval": 5, + "misp-feed-source-type": "url", + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-misp-feed-connector", + "CONNECTOR_SCOPE": "misp-feed", + "CONNECTOR_RUN_AND_TERMINATE": "false", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "MISP_FEED_URL": "https://changeme.com/misp-feed", + "MISP_FEED_SSL_VERIFY": "true", + "MISP_FEED_IMPORT_FROM_DATE": "2000-01-01", + "MISP_FEED_CREATE_REPORTS": "true", + "MISP_FEED_REPORT_TYPE": "misp-event", + "MISP_FEED_CREATE_INDICATORS": "true", + "MISP_FEED_CREATE_OBSERVABLES": "true", + "MISP_FEED_CREATE_OBJECT_OBSERVABLES": "true", + "MISP_FEED_CREATE_TAGS_AS_LABELS": "true", + "MISP_FEED_GUESS_THREAT_FROM_TAGS": "false", + "MISP_FEED_AUTHOR_FROM_TAGS": "false", + "MISP_FEED_IMPORT_TO_IDS_NO_SCORE": "true", + "MISP_FEED_IMPORT_UNSUPPORTED_OBSERVABLES_AS_TEXT": "false", + "MISP_FEED_IMPORT_UNSUPPORTED_OBSERVABLES_AS_TEXT_TRANSPARENT": "true", + "MISP_FEED_IMPORT_WITH_ATTACHMENTS": "false", + "MISP_FEED_INTERVAL": "5", + "MISP_FEED_SOURCE_TYPE": "url", + }, +) + +_add_connector_test_params( + name="mitre", + connector_name="mitre", + charm_config={ + "connector-scope": ( + "tool,report,malware,identity,campaign," + "intrusion-set,attack-pattern,course-of-action," + "x-mitre-data-source,x-mitre-data-component," + "x-mitre-matrix,x-mitre-tactic,x-mitre-collection" + ), + "connector-run-and-terminate": False, + "connector-log-level": "error", + "mitre-remove-statement-marking": True, + "mitre-interval": 7, + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-mitre-connector", + "CONNECTOR_SCOPE": ( + "tool,report,malware,identity,campaign,intrusion-set," + "attack-pattern,course-of-action,x-mitre-data-source," + "x-mitre-data-component,x-mitre-matrix,x-mitre-tactic,x-mitre-collection" + ), + "CONNECTOR_RUN_AND_TERMINATE": "false", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "MITRE_REMOVE_STATEMENT_MARKING": "true", + "MITRE_INTERVAL": "7", + }, +) + +_add_connector_test_params( + name="sekoia", + connector_name="sekoia", + charm_config={ + "connector-scope": ( + "identity,attack-pattern,course-of-action,intrusion-set," + "malware,tool,report,location,vulnerability,indicator," + "campaign,infrastructure,relationship" + ), + "connector-log-level": "error", + "sekoia-api-key": "ChangeMe", + "sekoia-collection": "d6092c37-d8d7-45c3-8aff-c4dc26030608", + "sekoia-start-date": "2022-01-01", + "sekoia-create-observables": True, + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-sekoia-connector", + "CONNECTOR_SCOPE": ( + "identity,attack-pattern,course-of-action,intrusion-set," + "malware,tool,report,location,vulnerability,indicator," + "campaign,infrastructure,relationship" + ), + "CONNECTOR_LOG_LEVEL": "error", + "SEKOIA_API_KEY": "ChangeMe", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "SEKOIA_BASE_URL": "https://api.sekoia.io", + "SEKOIA_COLLECTION": "d6092c37-d8d7-45c3-8aff-c4dc26030608", + "SEKOIA_START_DATE": "2022-01-01", + "SEKOIA_CREATE_OBSERVABLES": "true", + }, +) + +_add_connector_test_params( + name="urlscan", + connector_name="urlscan", + charm_config={ + "connector-log-level": "error", + "connector-confidence-level": 40, + "connector-create-indicators": True, + "connector-tlp": "white", + "connector-labels": "Phishing,Phishfeed", + "connector-interval": 86400, + "connector-lookback": 3, + "connector-update-existing-data": True, + "urlscan-url": "https://urlscan.io/api/v1/pro/phishfeed?format=json", + "urlscan-api-key": "", + "urlscan-default-x-opencti-score": 50, + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-urlscan-connector", + "CONNECTOR_SCOPE": "threatmatch", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_CONFIDENCE_LEVEL": "40", + "CONNECTOR_CREATE_INDICATORS": "true", + "CONNECTOR_TLP": "white", + "CONNECTOR_LABELS": "Phishing,Phishfeed", + "CONNECTOR_INTERVAL": "86400", + "CONNECTOR_LOOKBACK": "3", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "CONNECTOR_UPDATE_EXISTING_DATA": "true", + "URLSCAN_URL": "https://urlscan.io/api/v1/pro/phishfeed?format=json", + "URLSCAN_API_KEY": "", + "URLSCAN_DEFAULT_X_OPENCTI_SCORE": "50", + }, +) + +_add_connector_test_params( + name="urlscan-enrichment", + connector_name="urlscan-enrichment", + charm_config={ + "connector-scope": "url,ipv4-addr,ipv6-addr", + "connector-auto": False, + "connector-log-level": "error", + "urlscan-enrichment-api-key": "ChangeMe", + "urlscan-enrichment-api-base-url": "https://urlscan.io/api/v1/", + "urlscan-enrichment-import-screenshot": True, + "urlscan-enrichment-visibility": "public", + "urlscan-enrichment-search-filtered-by-date": ">now-1y", + "urlscan-enrichment-max-tlp": "TLP:AMBER", + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-urlscan-enrichment-connector", + "CONNECTOR_SCOPE": "url,ipv4-addr,ipv6-addr", + "CONNECTOR_AUTO": "false", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "INTERNAL_ENRICHMENT", + "URLSCAN_ENRICHMENT_API_KEY": "ChangeMe", + "URLSCAN_ENRICHMENT_API_BASE_URL": "https://urlscan.io/api/v1/", + "URLSCAN_ENRICHMENT_IMPORT_SCREENSHOT": "true", + "URLSCAN_ENRICHMENT_VISIBILITY": "public", + "URLSCAN_ENRICHMENT_SEARCH_FILTERED_BY_DATE": ">now-1y", + "URLSCAN_ENRICHMENT_MAX_TLP": "TLP:AMBER", + }, +) + +_add_connector_test_params( + name="virustotal-livehunt", + connector_name="virustotal-livehunt", + charm_config={ + "connector-scope": "StixFile,Indicator,Incident", + "connector-log-level": "error", + "virustotal-livehunt-notifications-api-key": "ChangeMe", + "virustotal-livehunt-notifications-interval-sec": 300, + "virustotal-livehunt-notifications-create-alert": True, + "virustotal-livehunt-notifications-extensions": "'exe,dll'", + "virustotal-livehunt-notifications-min-file-size": 1000, + "virustotal-livehunt-notifications-max-file-size": 52428800, + "virustotal-livehunt-notifications-max-age-days": 3, + "virustotal-livehunt-notifications-min-positives": 5, + "virustotal-livehunt-notifications-create-file": True, + "virustotal-livehunt-notifications-upload-artifact": False, + "virustotal-livehunt-notifications-create-yara-rule": True, + "virustotal-livehunt-notifications-delete-notification": False, + "virustotal-livehunt-notifications-filter-with-tag": '"mytag"', + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-virustotal-livehunt-connector", + "CONNECTOR_SCOPE": "StixFile,Indicator,Incident", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_API_KEY": "ChangeMe", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_INTERVAL_SEC": "300", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_CREATE_ALERT": "True", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_EXTENSIONS": "'exe,dll'", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_MIN_FILE_SIZE": "1000", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_MAX_FILE_SIZE": "52428800", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_MAX_AGE_DAYS": "3", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_MIN_POSITIVES": "5", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_CREATE_FILE": "True", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_UPLOAD_ARTIFACT": "False", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_CREATE_YARA_RULE": "True", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_DELETE_NOTIFICATION": "False", + "VIRUSTOTAL_LIVEHUNT_NOTIFICATIONS_FILTER_WITH_TAG": '"mytag"', + }, +) + + +_add_connector_test_params( + name="vxvault", + connector_name="vxvault", + charm_config={ + "connector-scope": "vxvault", + "connector-log-level": "error", + "vxvault-url": "https://vxvault.net/URL_List.php", + "vxvault-create-indicators": True, + "vxvault-interval": 3, + "vxvault-ssl-verify": False, + }, + environment={ + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "CONNECTOR_NAME": "opencti-vxvault-connector", + "CONNECTOR_SCOPE": "vxvault", + "CONNECTOR_LOG_LEVEL": "error", + "CONNECTOR_TYPE": "EXTERNAL_IMPORT", + "VXVAULT_URL": "https://vxvault.net/URL_List.php", + "VXVAULT_CREATE_INDICATORS": "true", + "VXVAULT_INTERVAL": "3", + "VXVAULT_SSL_VERIFY": "false", + }, +) + + +@pytest.mark.parametrize("connector_name, charm_config, environment", _CONNECTOR_TEST_PARAMS) +def test_connector_environment(connector_name, charm_config, environment): + """ + arrange: provide the connector charm with the required integrations and configurations. + act: simulate a config-changed event. + assert: the installed Pebble plan matches the expectation. + """ + name = f"opencti-{connector_name}-connector" + module = connector_name + charm_module = importlib.import_module(f"connectors.{_kebab_to_snake(module)}.src.charm") + charm_class = getattr(charm_module, _kebab_to_pascal(name) + "Charm") + ctx = ops.testing.Context(charm_class) + state_builder = ConnectorStateBuilder(name).add_opencti_connector_integration() + for config_key, config_value in charm_config.items(): + state_builder = state_builder.set_config(config_key, config_value) + state_in = state_builder.build() + state_out = ctx.run(ctx.on.config_changed(), state_in) + plan = state_out.get_container(name).plan.to_dict() + del plan["services"]["connector"]["environment"]["CONNECTOR_ID"] + assert plan == { + "services": { + "connector": { + "command": "bash /entrypoint.sh", + "environment": environment, + "on-failure": "restart", + "override": "replace", + "startup": "enabled", + } + } + } + + +def test_proxy_environment(monkeypatch): + """ + arrange: provide the connector charm with http proxy configured. + act: simulate a config-changed event. + assert: the installed Pebble plan matches the expectation. + """ + monkeypatch.setenv("JUJU_CHARM_HTTP_PROXY", "http://example.com") + monkeypatch.setenv("JUJU_CHARM_HTTPS_PROXY", "https://example.com") + monkeypatch.setenv("JUJU_CHARM_NO_PROXY", "localhost,127.0.0.1") + + ctx = ops.testing.Context(OpenctiExportFileStixConnectorCharm) + state_builder = ConnectorStateBuilder( + "opencti-export-file-stix-connector" + ).add_opencti_connector_integration() + state_builder = state_builder.set_config("connector-scope", "application/vnd.oasis.stix+json") + state_builder = state_builder.set_config("connector-confidence-level", 100) + state_in = state_builder.build() + state_out = ctx.run(ctx.on.config_changed(), state_in) + + plan = state_out.get_container("opencti-export-file-stix-connector").plan.to_dict() + del plan["services"]["connector"]["environment"]["CONNECTOR_ID"] + assert plan == { + "services": { + "connector": { + "command": "bash /entrypoint.sh", + "environment": { + "CONNECTOR_CONFIDENCE_LEVEL": "100", + "CONNECTOR_LOG_LEVEL": "info", + "CONNECTOR_NAME": "opencti-export-file-stix-connector", + "CONNECTOR_SCOPE": "application/vnd.oasis.stix+json", + "CONNECTOR_TYPE": "INTERNAL_EXPORT_FILE", + "HTTPS_PROXY": "https://example.com", + "HTTP_PROXY": "http://example.com", + "NO_PROXY": "localhost,127.0.0.1,opencti-endpoints.test-opencti-connector.svc", + "OPENCTI_TOKEN": "00000000-0000-0000-0000-000000000000", + "OPENCTI_URL": "http://opencti-endpoints.test-opencti-connector.svc:8080", + "http_proxy": "http://example.com", + "https_proxy": "https://example.com", + "no_proxy": "localhost,127.0.0.1,opencti-endpoints.test-opencti-connector.svc", + }, + "on-failure": "restart", + "override": "replace", + "startup": "enabled", + } + } + } diff --git a/tox.ini b/tox.ini index adf84c1..9517187 100644 --- a/tox.ini +++ b/tox.ini @@ -65,7 +65,8 @@ commands = # codespell {[vars]lib_path} codespell {toxinidir} --skip {toxinidir}/.git --skip {toxinidir}/.tox \ --skip {toxinidir}/build --skip {toxinidir}/lib --skip {toxinidir}/venv \ - --skip {toxinidir}/.mypy_cache --skip {toxinidir}/icon.svg + --skip {toxinidir}/.mypy_cache --skip {toxinidir}/icon.svg \ + --skip {toxinidir}/src/opencti.graphql # pflake8 wrapper supports config from pyproject.toml pflake8 {[vars]all_path} --ignore=W503 isort --check-only --diff {[vars]all_path} @@ -113,18 +114,17 @@ deps = pytest pytest-asyncio pytest-operator + PyYAML -r{toxinidir}/requirements.txt commands = pytest -v --tb native --ignore={[vars]tst_path}unit --log-cli-level=INFO -s {posargs} -[testenv:src-docs] -allowlist_externals=sh -setenv = - PYTHONPATH = {toxinidir}:{toxinidir}/lib:{[vars]src_path} -description = Generate documentation for src +[testenv:generate-connectors] deps = - lazydocs - -r{toxinidir}/requirements.txt + jinja2 + requests + markdown + PyYAML + beautifulsoup4 commands = - ; can't run lazydocs directly due to needing to run it on src/* which produces an invocation error in tox - sh generate-src-docs.sh + python3 scripts/gen_connector_charm.py