diff --git a/changelog/index.html b/changelog/index.html index d741045..69b8c28 100644 --- a/changelog/index.html +++ b/changelog/index.html @@ -2414,7 +2414,7 @@

+ + + @@ -1366,6 +1379,19 @@ Additional configuration + + @@ -1385,7 +1411,7 @@

Quick Start

-

The most straight forward and recommended way to use IRIS is with Docker. This is presented here.

+

The most straightforward and recommended way to use IRIS is with Docker. This is presented here.

Disclaimer

IRIS is in its early stage. It can already be used in production, but please set backups of the database and DO NOT expose the interface on the Internet. @@ -1393,13 +1419,13 @@

Quick Start

Pre-requisites

Hardware

-

IRIS is not very resourceful and can be run on a small laptop (4 cores, 8Gb of RAM). However, for large organization and heavy usage, -it will need to be greatly scaled up.
-We don't have benchmarks yet but keep in mind that the database can grow rapidly and modules can be resourceful depending on their purposes.

+

IRIS does not require a lot of resources, and it can be run on a small laptop (4 cores, 8Gb of RAM). However, for large a organization and heavy usage, +it will need to be significantly scaled up.
+We don't have benchmarks yet, but keep in mind that the database can grow rapidly and modules can require more resources depending on their purposes.

Docker

Docker and docker compose are needed to build and run the project. Depending on the OS you will find all the information to install them on the official website of Docker.

-

The platform is officially support on most Linux and MacOS. While it should work on Windows, some path needed by the dockers to store permanent files might need to be changed in the dockerfiles.

+

The platform is officially supported on most Linux and MacOS. While it should work on Windows, some path needed by the containers to store permanent files might need to be changed in the dockerfiles.

Versioning

Starting from version 2.0.0, Iris is following the Semantic Versioning 2.0 guidelines.
The code ready for production is always tagged with a version number. @@ -1455,13 +1481,17 @@

Build and Run

IRIS Structure

Additional configuration

Please see configuration for more details.

+

Kubernetes

+

For enterprises wishing to run their instance of IRIS, utilizing the projects official Helm charts and/or Kustomize manifests, allows them to significantly enhance their deployment and management, presenting a powerful solution to streamline their IRIS deployment and management processes, efficiently running across a cluster of machines, ensuring high availability and seamless scaling as demand fluctuates.

+

The deploy directory in the iris-web GitHub repository provides a practical starting point for deploying IRIS on their preferred managed k8s platform. We've created two variants: eks and gke, feel free to customize each with your own values.

+

For more details, please visit the deploy directory on GitHub: deploy


Last update: - 2023-11-29 + 2023-12-30
diff --git a/operations/access_control/authentication/index.html b/operations/access_control/authentication/index.html index 647dcf6..bab5d41 100644 --- a/operations/access_control/authentication/index.html +++ b/operations/access_control/authentication/index.html @@ -1456,7 +1456,7 @@

Changing a lost password

  • Generate the hash of the new password with Python BCrypt in Python prompt

    import bcrypt
    -print(bcrypt.hashpw(<new_password>.encode('utf-8'), bcrypt.gensalt())
    +print(bcrypt.hashpw('<new_password>'.encode('utf-8'), bcrypt.gensalt()))
     
  • @@ -1466,6 +1466,9 @@

    Changing a lost password

    / # psql postgres=# \c iris_db postgres=# UPDATE "user" SET password = '<hash>' WHERE "user".name = 'administrator'; +postgres=# \q +exit +exit
  • @@ -1484,7 +1487,7 @@

    Settings

    docker-compose restart app
     

    Setting up LDAP for the first runtime of IRIS

    -

    To set up LDAP without having run IRIS priorly, and as the app needs the accounts to be created first before using LDAP, one have to set the IRIS_ADM_EMAIL environment with the LDAP Email of the administrator user.

    +

    To set up LDAP without having run IRIS priorly, and as the app needs the accounts to be created first before using LDAP, one has to set the IRIS_ADM_EMAIL environment with the LDAP Email of the administrator user.

    Example of LDAP configuration for first run
    IRIS_AUTHENTICATION_TYPE=ldap
     
     ## IP address or FQDN of the ldap server
    @@ -1576,7 +1579,7 @@ 

    LDAP certificates

    Last update: - 2023-06-26 + 2023-12-30
    diff --git a/operations/access_control/groups/index.html b/operations/access_control/groups/index.html index f34624e..0661ec8 100644 --- a/operations/access_control/groups/index.html +++ b/operations/access_control/groups/index.html @@ -1465,7 +1465,7 @@

    Groups

    Setting up a new group

    Head to the Access Control page and click Add group.

    Create new group

    -

    Fill the form. All the fields can be change later on. The field Group name has to be unique on the IRIS instance.
    +

    Fill the form. All the fields can be changed later on. The field Group name has to be unique on the IRIS instance.
    Access control and members can be set once the group is created.

    Configuring the group

    The group can be configured once created by clicking on it in the list.
    @@ -1474,24 +1474,24 @@

    Users

    Adding users to a group

    To add users to the group, go to the Members tab and click Manage. Create new group 3

    -

    The users manager should load and offers a list of users that can be added to the group. Select all the users you want to add to the group and press save.

    +

    The User Manager should load and offers a list of users that can be added to the group. Select all the users you want to add to the group and press Save.

    Create new group 4

    Permissions computation

    -

    When a user is added/removed to a group, its effective cases access are recomputed. Depending on the amount of cases and users added/removed this can take some time. +

    When a user is added/removed to a group, its effective cases access are recomputed. Depending on the number of cases and users added/removed this can take some time. This process helps reducing the DB load when using IRIS during normal operation.

    Removing users from a group

    To remove users from the group, go to the Members tab and click Manage. Create new group 3

    -

    The users manager should load and present a list of both users already in the group as well as the ones that can be added. To remove one or more users, un-tick them from the list and press Save.

    -

    Alternatively, a user can be directly removed from withing the group manager. Click on the red trash next to the user to remove and confirm the deletion. +

    The User Manager should load and present a list of both users already in the group as well as the ones that can be added. To remove one or more users, un-tick them from the list and press Save.

    +

    Alternatively, a user can be directly removed from within the group manager. Click on the red trash next to the user to remove and confirm the deletion. Remove user from group

    Cases

    Adding cases to the group

    -

    Access to one or multiple existing cases can be granted to a group. From within the group manager, go to the Cases access tab and click Set case access.
    +

    Access to one or multiple existing cases can be granted to a group. From within the Group Manager, go to the Cases Access tab and click Set case access.
    Add case to group

    -

    The cases access manager loads and gives the possibility to set the access to one or more cases.
    +

    The Cases Access Manager loads and gives the possibility to set the access to one or more cases.
    Add case to org

    Three choices of access are offered:

    -

    A user can be in one or multiple groups. The effective case access control of a user is deducted from its groups membership and its own cases access control.
    -The effective permissions are deducted from its groups membership.

    +

    A user can be in one or multiple groups. The effective case access control of a user is deduced from its groups membership and its own cases access control.
    +The effective permissions are deduced from its groups membership.

    Cases access control overview

    Cases access control offer three levels:

    @@ -1416,14 +1416,14 @@

    Adding a user

    Create new user

    Editing a user

    -

    A user can be edited by clicking on its name or ID in Advanced > Access Control > Users. A window opens and display the user's information. Tabs at the top allows to configure multiple settings related to the user.

    +

    A user can be edited by clicking on its name or ID in Advanced > Access Control > Users. A window opens and display the user's information. Tabs at the top allow to configure multiple settings related to the user.

    Setting permissions

    Permissions of a user cannot be set directly. They are inherited from the groups membership. The tab Permissions only displays the permissions the user has from its groups memberships. See Groups for more info.

    Setting groups

    Groups can be set by clicking on the Groups tab of the user's window and then Manage.

    Manage user

    -

    A new window appear with the possibility to select the groups the user should belong to. +

    A new window appears with the possibility to select the groups the user should belong to. Manage user

    After saving, the permissions of the user are updated. This can be verified in the Permissions tab.
    Manage user

    @@ -1431,7 +1431,7 @@

    Setting cases access

    Cases access are usually set through groups membership. However for granularity they can be set per user.
    To set the access of a user on a case, click on the Cases access tab of the user's window and then Set case access.

    Manage user

    -

    As for the Groups, a selector appear and allows to select one or multiple cases and the access to associate.
    +

    As for the Groups, a selector appears and allows to select one or multiple cases and the access to associate.
    Manage user

    Info

    @@ -1458,7 +1458,7 @@

    Deleting a user

    Last update: - 2023-05-15 + 2023-07-01
    diff --git a/operations/alerts/index.html b/operations/alerts/index.html index aaec4cf..5b63281 100644 --- a/operations/alerts/index.html +++ b/operations/alerts/index.html @@ -482,8 +482,8 @@
  • - - Umerge alerts from a case + + Unmerge alerts from a case
  • @@ -1366,8 +1366,8 @@
  • - - Umerge alerts from a case + + Unmerge alerts from a case
  • @@ -1407,7 +1407,7 @@

    Alerts

    Introduced in IRIS v2.1.0

    -

    Alerts can be feeded directly into IRIS using the Alerts API.
    +

    Alerts can be fed directly into IRIS using the Alerts API.
    Any source can inject alerts into IRIS, as long as it can send HTTP requests and respects the alert format.

    A service account with the alert_read and alert_write permission can be used to send alerts to IRIS.

    @@ -1420,13 +1420,13 @@

    Viewing alerts

    Each alert can be expanded to show more details.

    Alerts assignment

    Alerts can be assigned to analysts. This can be done directly from the alert view.

    -

    To self assign an unassigned alert, click on the hand icon on the left.

    +

    To self-assign an unassigned alert, click on the hand icon on the left.

    Alerts

    Clicking again on the hand icon will prompt with a list of analysts to assign the alert to.

    -

    The right button Assign when hovering an alert can also be used to assign the alert to an analyst.

    +

    The right button Assign, when hovering above an alert, can also be used to assign the alert to an analyst.

    Merge / escalation operations

    Creating cases from alerts

    -

    Alerts can be escalated/merged into a new case. When hovering an alert, a Merge button will appear.

    +

    Alerts can be escalated/merged into a new case. When hovering above an alert, a Merge button will appear.

    Alerts

    Once clicked, a new window appears, requesting additional information. In this window, the analyst can:

    Merge alerts into an existing case

    -

    Alerts can also be escalated/merged into an existing case. When hovering an alert, a Merge button will appear.

    -

    Once clicked a new window appears, requesting additional information. The button Merge into existing case needs to be clicked.
    +

    Alerts can also be escalated/merged into an existing case. When hovering above an alert, a Merge button will appear.

    +

    Once clicked, a new window appears requesting additional information. The button Merge into existing case needs to be clicked.
    A new dropdown appears and allows to select the case to merge the alert into.

    Similar to the case creation, the analyst can:

    -

    The selections IOCs and assets are then added to the selected case.

    -

    Umerge alerts from a case

    +

    The selected IOCs and assets are then added to the selected case.

    +

    Unmerge alerts from a case

    Alerts can be unmerged from a case.

    Info

    When unmerging an alert, the alert is not deleted. It is only removed from the case. The alert state is not changed.
    -The IOC and assets are not removed from the case.

    +The IOCs and assets are not removed from the case.

    When a case is merged, a new link appears on the alert and mentions the case it was merged into.
    Clicking on this link allows to browse the case or to unmerge the alert.

    @@ -1475,7 +1475,7 @@

    Alerts relationships

    Last update: - 2023-05-16 + 2023-07-01
    diff --git a/operations/api/index.html b/operations/api/index.html index ba8ae10..f75eca3 100644 --- a/operations/api/index.html +++ b/operations/api/index.html @@ -1341,11 +1341,11 @@

    API

    API Keys

    The first step is to obtain an API key. Each user is automatically attributed one when it is created.
    -It can be found on the left panel, under username and My Settings.

    +It can be found on the left panel, under username and My Settings.

    Access Token

    Token exposure

    -

    In case the token is exposed and needs to be change, a new one can be generated with the Renew option. +

    In case the token is exposed and needs to be changed, a new one can be generated with the Renew option. Renewing a token revokes the previous.

    References

    @@ -1433,7 +1433,7 @@

    How to use

    Last update: - 2023-08-03 + 2023-12-30 diff --git a/operations/upgrades/index.html b/operations/upgrades/index.html index 1fcfe98..cbde12c 100644 --- a/operations/upgrades/index.html +++ b/operations/upgrades/index.html @@ -2184,7 +2184,7 @@

    v1.4.0

    Last update: - 2023-11-29 + 2023-12-30 diff --git a/search/search_index.json b/search/search_index.json index b48b365..be84bdf 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

    This documentation serves as a comprehensive guide to the IRIS web application operations, modules, and development.

    If you're new to IRIS, we recommend starting with our Getting Started guide to learn the basics.

    For those who want to try out IRIS easily, we offer a free demonstration instance of the rolling beta version here.

    Our documentation is constantly evolving, so if you don't find what you're looking for, please contact us so we can add the missing piece.

    "},{"location":"#what-is-iris","title":"What is IRIS?","text":"

    IRIS is a collaborative platform for incident response analysts that helps to share investigations at a technical level. It's a web application that can be installed on a fixed-server or on a laptop for roaming investigations where internet might not be available.

    IRIS was born out of the struggle to share long and complex investigations among analysts.

    The project is available on our Github organization.

    Disclaimer

    IRIS is still in its early stages. It can already be used in production, but please set backups of the database and DO NOT expose the interface on the Internet. We highly recommend the use of a private dedicated and secured network.

    "},{"location":"changelog/","title":"Changelog","text":"

    For upgrades instructions, please see the Upgrades page.

    "},{"location":"changelog/#v237-december-14-2023","title":"v2.3.7 December 14, 2023","text":""},{"location":"changelog/#whats-changed","title":"What's Changed","text":"

    Fixed

    Improved

    Full Changelog

    "},{"location":"changelog/#v236-december-7-2023","title":"v2.3.6 December 7, 2023","text":""},{"location":"changelog/#whats-changed_1","title":"What's Changed","text":"

    Fixed

    Full Changelog

    "},{"location":"changelog/#v235-november-30-2023","title":"v2.3.5 November 30, 2023","text":""},{"location":"changelog/#whats-changed_2","title":"What's Changed","text":"

    Fixed

    Full Changelog

    "},{"location":"changelog/#v234-november-29-2023","title":"v2.3.4 November 29, 2023","text":"

    A severe bug has been introduced in this version. Please upgarde to v2.3.5.

    "},{"location":"changelog/#whats-changed_3","title":"What's Changed","text":"

    Added

    Fixed

    \u2757 The layout of the reporting has slightly changed. Custom report templates might not work anymore. You can use https://<server>/case/export?cid=<case_id> to get all the possible fields.

    Full Changelog

    "},{"location":"changelog/#v233-october-5-2023","title":"v2.3.3 October 5, 2023","text":""},{"location":"changelog/#whats-changed_4","title":"What's Changed","text":"

    Fixed

    @Scriptception made their first contribution in 313

    Full Changelog

    "},{"location":"changelog/#v232-august-2-2023","title":"v2.3.2 August 2, 2023","text":""},{"location":"changelog/#whats-changed_5","title":"What's Changed","text":"

    Fixed

    Patches a critical issue corrupting files uploaded to the DataStore via the IOC option or when a password is set

    Full Changelog

    "},{"location":"changelog/#v231-july-23-2023","title":"v2.3.1 July 23, 2023","text":""},{"location":"changelog/#whats-changed_6","title":"What's Changed","text":"

    Improved

    Fixed

    Full Changelog

    "},{"location":"changelog/#v230-july-09-2023","title":"v2.3.0 July 09, 2023","text":""},{"location":"changelog/#whats-changed_7","title":"What's Changed","text":"

    Added

    Fixed

    Full Changelog

    "},{"location":"changelog/#v223-june-19-2023","title":"v2.2.3 June 19, 2023","text":""},{"location":"changelog/#whats-changed_8","title":"What's Changed","text":"

    Added

    Fixed

    Full Changelog

    "},{"location":"changelog/#v222-may-30-2023","title":"v2.2.2 May 30, 2023","text":""},{"location":"changelog/#whats-changed_9","title":"What's Changed","text":"

    Added

    Fixed - Delete character escaping for passwords by @juadde in #253 - Case template of tasks without tags - Shortening of case names during updates - Bad handling of certain requests without CID - Deletion of assets related to alerts once merge into a case

    Full Changelog

    "},{"location":"changelog/#v221-may-24-2023","title":"v2.2.1 May 24, 2023","text":""},{"location":"changelog/#whats-changed_10","title":"What's Changed","text":"

    Note 1: This version contains a security fix for iris-web (see CVE-2023-30615) Note 2: on_postload_case_info_update hook has been renamed to on_postload_case_update

    Added

    Fixed

    Full Changelog

    "},{"location":"changelog/#v220-may-22-2023","title":"v2.2.0 May 22, 2023","text":""},{"location":"changelog/#whats-changed_11","title":"What's Changed","text":"

    Added

    Fixes

    New Contributors

    Full Changelog

    "},{"location":"changelog/#v210-may-15-2023","title":"v2.1.0 May 15, 2023","text":"

    If you are using custom SSL certificates, please read the upgrade instructions when upgrading from previous versions.

    "},{"location":"changelog/#whats-changed_12","title":"What's Changed","text":"

    Added

    Fixed

    New Contributors

    Full Changelog

    "},{"location":"changelog/#v202-april-18-2023","title":"v2.0.2 April 18, 2023","text":""},{"location":"changelog/#whats-changed_13","title":"What's Changed","text":"

    Fixed * Update case_notes_db.py for bug fix #200 by @LoneWolf-96 in #208 * Do not escape_filter_chars for NTLM username by @juadde in #212 * docker-compose cleanup by @juadde in #213 * Listening port not being propagated in nginx docker

    New Contributors * @LoneWolf-96 made their first contribution in #208 * @juadde made their first contribution in #212

    Full Changelog

    "},{"location":"changelog/#v201-april-05-2023","title":"v2.0.1 April 05, 2023","text":""},{"location":"changelog/#whats-changed_14","title":"What's Changed","text":"

    Fixed [FIX] Additional table header in case management breaking proper loading of data in #206

    Full Changelog

    "},{"location":"changelog/#v200-march-26-2023","title":"v2.0.0 March 26, 2023","text":""},{"location":"changelog/#whats-changed_15","title":"What's Changed","text":"

    In addition to the features listed below, we are changing the way we are issuing releases. From now on, IRIS follows the Semantic Versioning 2.0 guidelines. The code ready for production is always tagged with a version number. alpha and beta versions are not production-ready.

    Do not use the master branch in production.

    A website with the current development version is also provided and freely accessible. It serves as a beta before public releases.

    Added

    Improved

    Fixed

    Full Changelog

    "},{"location":"changelog/#v145-june-9-2022","title":"v1.4.5 June 9, 2022","text":"

    What's Changed

    Full Changelog

    Notes: Changes are made to the Nginx docker to allow upload of big files, hence specific upgrades are needed and auto-updates is not yet supported for this version. Please see the upgrades instruction for more details.

    "},{"location":"changelog/#v144-may-18-2022","title":"v1.4.4 May 18, 2022","text":"

    What's Changed

    Full Changelog

    "},{"location":"changelog/#v143-may-13-2022","title":"v1.4.3 May 13, 2022","text":"

    What's changed

    Full Changelog

    "},{"location":"changelog/#v142-april-22-2022","title":"v1.4.2 April 22, 2022","text":"

    Improvements :

    Fixes :

    "},{"location":"changelog/#v141-april-8-2022","title":"v1.4.1 April 8, 2022","text":""},{"location":"changelog/#v140-april-6-2022","title":"v1.4.0 April 6, 2022","text":"

    A bug fixe exists for this version. See v1.4.3

    "},{"location":"changelog/#v131-march-19-2022","title":"v1.3.1 March 19, 2022","text":""},{"location":"changelog/#v130-january-24-2022","title":"v1.3.0 January 24, 2022","text":""},{"location":"changelog/#v121-december-31-2021","title":"v1.2.1 December 31, 2021","text":""},{"location":"contact/","title":"Contacting us","text":"

    You can directly contact us, should you need direct support, a demo, further information or anything else related to the project.

    contact@dfir-iris.org

    Discord

    Twitter

    "},{"location":"credits/","title":"Credits","text":"

    IRIS uses dozen of OS modules and this list is not exhaustive. If you developped something which is used in IRIS and does not figures here, you can contact us.

    "},{"location":"getting_started/","title":"Quick Start","text":"

    The most straight forward and recommended way to use IRIS is with Docker. This is presented here.

    Disclaimer

    IRIS is in its early stage. It can already be used in production, but please set backups of the database and DO NOT expose the interface on the Internet. We highly recommended the use of a private dedicated and secured network.

    "},{"location":"getting_started/#pre-requisites","title":"Pre-requisites","text":""},{"location":"getting_started/#hardware","title":"Hardware","text":"

    IRIS is not very resourceful and can be run on a small laptop (4 cores, 8Gb of RAM). However, for large organization and heavy usage, it will need to be greatly scaled up. We don't have benchmarks yet but keep in mind that the database can grow rapidly and modules can be resourceful depending on their purposes.

    "},{"location":"getting_started/#docker","title":"Docker","text":"

    Docker and docker compose are needed to build and run the project. Depending on the OS you will find all the information to install them on the official website of Docker.

    The platform is officially support on most Linux and MacOS. While it should work on Windows, some path needed by the dockers to store permanent files might need to be changed in the dockerfiles.

    "},{"location":"getting_started/#versioning","title":"Versioning","text":"

    Starting from version 2.0.0, Iris is following the Semantic Versioning 2.0 guidelines. The code ready for production is always tagged with a version number. alpha and beta versions are not production-ready.

    Do not use the master branch in production.

    "},{"location":"getting_started/#build-and-run","title":"Build and Run","text":"

    To build and run IRIS, follow these steps:

    1. Clone the iris-web repository:

      git clone https://github.com/dfir-iris/iris-web.git\ncd iris-web\n
    2. Check out the latest non-beta tagged version:

      git checkout v2.3.7\n
    3. Copy the environment file

      cp .env.model .env\n

      Warning

      The default configuration is suitable for testing only. To configure IRIS for production, see the configuration section.

    4. Build the Docker containers:

      docker-compose build\n
    5. Start IRIS:

      docker-compose up\n

    IRIS should now be available on the host interface, port 443, using HTTPS protocol by default. You can access it by navigating to https://hostip in your web browser.

    By default, an administrator account is created when IRIS is started for the first time. The password is printed in the console output. You can search for WARNING :: post_init :: create_safe_admin :: >>> in the logs to find the password. Running docker compose logs app | grep 'admin' should help to find it.

    If you want to define an admin password at the first start, you can create and define the environment variable IRIS_ADM_PASSWORD in the .env. This has no effect once the administrator account is created.

    Note that IRIS is split into five Docker services, each with a different role:

    Each service can be built independently, which is useful when developing. In this QuickStart, all services are built at once.

    "},{"location":"getting_started/#additional-configuration","title":"Additional configuration","text":"

    Please see configuration for more details.

    "},{"location":"resources/","title":"Resources","text":"

    This page is a collection of external resources to help you get started with IRIS and integrate it into your workflow. Please note that some of these resources may be outdated. If you want to add your own resources, please open a pull request or contact us.

    "},{"location":"resources/#blog-posts","title":"Blog posts","text":""},{"location":"resources/#iris-modules","title":"IRIS Modules","text":""},{"location":"resources/#videos","title":"Videos","text":""},{"location":"roadmap/","title":"Roadmap","text":"

    Note of 25-05-2023

    IRIS is growing both in code and interestes. To future-proof the project, we have decided to pause the development of new features and focus on the core functionalities and stability for a while. This includes a major refactoring of the codebase. We will still fix bugs and security issues.

    We do not provide a long-term roadmap to prevent any frustration and unmet expectations. It is constantly evolving with feedbacks we receive.

    We've thus moved it within a Github project. You can check it here.

    "},{"location":"security-advisories/","title":"Security Advisories","text":"

    This page lists all security advisories that have been published for the code released by DFIR-IRIS.

    "},{"location":"security-advisories/#cve-2023-50712-dec-18-2023","title":"CVE-2023-50712 Dec 18, 2023","text":"CVE ID Github ID Severity Impacted product CVE-2023-30615 GHSA-593r-747g-p92p Moderate - CVSS3 4.6/10 iris-web"},{"location":"security-advisories/#description","title":"Description","text":"

    A stored Cross-Site Scripting (XSS) vulnerability has been identified in iris-web, affecting multiple locations in versions prior to v2.3.7. The vulnerability may allow an attacker to inject malicious scripts into the application, which could then be executed when a user visits the affected locations. This could lead to unauthorized access, data theft, or other related malicious activities.

    An attacker need to be authenticated on the application to exploit this vulnerability.

    "},{"location":"security-advisories/#affected-versions","title":"Affected versions","text":""},{"location":"security-advisories/#fixed-versions","title":"Fixed versions","text":""},{"location":"security-advisories/#workarounds","title":"Workarounds","text":"

    No workaround is available.

    "},{"location":"security-advisories/#acknowledgment","title":"Acknowledgment","text":"

    Thanks to Leonard Rapp (G DATA Advanced Analytics GmbH) for the responsible disclosure.

    "},{"location":"security-advisories/#cve-2023-30615-may-24-2023","title":"CVE-2023-30615 May 24, 2023","text":"CVE ID Github ID Severity Impacted product CVE-2023-30615 GHSA-gc6j-6276-2m49 Moderate - CVSS3 4.6/10 iris-web"},{"location":"security-advisories/#description_1","title":"Description","text":"

    A stored Cross-Site Scripting (XSS) vulnerability has been identified in iris-web, affecting multiple locations in versions prior to v2.2.1. The vulnerability allows an attacker to inject malicious scripts into the application, which are then executed when a user visits the affected locations. This can lead to unauthorized access, data theft, or other related malicious activities.

    An attacker need to be authenticated on the application to exploit this vulnerability.

    "},{"location":"security-advisories/#affected-versions_1","title":"Affected versions","text":""},{"location":"security-advisories/#fixed-versions_1","title":"Fixed versions","text":""},{"location":"security-advisories/#workarounds_1","title":"Workarounds","text":"

    No workaround is available.

    "},{"location":"support_us/","title":"Support us","text":"

    As a free and open source project, we rely on the support of our community to continue development and improve our platform. If you find the platform useful and would like to help us sustain and grow, you may consider supporting us financially through OpenCollective.

    Support us

    "},{"location":"zqa/","title":"Q & A","text":""},{"location":"zqa/#general-questions","title":"General questions","text":""},{"location":"zqa/#which-version-should-i-install","title":"Which version should I install?","text":"

    The master branch is stable as all the development is done under the develop branch and merged once ready. To ease the identification, each new version is tagged and a new release is published. We recommend using these. git checkout <tagged_version>

    "},{"location":"zqa/#is-the-project-maintained","title":"Is the project maintained?","text":"

    Yes, IRIS is under heavy development. We are adding more and more features, led by feedbacks from the community.

    "},{"location":"zqa/#what-is-the-future-of-the-project","title":"What is the future of the project?","text":"

    We aim to make it evolve as much as possible with the help of the community. We have long term goals to integrate it seamlessly with project like MISP and other OS project, but we don't provide any commitment on how and when to avoid any unmet expectations. For a short term roadmap, you can head to the Github project.

    "},{"location":"zqa/#how-can-i-contact-the-dfir-iris-team","title":"How can I contact the DFIR-IRIS team?","text":"

    You can reach us on discord, Twitter or by email.

    "},{"location":"zqa/#cases","title":"Cases","text":""},{"location":"zqa/#can-i-recover-a-deleted-case","title":"Can I recover a deleted case?","text":"

    No. Cases are deleted from the database and changes are committed. There is no coming back unless you have made backups of the database (which we recommend).

    "},{"location":"zqa/#can-i-recover-a-deleted-case-object","title":"Can I recover a deleted case object?","text":"

    No. Every object such as IOCs, assets, events, notes, etc are immediately deleted from the database and changes are committed.

    "},{"location":"zqa/#can-i-add-a-new-asset-type","title":"Can I add a new asset type?","text":"

    Yes. With a user that have administrative rights, go to Advanced > Case Objects.

    "},{"location":"zqa/#can-i-add-a-new-ioc-type","title":"Can I add a new IOC type?","text":"

    Yes. Starting from v1.3.0, IOC types can be manipulated. Head to Advanced > Case Objects

    "},{"location":"zqa/#can-i-add-new-fields-to-case-objects-such-as-iocs-assets-etc","title":"Can I add new fields to case objects such as IOCs, Assets, etc?","text":"

    Yes. Starting from v1.4.0, all case objects can be extended thanks to custom attributes. With a user that have administrative rights, go to Advanced > Custom Attributes.

    "},{"location":"zqa/#can-i-search-into-custom-attributes-fields","title":"Can I search into custom attributes fields?","text":"

    Not for now. The searches in each case objects page are done client-side, and the attributes are not fetched. We will however implement a server side search in next releases.

    "},{"location":"zqa/#can-i-create-two-cases-with-the-same-name-for-the-same-customer","title":"Can I create two cases with the same name for the same customer?","text":"

    Yes. Cases are identified with a unique number, so they can have the same name.

    "},{"location":"zqa/#can-i-restrict-the-view-of-case-to-a-set-of-users","title":"Can I restrict the view of case to a set of users?","text":"

    Yes it is since v2.0.0. See Access control.

    "},{"location":"zqa/#can-i-change-the-name-or-customer-of-an-existing-case","title":"Can I change the name or customer of an existing case?","text":"

    Yes it is since v2.0.0.

    "},{"location":"zqa/#operations","title":"Operations","text":""},{"location":"zqa/#what-is-the-password-policy-can-it-be-changed","title":"What is the password policy? Can it be changed?","text":"

    Before v1.4.5, the password policy is hardcoded and cannot be changed. It should be 12 characters minimum and contains a capital letter and a number.

    "},{"location":"zqa/#can-i-change-my-profile-picture","title":"Can I change my profile picture?","text":"

    No, not for now. This wasn't a priority for us, it will be released in future versions.

    "},{"location":"zqa/#i-lost-the-administrator-password-can-i-recover-it","title":"I lost the administrator password, can I recover it?","text":"

    Passwords are hashed so they can't be recovered. But you can change it. Please see changing a lost password.

    "},{"location":"zqa/#can-i-delete-a-user","title":"Can I delete a user?","text":"

    No. To keep consistencies in the database, users unfortunately cannot be deleted if they have done some activities. You can however disable them to prevent them appearing in the UI and connecting to the plafeform.

    "},{"location":"zqa/#can-i-delete-a-customer","title":"Can I delete a customer?","text":"

    No. To keep consistencies in the database, customers unfortunately cannot be deleted if they are linked to cases.

    "},{"location":"zqa/#can-i-prevent-backrefs-of-assets-and-iocs","title":"Can I prevent backrefs of assets and IOCs?","text":"

    No. It might be possible in future versions but for now it is better to spin up a new instance for restricted cases. The backref is however automatically disabled for performance reasons, for cases with more than 300 assets. We are working on a more efficient way to backref.

    "},{"location":"zqa/#my-report-template-is-not-generated-and-generates-an-error","title":"My report template is not generated and generates an error","text":"

    Please triple check typos in tags as there is no fault tolerance. You can reach us in case of troubles.

    "},{"location":"zqa/#integration","title":"Integration","text":""},{"location":"zqa/#can-i-enrich-iocs-with-external-sources","title":"Can I enrich IOCs with external sources?","text":"

    Starting from v1.4.0, it is now possible to easily develop module to enrich case objects. A module Iris VT and IRIS MISP are already provided.

    "},{"location":"zqa/#is-there-an-api-client","title":"Is there an API client?","text":"

    Yes, you can find it on our Github.

    "},{"location":"zqa/#security","title":"Security","text":""},{"location":"zqa/#can-i-restrict-cases","title":"Can I restrict cases?","text":"

    Yes it is since v2.0.0. See Access control.

    "},{"location":"zqa/#can-i-expose-iris-on-the-internet","title":"Can I expose IRIS on the Internet?","text":"

    NO! Please don't. This platform should only be accessible in a restricted environment.

    "},{"location":"zqa/#i-found-a-security-issue-can-i-have-a-bounty","title":"I found a security issue, can I have a bounty?","text":"

    No - IRIS is free and open source so there is no bounty. Please report it as soon as possible so we can fix it.

    "},{"location":"zqa/#misc","title":"MISC","text":""},{"location":"zqa/#what-does-iris-stand-for","title":"What does IRIS stand for?","text":"

    Originally Incident Response Investigation System. But it can be whatever you want really.

    "},{"location":"development/","title":"Development","text":"

    This section is under construction and more elements will be added over time

    This documentation is not a detailed how-to develop IRIS. It gives some insights to help understand the basic code of the project and how to contribute.

    "},{"location":"development/#general-repositories-conventions","title":"General repositories conventions","text":""},{"location":"development/#branches","title":"Branches","text":"

    We are using the Gitflow Workflow to manage our git branches. In a nutshell :

    "},{"location":"development/#commits","title":"Commits","text":"

    The commits convention is the following :

    "},{"location":"development/#sections","title":"Sections","text":"

    The following sections are available in this documentation :

    "},{"location":"development/code-tips/","title":"Coding tips","text":""},{"location":"development/code-tips/#routes","title":"Routes","text":"

    IRIS does not defines a separate API for users, meaning the HTML pages are actually using the API themselves. Routes don't need to handle the authentication and roles. These are handles by wrappers (see snippets below).

    "},{"location":"development/code-tips/#page-route","title":"Page route","text":"

    A page returns an HTML content and should use the following code structure : Example of page route

    @blueprint.route('/a/good/route', methods=['GET']) # (1)\n@login_required # (2)\ndef view_a_good_route(caseid, url_redir):  # (3)\nif url_redir:\nreturn redirect(url_for('bluprintname.method_name', cid=caseid))  # (4)\n# route code \nreturn render_template(\"a_good_route.html\", variable_1=var_1, ...)  # (5)\n

    1. This defines which URI the route is handling as well as the methods it supports (ie GET, POST, etc). In IRIS, we try to limit one method per route.
    2. This defines the security of the endpoint. @login_required is used for users page and @admin_login_required is used for admin restricted pages.
    3. caseid and url_redir are variable provided by @login_required and @admin_login_required wraps. caseid indicates which case ID the user tried to access the route with. url_redir indicates the caseid provided wasn't valid and a redirection is needed.
    4. In case a redirection is needed, provide the URL to which the redirection should be done. It's often the page method itself except for modales.
    5. A page route needs to return an HTML template. variable_1 is a value that can be accessed from within the template itself. More variables can be added, or not at all.
    "},{"location":"development/code-tips/#api-route","title":"API route","text":"

    An API route returns a JSON content. Two types are pre-defined and should be used : Standard API returns

    response_success(msg=\"A success message\", data=<data associated with the success feedback>)\nresponse_error(msg=\"An error message\", data=<data associated with the error feedback>, status=<status code, by default 400>)\n

    Below is an example of standard API route. Example of page route

    @blueprint.route('/a/good/api_route', methods=['GET']) # (1)\n@api_login_required # (2)\ndef view_a_good_route(caseid):  # (3)\n# API route code \nreturn response_success(\"ok\", data=my_data_object)  # (4)\n

    1. This defines which URI the route is handling as well as the methods it supports (ie GET, POST, etc). In IRIS, we try to limit one method per route.
    2. This defines the security of the endpoint. @api_login_required is used for users API endpoints and @api_admin_required is used for admin restricted endpoints.
    3. caseid is provided @api_login_required and @api_admin_required wraps. It indicates which case ID the user tried to access the endpoint with.
    4. One of the standard return defined above.
    "},{"location":"development/db-migration/","title":"DB Migrations","text":"

    In case a DB migration is needed, you need to provide an alembic migration script.

    Test your migration

    Please try out your migration as this is an important piece of the upgrades. Spin up an old version of IRIS, input some data and then try to start your new version. Ensure that everything is migrated as expected.

    In a terminal and from within the IRIS virtual env :

    1. Go to source
    2. Issue the following command : alembic -c app/alembic.ini revision -m \"A few words to describe your changes\"

    This creates a new revision file source > app > alembic > versions. It's a Python file that basically describes what needs to be updated DB-wise. You can take example from the ones we already have generated in the same folder.

    Hint

    During your tests you might face the issue that Alembic does not apply your changes after you executed it once. It's because it keeps tracks of the latest applied revision in a table alembic_version. It doesn't know you changed the revision file. In that case the trick is to connect to the DB, and then delete the entry in the alembic_version. This will force it to reapply all revisions at startup. If you're using the DB docker you can use the following:

    "},{"location":"development/environment/","title":"Setup","text":"

    It follows an issue raised on the Github of the project.

    It recommends the use of a hybrid development environment, as most of the time only the web-app needs to be changed:

    "},{"location":"development/environment/#web-app","title":"Web-app","text":"

    For the webapp configuration, a specific .ini need to be created.

    That's the only configuration change needed for the app to run outside docker. The docker.priv.ini is already excluded in gitignore.

    Then Pycharm need to be setup with a dedicated environment, by adding a new configuration:

    To have pylint, right click on source in the directory tree and mark directory as > sources root. The requirements then need to be installed. Pycharm should detect the requirements.txt and propose to install the dependencies. Otherwise they can be installed with the following command (issued in the virtual environment) : pip3 install -r source\\requirements.txt

    "},{"location":"development/environment/#run","title":"Run","text":"
    1. Spin up the docker db docker-compose up db
    2. Run the Pycharm configuration you created
    3. The interface should be accessible on http://127.0.0.1:8000 (and https://127.0.0.1:4433 if you started the nginx docker)

    IRIS can now be developed and debugged on the fly.

    "},{"location":"development/environment/#tests-in-docker","title":"Tests in docker","text":"

    Once the code is working by running on Pycharm, we highly recommend testing it on Docker. To do so, the app docker need to be erased and rebuilt.

    1. docker-compose rm app
    2. docker-compose build app
    3. docker-compose up db app

    Development considerations If the development results in DB modification, please use Alembic and add a migration script so users don't loose their data when they upgrade.

    "},{"location":"development/hooks/","title":"Hooks","text":"

    Introduced in IRIS v1.4.0

    Hooks are a mean for modules to react on specific events that occurs on IRIS. By subscribing to a hook, a module is automatically notified when the associated event occurs. This offers a multitude of possibilities, from adding insight to IRIS objects, to pushing information to another platform or even changing how IRIS works.

    "},{"location":"development/hooks/#types","title":"Types","text":"

    There are 3 types of hooks.

    Danger

    on_preload hooks must run synchronously, i.e not queued in RabbitMQ. This effectively blocks the current user request until the module finishes the processing. We highly recommend to only use on_postload hooks for a better user experience. These hooks are transparent for users and rely on already verified and committed data. Handling on_preload hooks implies the received data is unsafe - directly coming from remote clients - and the module needs to process the data as fast as possible.

    "},{"location":"development/hooks/#subscribing-and-unsubscribing","title":"Subscribing and unsubscribing","text":"

    Two methods are provided by IrisModuleInterface to subscribe and unsubscribe to hooks.

      def register_to_hook(module_id: int, \niris_hook_name: str, \nmanual_hook_name: str = None, \nrun_asynchronously: bool = True)\ndef deregister_from_hook(module_id: int, \niris_hook_name: str)\n

    The registration method expects the following arguments:

    The deregistration method expects the following arguments:

    Please see the modules documentation for more details on how to implement these methods.

    "},{"location":"development/hooks/#available-hooks","title":"Available hooks","text":"

    The following hooks are natively available for subscription.

    Hook name Description on_preload_case_create Triggered on case creation, before commit in DB on_postload_case_create Triggered on case creation, after commit in DB on_preload_case_delete Triggered on case deletion, before commit in DB on_postload_case_delete Triggered on case deletion, after commit in DB on_postload_case_update Triggered on case update, before commit in DB on_manual_trigger_case Triggered upon user action on_postload_alert_create Triggered on alert creation, after commit in DB on_postload_alert_update Triggered on alert update, after commit in DB on_postload_alert_delete Triggered on alert deletion, after commit in DB on_postload_alert_escalate Triggered on alert escalation, after commit in DB on_postload_alert_merge Triggered on alert merge, after commit in DB on_postload_alert_unmerge Triggered on alert unmerge, after commit in DB on_preload_asset_create Triggered on asset creation, before commit in DB on_postload_asset_create Triggered on asset creation, after commit in DB on_preload_asset_update Triggered on asset update, before commit in DB on_postload_asset_update Triggered on asset update, after commit in DB on_preload_asset_delete Triggered on asset deletion, before commit in DB on_postload_asset_delete Triggered on asset deletion, after commit in DB on_manual_trigger_asset Triggered upon user action on_preload_note_create Triggered on note creation, before commit in DB on_postload_note_create Triggered on note creation, after commit in DB on_preload_note_update Triggered on note update, before commit in DB on_postload_note_update Triggered on note update, after commit in DB on_preload_note_delete Triggered on note deletion, before commit in DB on_postload_note_delete Triggered on note deletion, after commit in DB on_manual_trigger_note Triggered upon user action on_preload_ioc_create Triggered on ioc creation, before commit in DB on_postload_ioc_create Triggered on ioc creation, after commit in DB on_preload_ioc_update Triggered on ioc update, before commit in DB on_postload_ioc_update Triggered on ioc update, after commit in DB on_preload_ioc_delete Triggered on ioc deletion, before commit in DB on_postload_ioc_delete Triggered on ioc deletion, after commit in DB on_manual_trigger_ioc Triggered upon user action on_preload_event_create Triggered on event creation, before commit in DB on_preload_event_duplicate Triggered on event duplication, before commit in DB. This event only received the event ID which will be duplicated on_postload_event_create Triggered on event creation, after commit in DB on_preload_event_update Triggered on event update, before commit in DB on_postload_event_update Triggered on event update, after commit in DB on_preload_event_delete Triggered on event deletion, before commit in DB on_postload_event_delete Triggered on event deletion, after commit in DB on_manual_trigger_event Triggered upon user action on_preload_evidence_create Triggered on evidence creation, before commit in DB on_postload_evidence_create Triggered on evidence creation, after commit in DB on_preload_evidence_update Triggered on evidence update, before commit in DB on_postload_evidence_update Triggered on evidence update, after commit in DB on_preload_evidence_delete Triggered on evidence deletion, before commit in DB on_postload_evidence_delete Triggered on evidence deletion, after commit in DB on_manual_trigger_evidence Triggered upon user action on_preload_task_create Triggered on task creation, before commit in DB on_postload_task_create Triggered on task creation, after commit in DB on_preload_task_update Triggered on task update, before commit in DB on_postload_task_update Triggered on task update, after commit in DB on_preload_task_delete Triggered on task deletion, before commit in DB on_postload_task_delete Triggered on task deletion, after commit in DB on_manual_trigger_task Triggered upon user action on_preload_global_task_create Triggered on global task creation, before commit in DB on_postload_global_task_create Triggered on global task creation, after commit in DB on_preload_global_task_update Triggered on task update, before commit in DB on_postload_global_task_update Triggered on global task update, after commit in DB on_preload_global_task_delete Triggered on task deletion, before commit in DB on_postload_global_task_delete Triggered on global task deletion, after commit in DB on_manual_trigger_global_task Triggered upon user action on_preload_report_create Triggered on report creation, before generation in DB on_postload_report_create Triggered on report creation, before download of the document on_preload_activities_report_create Triggered on activities report creation, before generation in DB on_postload_activities_report_create Triggered on activities report creation, before download of the document on_postload_asset_commented Triggered on asset comment, after commit in DB on_postload_asset_comment_update Triggered on asset comment update, after commit in DB on_postload_asset_comment_delete Triggered on asset comment deletion, after commit in DB on_postload_evidence_commented Triggered on evidence comment, after commit in DB on_postload_evidence_comment_update Triggered on evidence comment update, after commit in DB on_postload_evidence_comment_delete Triggered on evidence comment deletion, after commit in DB on_postload_task_commented Triggered on task comment, after commit in DB on_postload_task_comment_update Triggered on task comment update, after commit in DB on_postload_task_comment_delete Triggered on task comment deletion, after commit in DB on_postload_ioc_commented Triggered on ioc comment, after commit in DB on_postload_ioc_comment_update Triggered on ioc comment update, after commit in DB on_postload_ioc_comment_delete Triggered on ioc comment deletion, after commit in DB on_postload_event_commented Triggered on event comment, after commit in DB on_postload_event_comment_update Triggered on event comment update, after commit in DB on_postload_event_comment_delete Triggered on event comment deletion, after commit in DB on_postload_note_commented Triggered on note comment, after commit in DB on_postload_note_comment_update Triggered on note comment update, after commit in DB on_postload_note_comment_delete Triggered on note comment deletion, after commit in DB on_postload_alert_commented Triggered on alert comment, after commit in DB on_postload_alert_comment_update Triggered on alert comment update, after commit in DB on_postload_alert_comment_delete Triggered on alert comment deletion, after commit in DB"},{"location":"development/structure/","title":"Structure overview","text":""},{"location":"development/structure/#flask","title":"Flask","text":"

    IRIS uses Flask for the web engine.

    "},{"location":"development/structure/#routes-and-blueprints","title":"Routes and blueprints","text":"

    Each page and API endpoints (eg /login, /dashboard, /case/assets/list, etc) refers to a route in the IRIS Flask app. They define what the application should do when Flask receives a request on an URI. To keep structure in the projects, these routes are grouped by Blueprints. The Blueprints reflects the structure shown in the IRIS UI left menu. For instance there is a case and an activities Blueprint.

    The Blueprints and thus routes are defined in source > app > blueprints. All the blueprints are registered in source > app > views.py.

    "},{"location":"development/structure/#templates","title":"Templates","text":"

    IRIS uses dynamic page templating when an URI is visited. These Jinja2 templates are filled at runtime with the needed information and then returned to the client. Each route offering a page (i.e non-API endpoints) thus relies on a template. These are set in a folder named templates in each Blueprint. For instance, for the dashboard template : source > app > blueprints > dashboard > templates > index.html.

    "},{"location":"development/structure/#static-contents","title":"Static contents","text":"

    Static content is served from a common folder under source > app > static > assets. It contains CSS, JS and images. These can be accessed by pages using \"/static/assets/<the-resource>\".

    "},{"location":"development/structure/#sqlalchemy","title":"SQLAlchemy","text":"

    For the database management, the application uses SQLAlchemy with a PostgreSQL backend. There is - normally - no need to directly deal with PostgreSQL, everything goes through SQLAlchemy. It provides a Python overlay which allows to talk to the DB with objects.

    "},{"location":"development/structure/#models","title":"Models","text":"

    Each table of the app is defined by a model. These are defined in source > app > model. When IRIS starts, it looks for the already created tables and creates the missing ones if needed. If changes are done on a table or field, then a migration is needed. This is explained in Alembic migrations.

    "},{"location":"development/structure/#requests","title":"Requests","text":"

    To help structuring the code, we are trying to move the DB code from the routes code. This is partially done and work in progress. If your route requests the DB, please put the DB code in source > app > datamgmt.

    "},{"location":"development/structure/#alembic","title":"Alembic","text":"

    To apply schema migration without the need to rebuild the DB, IRIS uses Alembic. It allows to define migration scheme and IRIS calls it when it starts so users can upgrade without too much hassles.

    "},{"location":"development/structure/#hooks-modules-and-tasks","title":"Hooks, modules and tasks","text":"

    Modules are handled via tasks thanks to Celery and RabbitMQ. More info here and here.

    "},{"location":"development/structure/#iris-startup","title":"IRIS startup","text":"

    When starting-up, IRIS initiates a bunch of DB objects, whether it is started for the first time or just restarted. Objects already created are not recreated, but the missing ones are applied. This ensure a smooth migration between versions. These are defined in source > app > post_init.py. The scripts also contains the code that runs th DB migration with Alembic.

    "},{"location":"development/modules/","title":"Modules","text":""},{"location":"development/modules/#introduction","title":"Introduction","text":"

    A DFIR-IRIS Module (DIM) is a Python package allowing to extend IRIS features. DIMs are not running constantly and are only called following specific actions done by users.

    We distinct two types of modules:

    Except for some triggers for processor modules, all tasks provided by DIMs are run asynchronously in RabbitMQ tasks, so they don't impact the UI.

    Both types of DIMs have the same structure, they only differ in their configurations and how they handle the data they receive. For that purpose, every DIM inherit from a common class named IrisModuleInterface - available here - which provides the basic structure and methods of a module.

    Hint

    To quickly start writing a new module, one can follow these tutorials.

    "},{"location":"development/modules/#overview","title":"Overview","text":"

    Modules are instantiated upon actions (hooks, triggers, user actions) and this occurs each time the said actions occur. It implies the initiation of a module has to be very quick. In most of the case, the __init__ method should not even be overwritten.

    They can live either in the worker or the web-app, depending on their type and action they are handling. They can also live in both. This implies multiple instances of the same module can run at the same time.

    The graph below shows two modules of different types running in the worker and interacting with external elements.

    Modules don't have to handle the task creations or resource locks. This is handled by IRIS. They just need to process the data they received and return results in a predefined manner.

    "},{"location":"development/modules/#common-structure","title":"Common structure","text":"

    The section below describes the common structure of modules.

    "},{"location":"development/modules/#directory-structure","title":"Directory structure","text":"
    setup.py                # Setup configuration to build the module \nREADME.md               # README \niris_example_name       # Name of the package \n    __init__.py              # Declaration of the package and main class\n    IrisExampleConfig.py     # Configuration of the module to help keep the main file clean \n    IrisExampleInterface.py  # Main class of the module \n    module_helper            # Sub module containing the helper functions of the module \n      helper.py              # for instance access to ext resource, manipulation of data \n      helper2.py             # etc. \n
    "},{"location":"development/modules/#the-initpy-file","title":"The init.py file","text":"

    Iris loads the modules dynamically. To do so, it needs to know the name of the main class of the module and relies on __init__.py to find this information.

    __iris_module_interface = \"IrisEXAMPLEInterface\"\n

    Where IrisEXAMPLEInterface is the main class of the module and inherits of the base class IrisModuleInterface.

    Caution

    Failing to provide the main class in __init__.py or having the main class inherit from IrisModuleInterface will make IRIS fail each time it attempts to load the module.

    "},{"location":"development/modules/#the-module-configuration","title":"The module configuration","text":"

    Iris needs to know what the module is doing and what services it is providing. This is done via the attributes of the main class (let's say IrisEXAMPLEInterface). The attributes are :

    pipeline_info = {\n# Name of the pipeline used for internal tracking. This \n# must be unique among all modules so pick something really unique \n\"pipeline_internal_name\": \"example_pipeline\",\n# The name of the pipeline presented to the user. Use something \n# that will help the users to identify the right pipeline\n\"pipeline_human_name\": \"Example Pipeline\",\n# Arguments presented to the users when they select the pipeline\n\"pipeline_args\": [\n['some_index', 'required'],\n['example_argument', 'optional']\n]\n}\n
    _module_configuration = [\n{\n\"param_name\": \"vt_api_key\",\n\"param_human_name\": \"VT API Key\",\n\"param_description\": \"Virus total API key\",\n\"default\": None,\n\"mandatory\": True,\n\"type\": \"sensitive_string\"\n},\n{\n\"param_name\": \"vt_key_is_premium\",\n\"param_human_name\": \"VT Key is premium\",\n\"param_description\": \"Set to True if the VT key is premium\",\n\"default\": False,\n\"mandatory\": True,\n\"type\": \"bool\"\n},\n{\n\"param_name\": \"vt_ip_assign_asn_as_tag\",\n\"param_human_name\": \"Assign ASN tag to IP\",\n\"param_description\": \"Assign a new tag to IOC IPs with the ASN fetched from VT\",\n\"default\": True,\n\"mandatory\": True,\n\"type\": \"bool\"\n}\n]\n

    The above example results in the following.

    "},{"location":"development/modules/quick_start/processor/","title":"Processor modules","text":"

    In this tutorial, we demonstrate the steps to write a basic processor module which subscribes to a hook, and log what it receives when the hook is triggered. We will also add a configuration setting to offer our users the ability disable this feature.

    We'll call it IrisDummyModule.

    "},{"location":"development/modules/quick_start/processor/#project-structure-overview","title":"Project structure overview","text":"

    As described in the development module main page, the module should have the following structure.

    setup.py                # Setup configuration to build the module \nREADME.md               # README \niris_dummy_module       # Name of the package \n__init__.py              # Declaration of the package and main class\nIrisDummyConfig.py       # Configuration of the module to help keep the main file clean \nIrisDummyModule.py    # Main class of the module \n

    While the module could have only one main file IrisDummyModule.py, we recommend splitting its configuration into a new configuration file (here IrisDummyConfig.py) to keep the code clear.

    There is no mandatory naming convention for the files or the class or the methods. We chose this one to keep things clear, and we recommend following the same. But it's up to you really.

    We will walk over these files one by one during this tutorial.

    "},{"location":"development/modules/quick_start/processor/#creating-the-interface","title":"Creating the interface","text":"

    The interface is the code that talks with IRIS. It implements methods that call and are called by the server. It needs to inherit IrisModuleInterface class from the IrisModuleInterface package. This module handles most of the methods needed by IRIS to recognize, set up and call the module. By inheriting this class in our interface, we avoid writing that part ourselves.

    Let's write our basic interface class. The name of the file has to be the name of the main class, that's the only constraint. We'll see later on why.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\npass \n

    That's it! Actually this class is not doing anything right now. We'll need to add a few methods to register our hook later.

    But first we need to indicate to IRIS what is our main interface class. Remember, there is no convention restriction, so IRIS has no way to know which class it should instantiate to call our module.

    To do so, we need to set a specific variable in our __init__.py.

    iris_dummy_module/__init__.py
    # Set the __iris_module_interface variable to the name of our main class. \n# When IRIS instantiates the python module, it looks for \"module.__iris_module_interface\"\n# And then tries to instantiate the class \"__iris_module_interface.__iris_module_interface\", here 'IrisDummyModule.IrisDummyModule'. \n# That's why the python file must have the same name as the class.  \n__iris_module_interface = \"IrisDummyModule\"\n

    Our module is now recognizable by IRIS Pretty simple right?

    "},{"location":"development/modules/quick_start/processor/#writing-the-configuration","title":"Writing the configuration","text":"

    The next step is to describe what the module is doing, its name, its configuration, etc. This is done by overwriting predefined variables of the IrisModuleInterface class.

    Let's create our Python configuration file and go through each variables.

    iris_dummy_module/IrisDummyConfig.py
    # Import the module types list,  so we can indicate the type of our module \nfrom iris_interface.IrisModuleInterface import IrisModuleTypes \n# Human name displayed in the GUI Manage > Modules. This can be anything, \n# but try to put something meaningful, so users recognize your module. \nmodule_name = \"IrisDummy\"\n# Description displayed when editing the module configuration in the UI. \n# This can be anything, \nmodule_description = \"Provides a dummy module that replies to one hook\"\n# Set the interface version used. This needs to be the version of \n# the IrisModuleInterface package. This version is check by the server to\n# to ensure our module can run on this specific server \ninterface_version = 1.1\n# The version of the module itself, it can be anything \nmodule_version = 1.0\n# The type of the module, here processor \nmodule_type = IrisModuleTypes.module_processor\n# Our module is a processor type, so it doesn't offer any pipeline \npipeline_support = False\n# Provide no pipeline information as our module don't implement any \npipeline_info = {}\n# The configuration of the module that will be displayed and configurable \n# by administrators on the UI. This describes every parameter that can \n# be set. \nmodule_configuration = [\n{\n\"param_name\": \"log_received_hook\",\n\"param_human_name\": \"Log received hook\",\n\"param_description\": \"Logs a message upon hook receiving if set to true. Otherwise do nothing.\",\n\"default\": True,\n\"mandatory\": True,\n\"type\": \"bool\"\n}\n]\n

    The module configuration parameters are the following :

    A module can have as many parameters as it needs.

    We now need to update our main class to set this configuration.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\n# Set the configuration\n_module_name = interface_conf.module_name\n_module_description = interface_conf.module_description\n_interface_version = interface_conf.interface_version\n_module_version = interface_conf.module_version\n_pipeline_support = interface_conf.pipeline_support\n_pipeline_info = interface_conf.pipeline_info\n_module_configuration = interface_conf.module_configuration\n_module_type = interface_conf.module_type\npass \n

    Done! The module is now providing enough information to IRIS, so it knows exactly what our module do and what needs to be called to run it.

    However, our module is still doing nothing. Let's make it subscribe to an IRIS hook.

    "},{"location":"development/modules/quick_start/processor/#subscribing-to-a-hook","title":"Subscribing to a hook","text":"

    Hooks allow to be notified by IRIS when a specific event occurs (IOC creation, deletion, etc). For a comprehensive description of hooks, please see the Hooks section of this documentation.

    The registration (or subscription) to a hook occurs at two moments during the life of a module:

    These registration/deregistration events are triggered by IRIS, and are propagated to modules through the IrisModuleInterface method register_hooks [ref].

    To register to a hook, we need to override this method and register our hook within this method. To do so, IrisModuleInterface offers us another method register_to_hook [ref], which we can call for each hook we want to subscribe.

    Here is a summary of the events:

    1. IRIS calls register_hooks of our module. This indicates it is time for us to register our hooks.
    2. Within this method, we call register_to_hook for each hook we want to subscribe

    Let's add this to our main class and register to the on_postload_ioc_create. This will notify use each time a new IOC is created and committed to the database.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\n# Set the configuration\n_module_name = interface_conf.module_name\n_module_description = interface_conf.module_description\n_interface_version = interface_conf.interface_version\n_module_version = interface_conf.module_version\n_pipeline_support = interface_conf.pipeline_support\n_pipeline_info = interface_conf.pipeline_info\n_module_configuration = interface_conf.module_configuration\n_module_type = interface_conf.module_type\ndef register_hooks(self, module_id: int):\n\"\"\"\n        Called by IRIS indicating it's time to register hooks.  \n        :param module_id: Module ID provided by IRIS.\n        \"\"\"\n# Call the hook registration method. We need to pass the \n# the module_id to this method, otherwise IRIS won't know \n# to whom associate the hook. \n# The hook name needs to be a well known hook name by IRIS. \nstatus = self.register_to_hook(module_id, iris_hook_name='on_postload_ioc_create')\nif status.is_failure():\n# If we have a failure, log something out \nself.log.error(status.get_message())\nelse:\n# Log that we successfully registered to the hook \nself.log.info(f\"Successfully subscribed to on_postload_ioc_create hook\")\n

    That's it! Our module has now officially subscribed to a hook and will be notified each time an IOC is created.

    So how the module is notified? Once again this is done by a method named hooks_handler [ref] that IrisModuleInterface provides, and we need to overwrite.

    This method is called each time one of the event associated to the hook we subscribed is triggered. It provides the name of the hook and as well as the data associated to it. By overwriting this method, we can process the hook and the data!

    We will add a condition in this method, that is if the administrator sets the module parameter log_received_hook to False, then the module won't log anything and simply return the data.

    Hint

    The current configuration of the module can be accessed with the attribute self._dict_conf.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\n# Set the configuration\n_module_name = interface_conf.module_name\n_module_description = interface_conf.module_description\n_interface_version = interface_conf.interface_version\n_module_version = interface_conf.module_version\n_pipeline_support = interface_conf.pipeline_support\n_pipeline_info = interface_conf.pipeline_info\n_module_configuration = interface_conf.module_configuration\n_module_type = interface_conf.module_type\ndef register_hooks(self, module_id: int):\n\"\"\"\n        Called by IRIS indicating it's time to register hooks.  \n        :param module_id: Module ID provided by IRIS.\n        \"\"\"\n# Call the hook registration method. We need to pass the \n# the module_id to this method, otherwise IRIS won't know \n# to whom associate the hook. \n# The hook name needs to be a well known hook name by IRIS. \nstatus = self.register_to_hook(module_id, iris_hook_name='on_postload_ioc_create')\nif status.is_failure():\n# If we have a failure, log something out \nself.log.error(status.get_message())\nelse:\n# Log that we successfully registered to the hook \nself.log.info(f\"Successfully subscribed to on_postload_ioc_create hook\")\ndef hooks_handler(self, hook_name: str, data):\n\"\"\"\n    Called by IRIS each time one of our hook is triggered. \n    \"\"\"\n# read the current configuration and only log the call if \n# our parameter is set to true \nif self._dict_conf.get('log_received_hook') is True:\nself.log.info(f'Received {hook_name}')\nself.log.info(f'Received data of type {type(data)}')\n# Return a standardized message to IRIS saying that everything is ok. \n# logs=list(self.message_queue) is needed, so the users can see the logs \n# our module generated during its execution.  \nreturn InterfaceStatus.I2Success(data=data, logs=list(self.message_queue))\n

    We are done! Our module is now fully ready to register, subscribe to a hook and act when notified.

    "},{"location":"development/modules/quick_start/processor/#installing-and-registering-the-module","title":"Installing and registering the module","text":"

    We need now need to build and install the module. To do so, you'll need this script and an IRIS docker instance running on the same machine.

    The script will build the module, copy it to the docker instances, install it within them and restart the dockers.

    1. From within the root directory of the module, paste the script
    2. Make it executable chmox +x buildnpush2iris.sh
    3. Execute it ./buildnpush2iris.sh -a

    The module should now be installed. We can register it in IRIS as explained here.

    "},{"location":"operations/alerts/","title":"Alerts","text":"

    This section is under construction.

    Introduced in IRIS v2.1.0

    Alerts can be feeded directly into IRIS using the Alerts API. Any source can inject alerts into IRIS, as long as it can send HTTP requests and respects the alert format.

    A service account with the alert_read and alert_write permission can be used to send alerts to IRIS.

    Warning

    This section is only available for users with the alert_read and alert_write permissions.

    "},{"location":"operations/alerts/#viewing-alerts","title":"Viewing alerts","text":"

    Alerts can then be viewed in the Alerts section of IRIS. Analysts can then triage the alerts and create cases from them.

    Each alert can be expanded to show more details.

    "},{"location":"operations/alerts/#alerts-assignment","title":"Alerts assignment","text":"

    Alerts can be assigned to analysts. This can be done directly from the alert view.

    To self assign an unassigned alert, click on the hand icon on the left.

    Clicking again on the hand icon will prompt with a list of analysts to assign the alert to.

    The right button Assign when hovering an alert can also be used to assign the alert to an analyst.

    "},{"location":"operations/alerts/#merge-escalation-operations","title":"Merge / escalation operations","text":""},{"location":"operations/alerts/#creating-cases-from-alerts","title":"Creating cases from alerts","text":"

    Alerts can be escalated/merged into a new case. When hovering an alert, a Merge button will appear.

    Once clicked, a new window appears, requesting additional information. In this window, the analyst can:

    "},{"location":"operations/alerts/#merge-alerts-into-an-existing-case","title":"Merge alerts into an existing case","text":"

    Alerts can also be escalated/merged into an existing case. When hovering an alert, a Merge button will appear.

    Once clicked a new window appears, requesting additional information. The button Merge into existing case needs to be clicked. A new dropdown appears and allows to select the case to merge the alert into.

    Similar to the case creation, the analyst can:

    The selections IOCs and assets are then added to the selected case.

    "},{"location":"operations/alerts/#umerge-alerts-from-a-case","title":"Umerge alerts from a case","text":"

    Alerts can be unmerged from a case.

    Info

    When unmerging an alert, the alert is not deleted. It is only removed from the case. The alert state is not changed. The IOC and assets are not removed from the case.

    When a case is merged, a new link appears on the alert and mentions the case it was merged into. Clicking on this link allows to browse the case or to unmerge the alert.

    "},{"location":"operations/alerts/#alerts-relationships","title":"Alerts relationships","text":"

    Each alert have a Relastionships section. This section shows the relationships between the alert and other objects in IRIS. This feature is in preview and might report false relationships.

    The relationships are computed using the following logic:

    By default the view limits the relationships to 100 nodes and looks back 7 days. This can be updated directly in the alert view.

    "},{"location":"operations/api/","title":"API","text":"

    IRIS is meant to be plug-able and be integrated with the existing environments.

    Through the REST API, one can do almost as much as it is possible to do through the web interface. Under the hood, the web interface is actually talking to the API.

    Hint

    A Python client is available here to ease the automation.

    "},{"location":"operations/api/#api-keys","title":"API Keys","text":"

    The first step is to obtain an API key. Each user is automatically attributed one when it is created. It can be found on the left panel, under username and My Settings.

    Token exposure

    In case the token is exposed and needs to be change, a new one can be generated with the Renew option. Renewing a token revokes the previous.

    "},{"location":"operations/api/#references","title":"References","text":"

    The API constantly evolves with IRIS and thus multiple versions exists. Use the references below to check which API version applies to your IRIS version. Starting from IRIS v1.4.0, the supported API version can also be checked in the UI Advanced > Server settings.

    IRIS Version API Version & Reference v1.2.0 API v1.0.0 v1.2.1 API v1.0.0 v1.3.0 API v1.0.1 v1.3.1 API v1.0.1 v1.4.0 API v1.0.2 v1.4.1 API v1.0.2 v1.4.2 API v1.0.2 v1.4.3 API v1.0.3 v1.4.4 API v1.0.3 v1.4.5 API v1.0.3 v2.0.x API v2.0.0 v2.1.x API v2.0.1 v2.2.x API v2.0.1 v2.3.x API v2.0.2 - To come"},{"location":"operations/api/#how-to-use","title":"How to use","text":"

    The API token is used as a Bearer and needs to be present in the header Authorization when issuing requests. For example, to list all the cases:

       curl --request GET \\\n--url http://localhost:8000/manage/cases/list?cid=1 \\\n--header 'Authorization: Bearer mWpCUVNzBMU5EnbIAK50jLPhYjKBTHZjobdogc_n_yixpJTmt9tzAf8WYDI7m5XgB9wCJnlaXlHIh9RZjtp2fA' \\\n--header 'Content-Type: application/json'\n

    The only way to revoke a token is to renew the current one. Once done, the previous API token does not exist anymore in the database and it becomes ineffective.

    "},{"location":"operations/case_templates/","title":"Case templates","text":"

    Introduced in IRIS v2.1.0

    Case templates are a way to pre-configure a case with a set of predefined informations. The case templates can be managed in Advanced > Case templates.

    Info

    This section is only available for users with the administrator role.

    Case templates are made of a set of informations that will be used to pre-fill the case creation form. The following elements can be set:

    Looking for case templates?

    We are providing a set of case templates in the IRIS Resources repository.

    "},{"location":"operations/case_templates/#structure-of-templates","title":"Structure of templates","text":"

    The following defines the structure of a case template:

    {\n\"name\": \"ransomware_infection\",\n\"display_name\": \"Ransomware Infection Template\",\n\"description\": \"This case template describes first-response tasks to handle information system compromised by a ransomware.\",\n\"author\": \"DFIR-IRIS\",\n\"classification\": \"malicious-code:ransomware\",\n\"title_prefix\": \"[RANS]\",\n\"summary\": \"# Context \\n\\n\\n# Contact \\n\\n\\n# Actions \\n\\n\\n\",\n\"tags\": [\"ransomware\",\"malware\"],\n\"tasks\": [\n{\n\"title\": \"Identify the perimeter\",\n\"description\": \"The perimeter of compromise must be identified\",\n\"tags\": [\"identify\"]\n},\n{\n\"title\": \"Collect compromised hosts\",\n\"description\": \"Deploy Velociraptor and start collecting evidence\",\n\"tags\": [\"collect\", \"velociraptor\"]\n},\n{\n\"title\": \"Containment\"\n}\n],\n\"note_groups\": [\n{\n\"title\": \"Identify\",\n\"notes\": [\n{\n\"title\": \"Identify the compromised accounts\",\n\"content\": \"# Observations\\n\\n\"\n}\n]\n},\n{\n\"title\": \"Collect\",\n\"notes\": [\n{\n\"title\": \"Velociraptor deployment\"\n},\n{\n\"title\": \"Assets collected\",\n\"content\": \"# Assets collected\\n\\n# Assets not collected\"\n}\n]\n}\n]\n}\n
    "},{"location":"operations/case_templates/#using-case-templates","title":"Using case templates","text":"

    Case templates can be used when creating a new case. On the UI, when creating a case, select the case template to use in the Case template dropdown. The case will then automatically use the informations defined in the template.

    "},{"location":"operations/configuration/","title":"Configuration","text":"

    Since v2.0.0 the entire configuration is done through the .env file at the root of the IRIS directory.

    "},{"location":"operations/configuration/#default-configuration","title":"Default configuration","text":"

    The default configuration is provided through a .env.model file at the root of the IRIS directory. One need to copy this file to .env and modify it if needed.

    The default configuration is suitable for testing only. See the section below to configure IRIS for production.

    "},{"location":"operations/configuration/#production-configuration","title":"Production configuration","text":""},{"location":"operations/configuration/#secrets","title":"Secrets","text":""},{"location":"operations/configuration/#required-changes","title":"Required changes","text":"

    The following secrets in the .env need to be changed for production. We recommend using OpenSSL to generate different values from each secret: openssl rand -base64 64

    Critical configuration

    These settings are critical and need to be set properly otherwise authentication bypass may occur.

    "},{"location":"operations/configuration/#optionnal-changes","title":"Optionnal changes","text":"

    To automate the provisionning of IRIS, one might need to set the default administrator API token and password. This can be achieve with the following environment variables. If those variables are not set, random ones are generated during the very first boot of the application.

    Warning

    The administrator password is printed in the logs. It is recommended to change it as soon as possible. The set of the following environment variables has no effect once the administrator account is created, i.e after the very first boot.

    "},{"location":"operations/configuration/#certificates","title":"Certificates","text":"

    IRIS is configured to use a self-signed certificate by default. This is suitable for testing only. To use your own certificate, you need to set the following environment variables:

    Once the changes are done, nginx docker container need to be rebuilt with the following command:

    docker-compose stop nginx\ndocker-compose build nginx --no-cache\ndocker-compose up 
    "},{"location":"operations/configuration/#authentication","title":"Authentication","text":""},{"location":"operations/configuration/#ldap","title":"LDAP","text":"

    IRIS can be configured to use LDAP authentication. See the Authentication section for more details.

    "},{"location":"operations/configuration/#available-settings","title":"Available settings","text":"

    These environment variables are availabled to be set.

    Key Section Opt Description SERVER_NAME Nginx No Passed to the server_name in NGINX configuration KEY_FILENAME Nginx No SSL Cert key filename passed to the NGINX configuration CERT_FILENAME Nginx No SSL Cert filename passed to the NGINX configuration INTERFACE_HTTPS_PORT Nginx Yes Listening interface of IRIS POSTGRES_USER DB No Name of the POSTGRES user POSTGRES_PASSWORD DB No Password of the POSTGRES user POSTGRES_ADMIN_USER DB No Name of the admin user POSTGRES_ADMIN_PASSWORD DB No Password of the ADMIN user POSTGRES_DB DB No Name of the DB used by IRIS POSTGRES_SERVER DB No Hostname or IP of the DB POSTGRES_PORT DB No Port of the DB server DOCKERIZED IRIS Yes Set to 1 when using dockers (default) IRIS_SECRET_KEY IRIS No Secret key used to secure sessions - needs to be random IRIS_SECURITY_PASSWORD_SALT IRIS No Secret used to salt the passwords in DB - needs to be random IRIS_UPSTREAM_SERVER IRIS No WebApp upstream server - used to configure nginx reverse proxy IRIS_UPSTREAM_PORT IRIS No WebApp upstream server port - used to configure nginx reverse proxy IRIS_ORGANISATION_NAME IRIS No Name of the company / organisation. Used on the UI IRIS_LOGIN_BANNER_TEXT IRIS No Text displayed on the login page IRIS_LOGIN_PTFM_CONTACT IRIS No Contact information displayed on the login page IRIS_UPLOADED_PATH IRIS No Path to store uploaded data. IRIS_BACKUP_PATH IRIS No Path to store backup files. IRIS_TEMPLATES_PATH IRIS No Path of the templates IRIS_DATASTORE_PATH IRIS No Path of the datastore files IRIS_DEMO_ENABLED Demo No Set to True to switch IRIS to Demo mode IRIS_DEMO_DOMAIN Demo No URL of the demonstration server IRIS_DEMO_USER_SEED Demo No Random seed to generate demo users IRIS_DEMO_ADM_SEED Demo No Random seed to generate admin users for demo CELERY_BROKER Celery No Broker URL used to handle IRIS tasks IRIS_AUTHENTICATION_TYPE Auth No IRIS auth mode : local or ldap IRIS_ADM_PASSWORD Auth Yes Set to use as initial password of the administrator account. Only works for the very first run of IRIS. Needs to match the password policy IRIS_ADM_API_KEY Auth Yes Set to use as initial API Key of the administrator IRIS_ADM_EMAIL Auth Yes Set to use as initial email of the administrator IRIS_ADM_USERNAME Auth Yes Set to use as initial username of the administrator LDAP_SERVER Auth Yes LDAP server IP or domain LDAP_PORT Auth Yes LDAP server port LDAP_USER_PREFIX Auth Yes Prefix to search the users within LDAP_USER_SUFFIX Auth Yes Suffix to search the users within LDAP_USE_SSL Auth Yes Set to True to use LDAPS LDAP_VALIDATE_CERTIFICATE Auth Yes Set to True to verify the server certificate validity LDAP_TLS_VERSION Auth Yes TLS version to use LDAPS LDAP_SERVER_CERTIFICATE Auth Yes Path of the LDAP server certificate LDAP_PRIVATE_KEY Auth Yes Path of the LDAP private certificate LDAP_PRIVATE_KEY_PASSWORD Auth Yes Password of the private key LDAP_AUTHENTICATION_TYPE Auth Yes Simple, SASL or NTLM LDAP_CUSTOM_TLS_CONFIG Auth Yes If set to true, the TLS configuration is not set by IRIS and taken from the defined environment. Default to False"},{"location":"operations/custom_attributes/","title":"Custom Attributes","text":"

    Introduced in IRIS v1.4.0

    All the case objects can be extended with custom attributes. These attributes can be added by :

    Attributes offer the ability to :

    This section only describes how an administrator can add or delete attributes to an object.

    Tip

    We have publish a detailed article of custom attributes with advanced usage on our blog.

    "},{"location":"operations/custom_attributes/#management-page","title":"Management page","text":"

    Custom attributes can be changed in the Advanced > Custom Attributes section on the left panel.

    The page lists the objects for which custom attributes can be added or modified.

    "},{"location":"operations/custom_attributes/#attributes-structure","title":"Attributes structure","text":"

    Attributes are defined in JSON which describes tabs and fields that makes the attributes.

      {\n\"Tab Name 1\": {                     // Defines a new tab \n\"Field 1\": {                    // Defines a new field within the Tab Name 1\n\"type\": \"input_string\",     // Defines the type of field, here a standard string input\n\"mandatory\": true,          // Indicates whether the field is mandatory upon saving\n\"value\": \"\"                 // Default value if any, else empty\n},\n\"Field 2\": {                    // Defines a second field within the tab Tab Name 1\n\"type\": \"input_checkbox\",   // Defines an input checkbox\n\"mandatory\": false,         // Indicates whether the field is mandatory upon saving\n\"value\": false              // Default value - must be set for booleans\n}\n},\n\"VT report\": {                      // Defines a second tab named VT report\n\"Content\": {                    // Defines a new field Content within the VT Report\n\"type\": \"html\",             // Defines an HTML interpreted content\n\"value\": \"\"                 // Default value if any, else empty\n}\n}\n}\n

    The code above would be rendered as :

    With :

    1. The native information of the object. This cannot be changed or updated
    2. The new attribute Tab Name 1
    3. The other new attribute VT report
    "},{"location":"operations/custom_attributes/#attributes-taxonomy","title":"Attributes taxonomy","text":"

    The available fields type are available for rendering :

    "},{"location":"operations/custom_attributes/#updating-resetting-attributes","title":"Updating / resetting attributes","text":"

    When an attribute is updated, it will try to update all the existing objects with the new attributes. To prevent any data loss from previous attributes and attributes pushed by modules, the update is only made on attributes which don't have any values set or are type-compatibles (ie string to textfield).

    The migration of an attribute can however be forced in two ways, both resulting in potential attributes data loss.

    Good to know

    Migrating or overwriting attributes never change the native information of an object. It only applies to custom attributes.

    Partial overwrite basically resets all the values of every target objects that matches the current attribute definition. All associated values are lost. This does not impact attributes pushed by modules or previous configuration.

    Complete overwrite resets all attributes of every target objects, including the ones created by modules, and then applies the current attributes. All associated values are lost.

    "},{"location":"operations/custom_attributes/#example","title":"Example","text":"

    Custom attributes can be more complex than what presented above. With the html type, it is possible to build almost anything. Below is an example of the custom attributes used in the IrisVT module. The {{ }} are used withing the module to generates the page with data received from VT.

    Note : This example won't work as is, the value field is expanded here for reability.

    IrisVT default custom attribute
    {\n\"VT report\": {                      \"Content\": {                    \"type\": \"html\",             \"value\": \"<div class='row'>\n                    <div class='col-12'>\n                        <h3>Basic information</h3>\n                        <dl class='row'>\n                            {% if results.as_owner %}\n                            <dt class='col-sm-3'>AS owner</dt>\n                            <dd class='col-sm-9'>{{ results.as_owner }}</dd>\n                            {% endif %}\n                            {% if country %}\n                            <dt class='col-sm-3'>Country</dt>\n                            <dd class='col-sm-9'>{{ results.country }}</dd>\n                            {% endif %}\n                        </dl>\n                    </div>\n                </div>    \n                {% if nb_detected_urls %}\n                <div class='row'>\n                    <div class='col-12'>\n                        <h3>Detected URLS</h3>\n                        <dl class='row'>\n                            <dt class='col-sm-3'>Total detected URLs</dt>\n                            <dd class='col-sm-9'>{{ nb_detected_urls }}</dd>\n                            <dt class='col-sm-3'>Average detection ratio</dt>\n                            <dd class='col-sm-9'>{{ avg_urls_detect_ratio }}</dd>\n                        </dl>\n                    </div>\n                </div>    \n                {% endif %}\n                {% if nb_detected_samples %}\n                <div class='row'>\n                    <div class='col-12'>\n                        <h3>Detected communicating samples</h3>\n                        <dl class='row'>\n                            <dt class='col-sm-3'>Total detected samples</dt>\n                            <dd class='col-sm-9'>{{ nb_detected_samples }}</dd>\n                            <dt class='col-sm-3'>Average detection ratio</dt>\n                            <dd class='col-sm-9'>{{ avg_samples_detect_ratio }}</dd>\n                        </dl>\n                    </div>\n                </div>    \n                {% endif %}\n                <div class='row'>\n                    <div class='col-12'>\n                        <div class='accordion'>\n                            <h3>Additional information</h3>\n                            {% if results.resolutions %}\n                            <div class='card'>\n                                <div class='card-header collapsed' id='drop_res' data-toggle='collapse' data-target='#drop_resolutions' aria-expanded='false' aria-controls='drop_resolutions' role='button'>\n                                    <div class='span-icon'>\n                                        <div class='flaticon-file'></div>\n                                    </div>\n                                    <div class='span-title'>\n                                        Resolutions history\n                                    </div>\n                                    <div class='span-mode'></div>\n                                </div>\n                                <div id='drop_resolutions' class='collapse' aria-labelledby='drop_res' style=''>\n                                    <div class='card-body'>\n                                        <ul>\n                                            {% for resolution in results.resolutions %} \n                                            <li>{{ resolution.hostname }} ( Last resolved on {{resolution.last_resolved}} )</li>\n                                            {% endfor %}\n                                        </ul>\n                                    </div>\n                                </div>\n                            </div>\n                            {% endif %}\n                        </div>\n                    </div>\n                </div>\n                <div class='row'>\n                    <div class='col-12'>\n                        <div class='accordion'>\n                            <h3>Raw report</h3>\n                            <div class='card'>\n                                <div class='card-header collapsed' id='drop_r' data-toggle='collapse' data-target='#drop_raw' aria-expanded='false' aria-controls='drop_raw' role='button'>\n                                    <div class='span-icon'>\n                                        <div class='flaticon-file'></div>\n                                    </div>\n                                    <div class='span-title'>\n                                        Raw report\n                                    </div>\n                                    <div class='span-mode'></div>\n                                </div>\n                                <div id='drop_raw' class='collapse' aria-labelledby='drop_r' style=''>\n                                    <div class='card-body'>\n                                        <div id='vt_raw_ace'>{{ results| tojson(indent=4) }}</div>\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div> \n                <script>\n                var vt_in_raw = ace.edit('vt_raw_ace',\n                {\n                    autoScrollEditorIntoView: true,\n                    minLines: 30,\n                });\n                vt_in_raw.setReadOnly(true);\n                vt_in_raw.setTheme('ace/theme/tomorrow');\n                vt_in_raw.session.setMode('ace/mode/json');\n                vt_in_raw.renderer.setShowGutter(true);\n                vt_in_raw.setOption('showLineNumbers', true);\n                vt_in_raw.setOption('showPrintMargin', false);\n                vt_in_raw.setOption('displayIndentGuides', true);\n                vt_in_raw.setOption('maxLines', 'Infinity');\n                vt_in_raw.session.setUseWrapMode(true);\n                vt_in_raw.setOption('indentedSoftWrap', true);\n                vt_in_raw.renderer.setScrollMargin(8, 5);\n                </script>\"                 }\n}\n}\n
    "},{"location":"operations/datastore/","title":"Datastore","text":"

    Introduced in IRIS v1.4.5

    The datastore offers a way to store files directly in the context of a case. Documents, IOCs, evidences, etc, anything can be uploaded and managed through IRIS.

    "},{"location":"operations/datastore/#accessing-the-datastore","title":"Accessing the datastore","text":"

    The datastore can be accessed from any page with the top-right shortcut.

    A new pane will open, with a default folder tree created for the case.

    "},{"location":"operations/datastore/#files","title":"Files","text":""},{"location":"operations/datastore/#adding-a-file","title":"Adding a file","text":"

    To add a file to a folder, press the + button near a folder where you want to place it, and select Add file.

    A new window appear and allows to upload the file. The following fields are available :

    A file can be both IOC and Evidence, in which case it is handled as an IOC and also added to the Evidence tab of the case.

    Depending on the file size, the upload might take some time. We are aware that the Nginx introduces a delay compared to a direct upload. We have not yet found a configuration that does not impact the speed upload.

    Once uploaded, and depending on the options selected, the file appear in the target folder with specific icons. A mouse hover explains what each icon means.

    "},{"location":"operations/datastore/#files-operations","title":"Files operations","text":"

    Once a file is added, a left-click on it shows a dropdown with multiple options.

    Batch operations such as moving and deleting are also available by clicking on Select at the top right, and then selecting the files.

    "},{"location":"operations/datastore/#pasting-in-notes-and-summary","title":"Pasting in notes and summary","text":"

    Images can now be directly pasted in notes an summary. Only images are supported. Once an image is pasted, the file is automatically uploaded in the datastore in the folder Notes Upload and a link to the file is inserted.

    Example of pasted image

    The image is by default sized to 40%. Changing the end of the link =SIZE%xSIZE% allows to resize the image.

    The file is now available in the DS and can be replaced if needed. The ID of the file is the one provided in the link, which can help finding out when names are updated.

    Note

    Under certain conditions (browser, version, OS) the image copy/paste cannot be done directly. This is a known issue, not directly linked to IRIS but related to how browsers handle files in clipboards. If you face this issue, try to open the image and copy it from there instead of the file manager. Otherwise you need to upload it via the Datastore and then get a link from it.

    "},{"location":"operations/datastore/#folders","title":"Folders","text":""},{"location":"operations/datastore/#adding-a-folder","title":"Adding a folder","text":"

    To add folder, press the + button near a folder where you want to place it, and select Add subfolder.

    A new window appear requesting the name of the folder to create. Validate and the new folder appears in the folder tree. Files can then be added to it.

    "},{"location":"operations/datastore/#moving-folders","title":"Moving folders","text":"

    Folders can be moved within other folders. When doing so, every files and subfolders are also moved, like we are used to with files managers.

    Click on the + near the folder to move, and then select Move. The target folder is underlined in blue. Select then the target folder which should appear underline in orange. Then validate the move.

    The folder and all its children are moved in the target directory.

    "},{"location":"operations/datastore/#searching","title":"Searching","text":"

    When dozens of files are added, the filtering bar can be used to quickly find a file. The filtering mechanism is similar to the one in the timeline.

    The query schema is : target_element:search_value AND target_element2:search_value2. There is no OR condition and searching without target does not work.

    The following target elements can be used to filter :

    "},{"location":"operations/datastore/#under-the-hood","title":"Under the hood","text":"

    Here a are a few concepts to better understand how the datastore is working.

    Folders represented on the datastore are virtual and do not represent the folders on the system. This is to ensure smooth files operations. The files are never touched again (unless overwritten or deleted) once uploaded. When a file or directory is moved or renamed, only its parent references are updated.

    Files are saved by GUID instead of their real names on the system. They are saved under the mapped volume /home/iris/server_data/datastore by default. Then three directories are created :

    Within each of these, a new subdirectory with the case ID is created when a file is uploaded. This is ensure IOC, which can be harmful, are formally identified on the server itself. Files can be found on the system by looking up the Storage UUID of the file (eg: dsf-f86926ec-513d-4e47-88fa-02110e7fb412) in these directories.

    "},{"location":"operations/logging/","title":"Logging","text":"

    All components of IRIS offers by-default logging in the docker instances. Depending on the OS of the hosts, the location of these logs may differ.

    For Debian-based distributions, the logs are usually in /var/lib/docker/containers/. The usually interesting logs in IRIS are the following:

    "},{"location":"operations/logging/#setting-up-forwarding","title":"Setting up forwarding","text":"

    Logs of IRIS can be forwarded to a SIEM for monitoring. Below is discussed how to setup Splunk forwarding. Other drivers are available and detailed on the docker website.

    1. Enable HEC and get an HEC token from Splunk. See the Splunk documentation
    2. On the host where docker is running, create a file /etc/docker/daemon.json and specify the following content:
      {\n\"log-driver\": \"splunk\",\n\"log-opts\": {\n\"splunk-insecureskipverify\": \"true\", \"splunk-index\": \"iris\",\n\"splunk-token\": \"YOUR HEC TOKEN\",\n\"splunk-url\": \"https://SPLUNK_SERVER:8088\"\n}\n}\n
    3. Reload the docker daemon: systemctl reload docker. The logs should appear in the Splunk instance.
    "},{"location":"operations/reports/","title":"Reports","text":"

    IRIS has the ability to generate reports based on the data of an investigation. The reports templates can be managed in Advanced > Templates.

    Info

    This section is only available for users with the Admin role.

    There is two types of reports :

    "},{"location":"operations/reports/#supported-formats","title":"Supported formats","text":"

    The following report formats are supported:

    "},{"location":"operations/reports/#structure-of-templates","title":"Structure of templates","text":"

    Reports templates are made of tags, which are then processed and filed by the template engine of IRIS. The templates can have any forms as soon as they respect the tags. We are providing two example of reports.

    Info

    The templates includes a few lines that describes how to handle styles. These should not be removed. They are be present in the generated reports and need to be removed manually.

    "},{"location":"operations/reports/#available-tags","title":"Available tags","text":"

    The following tags are available. None are mandatory. If a tag is mistyped, the generation step will produce an error message.

    Hint

    Standard objects are accessible with {{ objectname }}. List objects can be looped:

      {% for object in object_list %}\n    {{ object.attribute }}\n  {% endfor %} \n
    "},{"location":"operations/reports/#examples","title":"Examples","text":""},{"location":"operations/reports/#full-documents","title":"Full documents","text":"

    We are providing two example of full reports.

    "},{"location":"operations/reports/#snippets","title":"Snippets","text":"

    The following snippets aimed to be placed directly in the DOCX documents.

    "},{"location":"operations/reports/#loops-and-tables","title":"Loops and tables","text":""},{"location":"operations/reports/#standard-loops","title":"Standard loops","text":"

    A loop needs to be used for list objects. Loop on IOC example

    The IOCs of this case are : \n\n{% for ioc in case.iocs %}\n    - {{ ioc.ioc_value }}\n    - {{ ioc.ioc_description }}\n{% endfor %}\n

    "},{"location":"operations/reports/#table-loops","title":"Table loops","text":"

    To use a loop in a table, a tr tag needs to be added to the loop and the loop directly integrated in the table. Loop on IOC table example

    The IOCs of this case are in the following table : \n\n{%tr for ioc in case.iocs %}\n    {{ ioc.ioc_value }}\n    {{ ioc.type_name }}\n    {{ ioc.ioc_description }}\n{%tr endfor %}\n
    Such as :

    "},{"location":"operations/reports/#nested-loops","title":"Nested loops","text":"

    Loops can be nested. Don't forget to close each loop.

    Nested loop
    {%for ioc in case.iocs %}\n\n    Custom attributes of {{ ioc.ioc_value }} :\n\n    {% for attribute in ioc.custom_attributes %}\n\n        - {{ attribute }}\n\n    {% endfor %}\n\n{% endfor %}\n
    "},{"location":"operations/reports/#conditions","title":"Conditions","text":""},{"location":"operations/reports/#standard","title":"Standard","text":"Check if asset is compromised
    {% for asset in assets %} \n\n    {% if asset.compromised %}\n        Asset {{ asset.asset_name }} is compromised\n    {% endif %}\n\n{% endfor %}\n
    "},{"location":"operations/reports/#list-is-not-empty","title":"List is not empty","text":"

    To check if a list of objects is not empty, use the processor tag count.

    Check if case has assets
    {% if assets|count %} \n    The case has assets\n{% endif %}\n
    "},{"location":"operations/reports/#markdown-handling","title":"Markdown handling","text":"

    The case summary and notes are in markdown. A processor tag should thus be added |markdown. Summary as markdown

    This is an example of summary : \n\n{{ case.description|markdown }}\n

    Loop over notes
    This is an example of recursive notes  : \n\n{% for note in case.notes %}\n\n    My note named {{ note.note_title }} : \n    {{ note.note_content|markdown }}\n\n{% endfor %}\n
    "},{"location":"operations/reports/#troubleshoot","title":"Troubleshoot","text":"

    Most of the time an error of generation is due to misspelled tag or a missing closing tag ({% endfor %}, {% endif %}, etc). In case you cannot figure out what is going wrong, don't hesitate to reach us on Discord.

    "},{"location":"operations/server_settings/","title":"Server settings","text":"

    Some basic settings can be set in the section Advanced > Server settings.

    "},{"location":"operations/tutorials/","title":"Tutorials","text":"

    The tutorials have been discared as we now provide a free demonstration instance on v200.beta.dfir-iris.org. Should you need more information or assistance to use IRIS, you can contact us here.

    "},{"location":"operations/upgrades/","title":"Upgrades","text":"

    Most of the time, Iris handles upgrades of the database automatically when a new version is started, thus no specific actions are required. However, some breaking changes might need manual intervention. Please use the selectors below to assess if a manual action is required.

    Your current version: --Please choose current version-- v1.2.1 v1.3.0 v1.3.1 v1.4.0 v1.4.1 v1.4.2 v1.4.3 v1.4.4 v1.4.5 v2.0.0 v2.0.1 v2.0.2 v2.1.0 v2.2.0 v2.2.1 v2.2.2 v2.2.3 v2.3.0 v2.3.1 v2.3.2 v2.3.3 v2.3.4 v2.3.5 v2.3.6 v2.3.7

    Upgrading to: --Please choose target version-- v1.2.1 v1.3.0 v1.3.1 v1.4.0 v1.4.1 v1.4.2 v1.4.3 v1.4.4 v1.4.5 v2.0.0 v2.0.1 v2.0.2 v2.1.0 v2.2.0 v2.2.1 v2.2.2 v2.2.3 v2.3.0 v2.3.1 v2.3.2 v2.3.3 v2.3.4 v2.3.5 v2.3.6 v2.3.7

    Check upgrades conditions

    For production environments, it is highly recommended to make backups of the DB in case any issues occur during upgrades.

    "},{"location":"operations/upgrades/#backing-up-db","title":"Backing-up DB","text":"

    Only if you run in production and/or data is critical.

    1. List the current running docker containers docker container list
    2. Spot the IRIS DB container name or ID, and execute the backup
      docker exec <container> pg_dump -U postgres iris_db | \\ \ngzip > ../iris_db_backup.gz\n
    1. Ensure the backup was successful by looking at the gz file
      zcat ../iris_db_backup.gz | less 
    "},{"location":"operations/upgrades/#upgrading","title":"Upgrading","text":"
    1. Stop the dockers

      docker-compose stop\n

    2. Remove the application dockers

      docker-compose rm app worker\n

    3. Get the last version of Iris

      git checkout <last_tagged_version>\n

      eg git checkout v2.3.6

    4. Build the new versions

      docker-compose build --no-cache app worker\n

    5. Run IRIS again. The app will handle the DB migration automatically.

      docker-compose up\n

    "},{"location":"operations/upgrades/#rolling-back","title":"Rolling back","text":"

    In case something went wrong, you can rollback to your previous version and restore data.

    1. Remove the faulty docker DB docker-compose down db --volumes
    2. Checkout to the previous version working of IRIS
    3. Rebuild the images docker-compose build --no-cache
    4. Spin up the docker DB, and ONLY this one. docker-compose up db
    5. Get the ID or name of the docker DB docker container list
    6. Restore the DB data zcat ../iris_db_backup.gz | docker exec -i <container> psql -U postgres -d iris_db
    7. Spin up the rest of the dockers docker-compose up
    8. Your data should back.
    "},{"location":"operations/upgrades/#version-specific-upgrades","title":"Version specific upgrades","text":""},{"location":"operations/upgrades/#v234","title":"v2.3.4","text":"

    \u2757 The layout of the reporting has slightly changed. Custom report templates might not work anymore. You can use https://<server>/case/export?cid=<case_id> to get all the possible fields.

    No other impact is to be expected.

    "},{"location":"operations/upgrades/#v210","title":"v2.1.0","text":"

    The default location of the SSL certificates have been changed from dockers/nginx/dev_certs to certificates/nginx/web_certificates. The docker-compose.yml has thus been updated to mount this volume on the nginx Docker.

    Except these changes, users in v2.0.x can upgrade to v2.1.0 without any manual intervention. Users in v1.4.x need to follow the v2.0.0 upgrade instructions before upgrading to v2.1.0.

    "},{"location":"operations/upgrades/#v200","title":"v2.0.0","text":""},{"location":"operations/upgrades/#breaking-changes","title":"Breaking changes","text":"

    This version brings breaking changes on the following:

    Warning

    Custom made modules need to be upgraded to IRIS Module Interface v1.2.0. Please see modules upgrade for v2.0.0

    "},{"location":"operations/upgrades/#instance-migration","title":"Instance migration","text":"

    To migrate an instance from v1.4.5, one can use the script in upgrades/upgrade_to_2.0.0.py located in the repository. These commands needs to be run from the root of the repository (pwd should return something like /iris-web):

    # Pull the lastest version \ngit pull # Checkout to iris v2.0.0\ngit checkout v2.0.0 # Check if upgrades possible\npython3 upgrades/upgrade_to_2.0.0.py --check\n\n# Run the upgrade\npython3 upgrades/upgrade_to_2.0.0.py --install\n

    The script will take care of migrating the environment variables to reflect the changes in v2.0.0. Please review the .env file afterward.

    The port have been changed 443. The script asks if the previous port should be kept or migrated to the new one.

    Once validated, one can proceed with the usual upgrade methodology.

    docker-compose stop \ndocker-compose build --no-cache \ndocker-compose up -d\n
    "},{"location":"operations/upgrades/#v200-modules-upgrades","title":"v2.0.0 modules upgrades","text":"

    This only concerns custom modules not shipped with IRIS Web App. The IRIS module interface has been upgraded to v1.2.0. No breaking changes are associated. One need to change the iris_module_interface dependency to 1.2.0 in the requirements and rebuild the module.

    "},{"location":"operations/upgrades/#python-client","title":"Python client","text":"

    The client has been updated to reflect the latest changes of the API. It also integrates features that were missing previously, such as Datastore Management. Some methods have been deprecated and some other modified. The easiest way to upgrade is to increase the version in the requirements and test. Each deprecated method will produce a warning or raise an exception.

    "},{"location":"operations/upgrades/#v145","title":"v1.4.5","text":"

    If you are coming from IRIS <= v1.3.1 please read this. Changes have been made to the NGINX docker to allow upload of big files for the datastore. It is hence necessary to also rebuild the NGINX docker this time.

    1. Stop the dockers docker-compose stop
    2. Remove the application dockers docker-compose rm app worker
    3. Get the last version of Iris git checkout <last_tagged_version> - eg git checkout v1.4.5
    4. Build the new versions docker-compose build --no-cache app worker nginx
    5. Run IRIS again. docker-compose up
    "},{"location":"operations/upgrades/#v144","title":"v1.4.4","text":"

    This only applies if you are coming from IRIS <= v1.3.1.

    This version brings breaking changes in the DB docker by adding a named volume instead of the default one. This implies that previous existing database is ignored as the new docker won't know which volume was previously used. To prevent this, please strictly follow the guide below. This will copy the data of the existing volume, to the new named one.

    1. Spot the IRIS DB container with docker container list. It should look like iris-web-db-x
    2. Fetch the current db volume ID (name field with the command below)

    docker inspect <iris_db> | grep -A5 \"Mounts\"\n# Example of output\n\"Mounts\": [\n{\n\"Type\": \"volume\",\n      \"Name\": \"a90b9998a3233a68438c8e099bd0ba98d9f62c9734e40297b8067f9fdb921eb9\",\n      \"Source\": \"/var/lib/docker/volumes/a90b9998a3233a68438c8e099bd0ba98d9f62c9734e40297b8067f9fdb921eb9/_data\",\n      \"Destination\": \"/var/lib/postgresql/data\",\n
    3. Stop all the IRIS dockers : docker-compose stop 4. Create a new empty volume : docker volume create --name iris-web_db_data 5. Run a volume copy via a dummy image :
    docker run --rm -it -v <previous_db_volume_id>:/from:ro -v iris-web_db_data:/to alpine ash -c \"cd /from ; cp -av . /to\"\n# With the example of 2., this gives \ndocker run --rm -it -v a90b9998a3233a68438c8e099bd0ba98d9f62c9734e40297b8067f9fdb921eb9:/from:ro -v iris-web_db_data:/to alpine ash -c \"cd /from ; cp -av . /to\"\n
    6. Pull the last changes from the repository, checkout to v1.4.4, build and run.

    git pull origin git checkout v1.4.4\ndocker-compose build docker-compose up 
    7. The data should be successfully transferred.

    Do not forget to clear out your browser cache, many JS files were changed.

    "},{"location":"operations/upgrades/#v143","title":"v1.4.3","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/upgrades/#v142","title":"v1.4.2","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/upgrades/#v141","title":"v1.4.1","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/upgrades/#v140","title":"v1.4.0","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/access_control/","title":"Access control","text":"

    Introduced in v2.0.0

    IRIS offers a granular access control for cases and management features. Two types of access control are available :

    To ease the access control, users can be managed in :

    A user can be in one or multiple groups. The effective case access control of a user is deducted from its groups membership and its own cases access control. The effective permissions are deducted from its groups membership.

    "},{"location":"operations/access_control/#cases-access-control-overview","title":"Cases access control overview","text":"

    Cases access control offer three levels:

    As mentioned above, cases access control can be applied to groups and users. It starts with the groups and ends with atomic user access control.

    For example, the following configuration gives no access to the user since the atomic user access prevail upon the rest.

    stateDiagram-v2\n    DefaultPermission --> Group_prevail: FullAccess\n\n    state join_groups <<join>>\n    Group1 --> join_groups: ReadOnly\n    Group2 --> join_groups: DenyAll\n    join_groups --> Group_prevail: ReadOnly\n    Group_prevail --> Effective_DenyAll: ReadOnly \n\n    Effective_DenyAll: Resulting Deny All access for user\n    User_Access --> Effective_DenyAll: DenyAll

    In the next configuration, the user has Read Only access to the case because the atomic user access is not set, so the access is inherited from the group ownership.

    stateDiagram-v2\n    state join_groups <<join>>\n    Group1 --> join_groups: ReadOnly\n    Group2 --> join_groups: DenyAll\n    Group3 --> join_groups: DenyAll\n    join_groups --> Group_prevail: ReadOnly\n\n    Effective_ReadOnly: Resulting Read Only access for user\n    Group_prevail --> Effective_ReadOnly: ReadOnly \n\n    User_Access --> Effective_ReadOnly: Unset

    This notably allows to create groups which can join a set of people from different organisations to work on the same case.

    "},{"location":"operations/access_control/#permissions-control","title":"Permissions control","text":"

    Permissions allow to control the access to specific management features on the platform (adding users, cases etc.). Two permissions are available:

    "},{"location":"operations/access_control/authentication/","title":"Authentication","text":"

    IRIS supports local and LDAP authentication. In both cases, users need to be declared in IRIS.

    "},{"location":"operations/access_control/authentication/#local-authentication","title":"Local authentication","text":"

    Local authentication is the default setting. The password is validated against the local IRIS database. Passwords are stored salted and hashed, it is thus not possible to retrieve them in case they are lost. It is however possible to change them.

    "},{"location":"operations/access_control/authentication/#changing-a-lost-password","title":"Changing a lost password","text":"

    If another administrative user exists : Being logged as this user, head to the Advanced > Access Control > Users section, and change the administrator password.

    If no other administrative user exists : the change cannot be done via IRIS and an access to the backend is needed.

    Danger

    Do not delete and recreate any users directly from the DB! This will create inconsistencies in the relations and certainly corrupt everything.

    1. Generate the hash of the new password with Python BCrypt in Python prompt

      import bcrypt\nprint(bcrypt.hashpw(<new_password>.encode('utf-8'), bcrypt.gensalt())\n
    2. Connect to the DB docker then the Postgresql database iris_db and update the password

      docker exec -ti <db_docker_id> /bin/bash\n/ # su postgres\n/ # psql\npostgres=# \\c iris_db \npostgres=# UPDATE \"user\" SET password = '<hash>' WHERE \"user\".name = 'administrator';\n
    "},{"location":"operations/access_control/authentication/#ldap-authentication","title":"LDAP authentication","text":"

    LDAP authentication rely on a LDAP server to verify the password of a user. The user needs to be declared in IRIS.

    graph LR\n    A[User] -->|Authenticate| B(IRIS WebApp)\n    B --> C{User exists in DB?}\n    C -->|Yes| D{LDAP accepted password?}\n    C -->|No| E[Authentication failed]\n    D -->|Yes| F[Authentication succeeded]\n    D -->|No| E[Authentication failed]
    "},{"location":"operations/access_control/authentication/#settings","title":"Settings","text":"

    The LDAP settings are present in the .env. Once the LDAP server information is set, reboot the Iris WebApp docker needs to be restarted.

    docker-compose restart app\n
    "},{"location":"operations/access_control/authentication/#setting-up-ldap-for-the-first-runtime-of-iris","title":"Setting up LDAP for the first runtime of IRIS","text":"

    To set up LDAP without having run IRIS priorly, and as the app needs the accounts to be created first before using LDAP, one have to set the IRIS_ADM_EMAIL environment with the LDAP Email of the administrator user.

    Example of LDAP configuration for first run
    IRIS_AUTHENTICATION_TYPE=ldap\n\n## IP address or FQDN of the ldap server\nLDAP_SERVER=dc1.domain.local\n\n## Port of the LDAP server\nLDAP_PORT=636\n## LDAP Authentication type\nLDAP_AUTHENTICATION_TYPE=SIMPLE\n\n## Prefix to search the users within \nLDAP_USER_PREFIX=uid=\n## Suffix to search the users within\nLDAP_USER_SUFFIX=ou=people,dc=example,dc=com\n\n## Set to True to use LDAPS\nLDAP_USE_SSL=True\n\n## Set to True to verify the server certificate validity\nLDAP_VALIDATE_CERTIFICATE=True\n\n## TLS version to use LDAPS\nLDAP_TLS_VERSION=1.2\n\n## LDAP TLS configuration \nLDAP_CUSTOM_TLS_CONFIG=False\n\n# Set email address of the first user, that will be the admin \nIRIS_ADM_EMAIL=adm@example.com 
    "},{"location":"operations/access_control/authentication/#setting-up-for-active-directory","title":"Setting up for Active Directory","text":"

    To use LDAP with an Active Directory, the following settings can be used:

    Example of LDAP configuration for first run with Active Directory
    IRIS_AUTHENTICATION_TYPE=ldap\n\n## IP address or FQDN of the ldap server\nLDAP_SERVER=dc1.domain.local\n\n## Port of the LDAP server\nLDAP_PORT=636\n## LDAP Authentication type\nLDAP_AUTHENTICATION_TYPE=SIMPLE\n\n## Prefix to search the users within\nLDAP_USER_PREFIX=DOMAIN\\\n## Suffix to search the users within\nLDAP_USER_SUFFIX=\n## Set to True to verify the server certificate validity\nLDAP_VALIDATE_CERTIFICATE=True\n\n## TLS version to use LDAPS\nLDAP_TLS_VERSION=1.2\n\n## LDAP TLS configuration \nLDAP_CUSTOM_TLS_CONFIG=False\n\n# Set email address of the first user, that will be the admin\nIRIS_ADM_EMAIL=adm@example.com 
    "},{"location":"operations/access_control/authentication/#setting-up-ldap-after-iris-already-ran","title":"Setting up LDAP after IRIS already ran","text":"

    To set up LDAP after IRIS was already run, one only needs to set up the settings described previously without # Set email address of admin IRIS_ADM_EMAIL=adm@example.com and restart the docker.

    Usernames in IRIS have to match the ones set in LDAP for the authentication to succeed.

    "},{"location":"operations/access_control/authentication/#ldap-certificates","title":"LDAP certificates","text":"

    If the LDAP server uses a self-signed certificate, it is possible to add it to the trusted certificates of the IRIS WebApp docker.

    1. Copy the certificate to the certificates/ldap folder of the IRIS root directory.
    2. Set the LDAP_VALIDATE_CERTIFICATE environment variable to True in the .env file.
    3. Set the LDAP_CUSTOM_TLS_CONFIG environment variable to False in the .env file.
    4. Set the LDAP_CA_CERTIFICATE environment variable certificate path used by the LDAP server in the .env file.

    If the LDAP server requires a client certificate, it is possible to add it to the trusted certificates of the IRIS WebApp docker.

    1. Copy the certificate and key to the certificates/ldap folder of the IRIS root directory.
    2. Set the LDAP_VALIDATE_CERTIFICATE environment variable to True in the .env file.
    3. Set the LDAP_CUSTOM_TLS_CONFIG environment variable to True in the .env file.
    4. Set the LDAP_PRIVATE_KEY environment to the file name of the key in the .env file
    5. Set the LDAP_PRIVATE_KEY_PASSWORD environment variable to the password of the key in the .env file - if needed
    "},{"location":"operations/access_control/groups/","title":"Groups","text":"

    Groups offer the possibility to set case access as well as permissions. By default two groups are created:

    Both groups are set to give full cases access to the users.

    "},{"location":"operations/access_control/groups/#setting-up-a-new-group","title":"Setting up a new group","text":"

    Head to the Access Control page and click Add group.

    Fill the form. All the fields can be change later on. The field Group name has to be unique on the IRIS instance. Access control and members can be set once the group is created.

    "},{"location":"operations/access_control/groups/#configuring-the-group","title":"Configuring the group","text":"

    The group can be configured once created by clicking on it in the list.

    "},{"location":"operations/access_control/groups/#users","title":"Users","text":""},{"location":"operations/access_control/groups/#adding-users-to-a-group","title":"Adding users to a group","text":"

    To add users to the group, go to the Members tab and click Manage.

    The users manager should load and offers a list of users that can be added to the group. Select all the users you want to add to the group and press save.

    Permissions computation

    When a user is added/removed to a group, its effective cases access are recomputed. Depending on the amount of cases and users added/removed this can take some time. This process helps reducing the DB load when using IRIS during normal operation.

    "},{"location":"operations/access_control/groups/#removing-users-from-a-group","title":"Removing users from a group","text":"

    To remove users from the group, go to the Members tab and click Manage.

    The users manager should load and present a list of both users already in the group as well as the ones that can be added. To remove one or more users, un-tick them from the list and press Save.

    Alternatively, a user can be directly removed from withing the group manager. Click on the red trash next to the user to remove and confirm the deletion.

    "},{"location":"operations/access_control/groups/#cases","title":"Cases","text":""},{"location":"operations/access_control/groups/#adding-cases-to-the-group","title":"Adding cases to the group","text":"

    Access to one or multiple existing cases can be granted to a group. From within the group manager, go to the Cases access tab and click Set case access.

    The cases access manager loads and gives the possibility to set the access to one or more cases.

    Three choices of access are offered:

    Once the desired access is selected, press Set access.

    Permissions computation

    As for the addition of users, when a case is added/removed to a group, all the users effective cases access are recomputed. Depending on the amount of cases added/removed and number of users this can take some time. This process helps reducing the DB load when using IRIS during normal operation.

    "},{"location":"operations/access_control/groups/#removing-cases-from-the-group","title":"Removing cases from the group","text":"

    From within the group manager, go to the Cases access tab. Click on the red trash next to the case to remove and confirm the deletion.

    "},{"location":"operations/access_control/groups/#removing-a-group","title":"Removing a group","text":"

    A group can be deleted by clicking on its name in the list and then Delete at the bottom of the Info tab.

    "},{"location":"operations/access_control/users/","title":"Users","text":"

    Authentication

    Looking for authentication settings? It's here

    Whatever the authentication mechanism used (Local or LDAP), the users have to be declared in IRIS. This is done in Advanced > Access Control > Users.

    "},{"location":"operations/access_control/users/#adding-a-user","title":"Adding a user","text":"

    Head to Advanced > Access Control > Users and click Add user. All fields of the form are required. All information can be changed after the creation.

    Note

    Permissions and groups can be set once the user is created.

    Service accounts

    Service accounts users can use the API to perform any actions on the instance. They cannot login to the UI and they don't have a password.

    "},{"location":"operations/access_control/users/#editing-a-user","title":"Editing a user","text":"

    A user can be edited by clicking on its name or ID in Advanced > Access Control > Users. A window opens and display the user's information. Tabs at the top allows to configure multiple settings related to the user.

    "},{"location":"operations/access_control/users/#setting-permissions","title":"Setting permissions","text":"

    Permissions of a user cannot be set directly. They are inherited from the groups membership. The tab Permissions only displays the permissions the user has from its groups memberships. See Groups for more info.

    "},{"location":"operations/access_control/users/#setting-groups","title":"Setting groups","text":"

    Groups can be set by clicking on the Groups tab of the user's window and then Manage.

    A new window appear with the possibility to select the groups the user should belong to.

    After saving, the permissions of the user are updated. This can be verified in the Permissions tab.

    "},{"location":"operations/access_control/users/#setting-cases-access","title":"Setting cases access","text":"

    Cases access are usually set through groups membership. However for granularity they can be set per user. To set the access of a user on a case, click on the Cases access tab of the user's window and then Set case access.

    As for the Groups, a selector appear and allows to select one or multiple cases and the access to associate.

    Info

    Application of a case access is immediate, even if the user is logged in and browsing the case.

    Info

    Granular case access can also be set from a case itself, in Summary > Manage > Access.

    "},{"location":"operations/access_control/users/#deactivating-a-user","title":"Deactivating a user","text":"

    A user can be deactivated, which has the following impact:

    "},{"location":"operations/access_control/users/#deleting-a-user","title":"Deleting a user","text":"

    It is usually not possible to delete a user. This is to keep consistency in the database. A user can be deleted if it has done absolutely no actions on the platform. If a user leaves the organisation, it is recommended to rename the user and deactivate it.

    "},{"location":"operations/cases/case_operations/","title":"Case operations","text":""},{"location":"operations/cases/case_operations/#opening-a-case","title":"Opening a case","text":"

    To open a case from the dashboard, press Add case in the top right corner. Otherwise, go to the Manage Cases tab and press Add case in the top right corner.

    A new window appears, requesting additional information. The following information are required:

    The following information is optional:

    Once Create is clicked, the case is created and a popup ask whether to the get redirected to the case or to add a new one.

    "},{"location":"operations/cases/case_operations/#switching-between-cases","title":"Switching between cases","text":"

    Each case has its own context. To switch between cases/context, either click on the name of the current case at the top left, or click on the switch button on the top right.

    A popup appears and allows to select the case to switch to. By default the last 100 cases are displayed. To look further in the past, one can use the search bar. Press Save to validate the switch. The page reloads with the new context.

    "},{"location":"operations/cases/case_operations/#updating-a-case","title":"Updating a case","text":"

    A case metadata can be updated by going switching the case context and heading to Case > Summary. Clicking on Manage brings up a new window with the case metadata. The right pencil button allows to edit the metadata.

    The following information can be updated:

    "},{"location":"operations/cases/case_operations/#updating-the-access-of-a-case","title":"Updating the access of a case","text":"

    The access of a case can be updated by going to Case > Summary > Manage, and from the popup, clicking on the Access tab.

    Changes of access are immediately applied.

    "},{"location":"operations/cases/case_operations/#closing-a-case","title":"Closing a case","text":"

    A case can be closed by going to Case > Summary > Manage, and from the popup, clicking on the Close case button. Closing a case doesn't delete it and it can be reopened at any time. The case can also be modified after it has been closed.

    "},{"location":"operations/cases/case_operations/#getting-modifications-history-of-a-case","title":"Getting modifications history of a case","text":"

    The modifications history of a case can be retrieved by going to Case > Summary > Manage, and from the popup, clicking on the history icon next to the case name.

    "},{"location":"operations/cases/iocs/","title":"IOCs","text":"

    IOCs are observables that were identified during the investigation, or that led to the case creation upon monitoring activities.

    "},{"location":"operations/cases/iocs/#add-an-ioc","title":"Add an IoC","text":"

    An IoC object could be created by going to Case > IOC. Clicking on Add IOC in the top right corner brings up a new window for the IoC creation.

    A new window appears, requesting additional information. The following information is required:

    The following information is optional:

    Once Save is clicked, the ioc is created.

    "},{"location":"operations/cases/iocs/#update-an-ioc","title":"Update an IoC","text":"

    IoC object data can be updated by clicking on the IoC value in the Case > IOC table. A popup appears and allows to change required and non-required fields.

    Once Update is clicked, the IoC is updated.

    "},{"location":"operations/cases/iocs/#enrich-an-ioc","title":"Enrich an IoC","text":"

    IoC objects can be enriched in order to add valuable information to it.

    "},{"location":"operations/cases/iocs/#comment-an-ioc","title":"Comment an IoC","text":"

    To comment an IoC, one can right click on it, in the Case > IOC menu, and select Comment. A new pop-up appears and allows to leave comments. This is also achievable by clicking on the IoC value in the Case > IOC table, and by clicking on the Comment button.

    "},{"location":"operations/cases/iocs/#launch-a-module-on-an-ioc","title":"Launch a module on an IoC","text":"

    To have more information about modules, see the Modules section.

    A set of modules can be launched to enrich IoCs. To do so, one can right click on the IoC , in the Case > IOC table, and select the module of choice. This is also achievable by clicking on the IoC value in the Case > IOC table, by clicking the Option button, and selecting the desired module.

    The results of the module will appear in newly created tabs, in the IoC details. To view the tabs, click on the the IoC value.

    "},{"location":"operations/cases/iocs/#delete-an-ioc","title":"Delete an IoC","text":"

    This will permanently delete the IoC and its attributes

    To delete an IoC, one could either right click on the IoC, and select Delete, or click on the IoC value, and click on the Delete button.

    The IOC is only unlinked from the case if it references other cases

    "},{"location":"operations/cases/notes/","title":"Notes","text":"

    IRIS allows analysts to add notes to cases. Notes can be added to a case from the Notes tab. Notes are organized by groups. A note has to be within a group.

    "},{"location":"operations/cases/notes/#adding-a-group","title":"Adding a group","text":"

    To add a group, click on the Add note group button on the top right.

    The title of the group note can be edited by clicking direclty on it and typing the new title. Validated with the green checkmark.

    "},{"location":"operations/cases/notes/#adding-a-note","title":"Adding a note","text":"

    To add a note, click on the + button on the top right of the target note group. A new note is added to the group. To edit it, click on the note and type the new content.

    1. The title of the note. It is viewable in the group note list.
    2. The content editor. This is where the note should be written. The editor supports Markdown. The toolbar on top of the editor allows to format the text.
    3. The live preview of the note. This is how the note is rendered.
    4. The edit button. Clicking on it allows to edit or view the note.
    5. The zen button. Useless but allows to concentrate on the note.
    6. The comment button. Allows to set comments on the note.
    7. The options button. Allows to share the note and more.
    8. The minimize button. Allows to minimize the note, allowing to copy text from somewhere else.
    "},{"location":"operations/cases/tasks/","title":"Tasks","text":"

    Tasks allow incident handlers to split the workload into unit tasks, and to assign them to the team members.

    "},{"location":"operations/cases/tasks/#add-a-task","title":"Add a task","text":"

    A task can be created by going to Case > Tasks. Clicking on Add Task in the top right corner brings up a new window for the task creation.

    A new window appears, requesting additional information. The following information is required:

    The following information is optional:

    Once Save is clicked, the task is created.

    "},{"location":"operations/cases/tasks/#update-a-task","title":"Update a task","text":"

    Task metadata can be updated by clicking on the task title in the Case > Tasks table. A popup appears and allows to change required and non-required fields.

    Once Update is clicked, the task is updated.

    "},{"location":"operations/cases/tasks/#comment-a-task","title":"Comment a task","text":"

    Tasks can be commented. This provide the ability for analysts to give more in-deepth information on the task execution (what did they do, how did they do, what are the results, etc.)

    To comment a task, one can either right click on the task line and select Comment, or click on the task title, and click on the Comment button. A new windows appears and allows to add comments to the task.

    Once Comment is clicked, in the last window, a comment is added to the task. Comments are editable and removable.

    "},{"location":"operations/modules/","title":"Introduction","text":"

    New types of modules are introduced in IRIS v1.4.0

    IRIS can be extended with modules. They can be split in two types:

    Modules (or DIM - DFIR-IRIS Modules) are actually Python packages which must be installed in the Python environment of iris-webapp and the worker (see Quick Start). Once installed in the Python environment, modules can be managed in Advanced > Modules.

    Info

    This section is only available for users with the Admin role.

    By default IRIS is shipped with multiple modules.

    "},{"location":"operations/modules/mod_management/","title":"Management","text":"

    To add a module, the user can click on the \"+\" button:

    Then the user must enter the name of the pre-installed module. The name of the pip package must be used.

    If everything is ok, the module will appear on the list. It is currently disabled, and needs configuration before it can be enabled. To do so, the user can click on the module's name:

    A new text box appears, showing information about the module, and a list of parameters to configure. Each mandatory parameter must be configured to enable the module.

    After configuring all the mandatory parameters, the \"Enable button\" is revealed and the user can finally enable the module.

    That's all! The user can confirm in the summary that the module is indeed enabled and ready to use.

    Finally, the user can either disable or remove the module by clicking on the according buttons.

    Now that the module is configured and enabled, let's see how we can use it!

    NB: As a temporary fix, after adding and configuring a module, one must restart the IRIS services (dockers) else the worker won't have the module installed properly.

    "},{"location":"operations/modules/mod_management/#how-to-use-the-module","title":"How to use the module","text":"

    As stated in the beginning, a module extends the capabilities of IRIS. For now, it allows importing evidences of your needs into what we call a pipeline, where data will be handled in the module (checking, parsing, ingestion...). In our provided module, IrisEVTXModule ingest EVTX files, parse them as JSON, and send the results to a Splunk instance using its HTTP event collector (HEC) endpoint.

    In IRIS, the files are always imported in the context of a case. To import a file, the user can click on Manage cases then Update tab.

    In Processing pipeline, the user can pick a pipeline that will send the files to the wanted module. In our example, EVTX pipeline refers to the IrisEVTXModule module. Below, the user can fill the arguments needed by the according pipeline. Arguments can be optional. Finally, the user can import one or several files and click Update to start their processing by the module.

    You can see in the picture below that the user will import four EVTX files.

    The user can follow the upload of the different files with their respective progress bars.

    Once uploaded, the status of the task can be observed on the DIM Tasks page.

    Clicking on a Task ID shows information on the task processing.

    After the processing of the files by the module, the list of the imported files is stored in the Evidences tab of the according case.

    "},{"location":"operations/modules/natives/IrisMISP/","title":"Module IRIS MISP","text":"

    Introduced in IRIS v1.4.0

    This module offers an interface with MISP and IRIS to automatically enrich IOCs with MISP insight.

    The source code is available here. It is installed by default but needs to be configured to be enabled.

    Note

    The module is in its early stage and new features will be added over time.

    "},{"location":"operations/modules/natives/IrisMISP/#features","title":"Features","text":"

    Two types of enrichement mecanism are proposed :

    The following types of IOCs are handled by the module :

    The insight request on an IOC not handled is simply ignored.

    The insights take the form of attributes added to the IOC. They are based on configurable templates.

    "},{"location":"operations/modules/natives/IrisMISP/#configuration","title":"Configuration","text":"

    The behavior of the module can be configured as needed. Head to the Advanced > Modules > IrisMISP to change it.

    "},{"location":"operations/modules/natives/IrisMISP/#misp-configuration","title":"MISP configuration","text":"

    At the time, only one MISP can be added. Future version might handled more than one MISP. The expected structure is the following :

    {\n\"name\": \"Public_MISP\", \"type\":\"public\", \"url\":[\"https://testmisp\"],\n\"key\":[\"<apikey>\"], \"ssl\":[false]\n}\n
    "},{"location":"operations/modules/natives/IrisVT/","title":"Module IRIS VT","text":"

    Introduced in IRIS v1.4.0

    This module offers an interface with VirusTotal and IRIS to automatically enrich IOCs with VT insight. The source code is available here. It is installed by default but needs to be configured to be enabled.

    "},{"location":"operations/modules/natives/IrisVT/#features","title":"Features","text":"

    Two types of enrichment mechanism are proposed :

    The following types of IOCs are handled by the module :

    The insight request on an IOC not handled is simply ignored.

    Two types of insights are proposed :

    "},{"location":"operations/modules/natives/IrisVT/#configuration","title":"Configuration","text":"

    The behavior of the module can be configured as needed. Head to the Advanced > Modules > IrisVT to change it.

    "},{"location":"operations/modules/natives/IrisWebHooks/","title":"Module IRIS Webhooks","text":"

    This module offers webhooks support for IRIS. It can be configured to send almost any events to to an external service supporting webhooks, such as Discord, Slack or Microsoft Teams. It can also be used with automation tools such as Tines and Shufle to further automate IRIS. The source code is available here.

    "},{"location":"operations/modules/natives/IrisWebHooks/#features","title":"Features","text":"

    Slack Example

    "},{"location":"operations/modules/natives/IrisWebHooks/#configuration","title":"Configuration","text":"

    The expected configuration is a JSON file, following the structure :

    {   \"instance_url\": \"<IRIS_INSTANCE_URL>\",\n\"webhooks\": [\n{\n\"name\": \"Name of the webhook for internal reference only\",\n\"active\": false,\n\"trigger_on\": [<LIST OF HOOKS TO LISTEN TO>],\n\"request_url\": \"<URL OF THE WEBHOOK>\",\n\"use_rendering\": true,\n\"request_rendering\": \"<RENDERING TYPE OF THE MESSAGE>\", \"request_body\": {<BODY OF THE REQUET TO SEND>}\n},\n{\n\"name\": \"Another hook\",\n\"active\": false,\n\"use_rendering\": false,\n\"trigger_on\": [<LIST OF HOOKS TO LISTEN TO>],\n\"request_url\": \"<URL OF THE WEBHOOK 2>\",\n\"request_rendering\": \"<RENDERING TYPE OF THE MESSAGE>\", \"request_body\": {<BODY OF THE REQUEST TO SEND 2>}\n}\n]\n}\n
    "},{"location":"operations/modules/natives/IrisWebHooks/#checking-iris-hooks-registration","title":"Checking IRIS hooks registration","text":"

    Each time a webhook is added, the module subscribes to the specified hooks. After saving the configuration, one can check the registration was successful by filtering the Registered hooks table (don't forget to refresh the table).

    "},{"location":"operations/modules/natives/IrisWebHooks/#examples-without-rendering","title":"Examples without rendering","text":"

    The following example is a combination of webhooks that can be used to further automate IRIS. It uses Tines as an example, but this is reproductible with any automation tool that can sent HTTP requests. A Tines story is created and is set up to receive a webhook, such as https://anothertest.tines.io/webhook/xxxx/xxxxx. In this scenario, two IRIS webhooks are added:

    We use the same Tines story and thus Tines webhook for both and dispatch the incoming request depending on its parameters.

    "},{"location":"operations/modules/natives/IrisWebHooks/#todo","title":"TODO","text":""},{"location":"operations/modules/natives/IrisWebHooks/#examples-using-rendering","title":"Examples using rendering","text":"

    The following is an example of combined webhooks configuration. It can be directly imported in the module with the import feature. Please note that after import, the configuration should be opened and change to match your URL webhook receiver.

    Download webhooks combined configuration example

    "},{"location":"operations/modules/natives/IrisWebHooks/#discord","title":"Discord","text":"Discord webhook example - selection of events
    {   \"instance_url\": \"https://iris.local\",\n\"webhooks\": [\n{\n\"name\": \"Discord\",\n\"trigger_on\": [\n\"on_postload_ioc_create\",\n\"on_postload_ioc_update\",\n\"on_postload_note_create\",\n\"on_postload_note_update\"\n],\n\"request_url\": \"https://discord.com/api/webhooks/XXXX/XXXX\",\n\"request_rendering\": \"markdown\", \"request_body\": {\n\"embeds\": [{\n\"description\" : \"%DESCRIPTION%\",\n\"title\" : \"%TITLE%\"\n}]\n}\n}\n]\n}\n
    "},{"location":"operations/modules/natives/IrisWebHooks/#slack","title":"Slack","text":"Slack webhook example - all events
    {   \"instance_url\": \"https://iris.local\",\n\"webhooks\": [\n{\n\"name\": \"Slack\",\n\"trigger_on\": [\n\"all\"\n],\n\"request_url\": \"https://hooks.slack.com/services/<XXX>/<XXX>/<XXX>\",\n\"request_rendering\": \"markdown_slack\",\n\"request_body\": {\n\"text\": \"%TITLE%\",\n\"blocks\": [\n{\n\"type\": \"section\",\n\"text\": {\n\"type\": \"mrkdwn\",\n\"text\": \"*%TITLE%*\"\n}\n},\n{\n\"type\": \"section\",\n\"block_id\": \"section567\",\n\"text\": {\n\"type\": \"mrkdwn\",\n\"text\": \"%DESCRIPTION%\"\n}\n}\n]\n}\n}\n]\n}\n
    "},{"location":"operations/modules/natives/IrisWebHooks/#troubleshooting","title":"Troubleshooting","text":"

    Webhooks receivers are expecting specific message formatting to successfully process them. Please carefully read their documentations.

    The module only handles JSON POST for the moment. If the target webhook receiver needs another type of request, please contact us so we can add it.

    As any IRIS module, IrisWebhooks is logged into DIM Tasks. You can check the status of the requests made in these. Go to DIM Tasks and then filter with webhooks. You can then check details info by clicking in the Task ID. More info might be available in the Docker worker logs depending on the situation.

    "},{"location":"operations/modules/natives/IrisWebHooks/#important-notes-and-know-issues","title":"Important Notes and know issues","text":""},{"location":"python_client/","title":"Introduction","text":"

    dfir_iris_client offers a Python interface to communicate with IRIS.

    It relies exclusively on the API, which means output of the methods are the same as specified in the API reference.

    "},{"location":"python_client/#installation","title":"Installation","text":"

    It can be easily with pip : pip3 install dfir_iris_client.

    The source code of the project is available here.

    "},{"location":"python_client/#versions","title":"Versions","text":"

    The Python client version follows the API versions (until the patch level). Meaning for API v1.0.1, one need to install dfir_iris_client-1.0.1.

    "},{"location":"python_client/#examples","title":"Examples","text":"

    Examples of usage are available here.

    "},{"location":"python_client/#documentation","title":"Documentation","text":"

    The documentation of the client is available on client.docs.dfir-iris.org.

    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

    This documentation serves as a comprehensive guide to the IRIS web application operations, modules, and development.

    If you're new to IRIS, we recommend starting with our Getting Started guide to learn the basics.

    For those who want to try out IRIS easily, we offer a free demonstration instance of the rolling beta version here.

    Our documentation is constantly evolving, so if you don't find what you're looking for, please contact us so we can add the missing piece.

    "},{"location":"#what-is-iris","title":"What is IRIS?","text":"

    IRIS is a collaborative platform for incident response analysts that helps to share investigations at a technical level. It's a web application that can be installed on a fixed-server or on a laptop for roaming investigations where internet might not be available.

    IRIS was born out of the struggle to share long and complex investigations among analysts.

    The project is available on our Github organization.

    Disclaimer

    IRIS is still in its early stages. It can already be used in production, but please set backups of the database and DO NOT expose the interface on the Internet. We highly recommend the use of a private dedicated and secured network.

    "},{"location":"changelog/","title":"Changelog","text":"

    For upgrades instructions, please see the Upgrades page.

    "},{"location":"changelog/#v237-december-14-2023","title":"v2.3.7 December 14, 2023","text":""},{"location":"changelog/#whats-changed","title":"What's Changed","text":"

    Fixed

    Improved

    Full Changelog

    "},{"location":"changelog/#v236-december-7-2023","title":"v2.3.6 December 7, 2023","text":""},{"location":"changelog/#whats-changed_1","title":"What's Changed","text":"

    Fixed

    Full Changelog

    "},{"location":"changelog/#v235-november-30-2023","title":"v2.3.5 November 30, 2023","text":""},{"location":"changelog/#whats-changed_2","title":"What's Changed","text":"

    Fixed

    Full Changelog

    "},{"location":"changelog/#v234-november-29-2023","title":"v2.3.4 November 29, 2023","text":"

    A severe bug has been introduced in this version. Please upgarde to v2.3.5.

    "},{"location":"changelog/#whats-changed_3","title":"What's Changed","text":"

    Added

    Fixed

    \u2757 The layout of the reporting has slightly changed. Custom report templates might not work anymore. You can use https://<server>/case/export?cid=<case_id> to get all the possible fields.

    Full Changelog

    "},{"location":"changelog/#v233-october-5-2023","title":"v2.3.3 October 5, 2023","text":""},{"location":"changelog/#whats-changed_4","title":"What's Changed","text":"

    Fixed

    @Scriptception made their first contribution in 313

    Full Changelog

    "},{"location":"changelog/#v232-august-2-2023","title":"v2.3.2 August 2, 2023","text":""},{"location":"changelog/#whats-changed_5","title":"What's Changed","text":"

    Fixed

    Patches a critical issue corrupting files uploaded to the DataStore via the IOC option or when a password is set

    Full Changelog

    "},{"location":"changelog/#v231-july-23-2023","title":"v2.3.1 July 23, 2023","text":""},{"location":"changelog/#whats-changed_6","title":"What's Changed","text":"

    Improved

    Fixed

    Full Changelog

    "},{"location":"changelog/#v230-july-09-2023","title":"v2.3.0 July 09, 2023","text":""},{"location":"changelog/#whats-changed_7","title":"What's Changed","text":"

    Added

    Fixed

    Full Changelog

    "},{"location":"changelog/#v223-june-19-2023","title":"v2.2.3 June 19, 2023","text":""},{"location":"changelog/#whats-changed_8","title":"What's Changed","text":"

    Added

    Fixed

    Full Changelog

    "},{"location":"changelog/#v222-may-30-2023","title":"v2.2.2 May 30, 2023","text":""},{"location":"changelog/#whats-changed_9","title":"What's Changed","text":"

    Added

    Fixed - Delete character escaping for passwords by @juadde in #253 - Case template of tasks without tags - Shortening of case names during updates - Bad handling of certain requests without CID - Deletion of assets related to alerts once merge into a case

    Full Changelog

    "},{"location":"changelog/#v221-may-24-2023","title":"v2.2.1 May 24, 2023","text":""},{"location":"changelog/#whats-changed_10","title":"What's Changed","text":"

    Note 1: This version contains a security fix for iris-web (see CVE-2023-30615) Note 2: on_postload_case_info_update hook has been renamed to on_postload_case_update

    Added

    Fixed

    Full Changelog

    "},{"location":"changelog/#v220-may-22-2023","title":"v2.2.0 May 22, 2023","text":""},{"location":"changelog/#whats-changed_11","title":"What's Changed","text":"

    Added

    Fixes

    New Contributors

    Full Changelog

    "},{"location":"changelog/#v210-may-15-2023","title":"v2.1.0 May 15, 2023","text":"

    If you are using custom SSL certificates, please read the upgrade instructions when upgrading from previous versions.

    "},{"location":"changelog/#whats-changed_12","title":"What's Changed","text":"

    Added

    Fixed

    New Contributors

    Full Changelog

    "},{"location":"changelog/#v202-april-18-2023","title":"v2.0.2 April 18, 2023","text":""},{"location":"changelog/#whats-changed_13","title":"What's Changed","text":"

    Fixed * Update case_notes_db.py for bug fix #200 by @LoneWolf-96 in #208 * Do not escape_filter_chars for NTLM username by @juadde in #212 * docker-compose cleanup by @juadde in #213 * Listening port not being propagated in nginx docker

    New Contributors * @LoneWolf-96 made their first contribution in #208 * @juadde made their first contribution in #212

    Full Changelog

    "},{"location":"changelog/#v201-april-05-2023","title":"v2.0.1 April 05, 2023","text":""},{"location":"changelog/#whats-changed_14","title":"What's Changed","text":"

    Fixed [FIX] Additional table header in case management breaking proper loading of data in #206

    Full Changelog

    "},{"location":"changelog/#v200-march-26-2023","title":"v2.0.0 March 26, 2023","text":""},{"location":"changelog/#whats-changed_15","title":"What's Changed","text":"

    In addition to the features listed below, we are changing the way we are issuing releases. From now on, IRIS follows the Semantic Versioning 2.0 guidelines. The code ready for production is always tagged with a version number. alpha and beta versions are not production-ready.

    Do not use the master branch in production.

    A website with the current development version is also provided and freely accessible. It serves as a beta before public releases.

    Added

    Improved

    Fixed

    Full Changelog

    "},{"location":"changelog/#v145-june-9-2022","title":"v1.4.5 June 9, 2022","text":"

    What's Changed

    Full Changelog

    Notes: Changes are made to the Nginx docker to allow upload of big files, hence specific upgrades are needed and auto-updates is not yet supported for this version. Please see the upgrades instruction for more details.

    "},{"location":"changelog/#v144-may-18-2022","title":"v1.4.4 May 18, 2022","text":"

    What's Changed

    Full Changelog

    "},{"location":"changelog/#v143-may-13-2022","title":"v1.4.3 May 13, 2022","text":"

    What's changed

    Full Changelog

    "},{"location":"changelog/#v142-april-22-2022","title":"v1.4.2 April 22, 2022","text":"

    Improvements :

    Fixes :

    "},{"location":"changelog/#v141-april-8-2022","title":"v1.4.1 April 8, 2022","text":""},{"location":"changelog/#v140-april-6-2022","title":"v1.4.0 April 6, 2022","text":"

    A bug fixe exists for this version. See v1.4.3

    "},{"location":"changelog/#v131-march-19-2022","title":"v1.3.1 March 19, 2022","text":""},{"location":"changelog/#v130-january-24-2022","title":"v1.3.0 January 24, 2022","text":""},{"location":"changelog/#v121-december-31-2021","title":"v1.2.1 December 31, 2021","text":""},{"location":"contact/","title":"Contacting us","text":"

    You can directly contact us, should you need direct support, a demo, further information or anything else related to the project.

    contact@dfir-iris.org

    Discord

    Twitter

    "},{"location":"credits/","title":"Credits","text":"

    IRIS uses dozen of OS modules and this list is not exhaustive. If you developped something which is used in IRIS and does not figures here, you can contact us.

    "},{"location":"getting_started/","title":"Quick Start","text":"

    The most straightforward and recommended way to use IRIS is with Docker. This is presented here.

    Disclaimer

    IRIS is in its early stage. It can already be used in production, but please set backups of the database and DO NOT expose the interface on the Internet. We highly recommended the use of a private dedicated and secured network.

    "},{"location":"getting_started/#pre-requisites","title":"Pre-requisites","text":""},{"location":"getting_started/#hardware","title":"Hardware","text":"

    IRIS does not require a lot of resources, and it can be run on a small laptop (4 cores, 8Gb of RAM). However, for large a organization and heavy usage, it will need to be significantly scaled up. We don't have benchmarks yet, but keep in mind that the database can grow rapidly and modules can require more resources depending on their purposes.

    "},{"location":"getting_started/#docker","title":"Docker","text":"

    Docker and docker compose are needed to build and run the project. Depending on the OS you will find all the information to install them on the official website of Docker.

    The platform is officially supported on most Linux and MacOS. While it should work on Windows, some path needed by the containers to store permanent files might need to be changed in the dockerfiles.

    "},{"location":"getting_started/#versioning","title":"Versioning","text":"

    Starting from version 2.0.0, Iris is following the Semantic Versioning 2.0 guidelines. The code ready for production is always tagged with a version number. alpha and beta versions are not production-ready.

    Do not use the master branch in production.

    "},{"location":"getting_started/#build-and-run","title":"Build and Run","text":"

    To build and run IRIS, follow these steps:

    1. Clone the iris-web repository:

      git clone https://github.com/dfir-iris/iris-web.git\ncd iris-web\n
    2. Check out the latest non-beta tagged version:

      git checkout v2.3.7\n
    3. Copy the environment file

      cp .env.model .env\n

      Warning

      The default configuration is suitable for testing only. To configure IRIS for production, see the configuration section.

    4. Build the Docker containers:

      docker-compose build\n
    5. Start IRIS:

      docker-compose up\n

    IRIS should now be available on the host interface, port 443, using HTTPS protocol by default. You can access it by navigating to https://hostip in your web browser.

    By default, an administrator account is created when IRIS is started for the first time. The password is printed in the console output. You can search for WARNING :: post_init :: create_safe_admin :: >>> in the logs to find the password. Running docker compose logs app | grep 'admin' should help to find it.

    If you want to define an admin password at the first start, you can create and define the environment variable IRIS_ADM_PASSWORD in the .env. This has no effect once the administrator account is created.

    Note that IRIS is split into five Docker services, each with a different role:

    Each service can be built independently, which is useful when developing. In this QuickStart, all services are built at once.

    "},{"location":"getting_started/#additional-configuration","title":"Additional configuration","text":"

    Please see configuration for more details.

    "},{"location":"getting_started/#kubernetes","title":"Kubernetes","text":"

    For enterprises wishing to run their instance of IRIS, utilizing the projects official Helm charts and/or Kustomize manifests, allows them to significantly enhance their deployment and management, presenting a powerful solution to streamline their IRIS deployment and management processes, efficiently running across a cluster of machines, ensuring high availability and seamless scaling as demand fluctuates.

    The deploy directory in the iris-web GitHub repository provides a practical starting point for deploying IRIS on their preferred managed k8s platform. We've created two variants: eks and gke, feel free to customize each with your own values.

    For more details, please visit the deploy directory on GitHub: deploy

    "},{"location":"resources/","title":"Resources","text":"

    This page is a collection of external resources to help you get started with IRIS and integrate it into your workflow. Please note that some of these resources may be outdated. If you want to add your own resources, please open a pull request or contact us.

    "},{"location":"resources/#blog-posts","title":"Blog posts","text":""},{"location":"resources/#iris-modules","title":"IRIS Modules","text":""},{"location":"resources/#videos","title":"Videos","text":""},{"location":"roadmap/","title":"Roadmap","text":"

    Note of 25-05-2023

    IRIS is growing both in code and interestes. To future-proof the project, we have decided to pause the development of new features and focus on the core functionalities and stability for a while. This includes a major refactoring of the codebase. We will still fix bugs and security issues.

    We do not provide a long-term roadmap to prevent any frustration and unmet expectations. It is constantly evolving with feedbacks we receive.

    We've thus moved it within a Github project. You can check it here.

    "},{"location":"security-advisories/","title":"Security Advisories","text":"

    This page lists all security advisories that have been published for the code released by DFIR-IRIS.

    "},{"location":"security-advisories/#cve-2023-50712-dec-18-2023","title":"CVE-2023-50712 Dec 18, 2023","text":"CVE ID Github ID Severity Impacted product CVE-2023-30615 GHSA-593r-747g-p92p Moderate - CVSS3 4.6/10 iris-web"},{"location":"security-advisories/#description","title":"Description","text":"

    A stored Cross-Site Scripting (XSS) vulnerability has been identified in iris-web, affecting multiple locations in versions prior to v2.3.7. The vulnerability may allow an attacker to inject malicious scripts into the application, which could then be executed when a user visits the affected locations. This could lead to unauthorized access, data theft, or other related malicious activities.

    An attacker need to be authenticated on the application to exploit this vulnerability.

    "},{"location":"security-advisories/#affected-versions","title":"Affected versions","text":""},{"location":"security-advisories/#fixed-versions","title":"Fixed versions","text":""},{"location":"security-advisories/#workarounds","title":"Workarounds","text":"

    No workaround is available.

    "},{"location":"security-advisories/#acknowledgment","title":"Acknowledgment","text":"

    Thanks to Leonard Rapp (G DATA Advanced Analytics GmbH) for the responsible disclosure.

    "},{"location":"security-advisories/#cve-2023-30615-may-24-2023","title":"CVE-2023-30615 May 24, 2023","text":"CVE ID Github ID Severity Impacted product CVE-2023-30615 GHSA-gc6j-6276-2m49 Moderate - CVSS3 4.6/10 iris-web"},{"location":"security-advisories/#description_1","title":"Description","text":"

    A stored Cross-Site Scripting (XSS) vulnerability has been identified in iris-web, affecting multiple locations in versions prior to v2.2.1. The vulnerability allows an attacker to inject malicious scripts into the application, which are then executed when a user visits the affected locations. This can lead to unauthorized access, data theft, or other related malicious activities.

    An attacker need to be authenticated on the application to exploit this vulnerability.

    "},{"location":"security-advisories/#affected-versions_1","title":"Affected versions","text":""},{"location":"security-advisories/#fixed-versions_1","title":"Fixed versions","text":""},{"location":"security-advisories/#workarounds_1","title":"Workarounds","text":"

    No workaround is available.

    "},{"location":"support_us/","title":"Support us","text":"

    As a free and open source project, we rely on the support of our community to continue development and improve our platform. If you find the platform useful and would like to help us sustain and grow, you may consider supporting us financially through OpenCollective.

    Support us

    "},{"location":"zqa/","title":"Q & A","text":""},{"location":"zqa/#general-questions","title":"General questions","text":""},{"location":"zqa/#which-version-should-i-install","title":"Which version should I install?","text":"

    The master branch is stable as all the development is done under the develop branch and merged once ready. To ease the identification, each new version is tagged and a new release is published. We recommend using these. git checkout <tagged_version>

    "},{"location":"zqa/#is-the-project-maintained","title":"Is the project maintained?","text":"

    Yes, IRIS is under heavy development. We are adding more and more features, led by feedbacks from the community.

    "},{"location":"zqa/#what-is-the-future-of-the-project","title":"What is the future of the project?","text":"

    We aim to make it evolve as much as possible with the help of the community. We have long term goals to integrate it seamlessly with project like MISP and other OS project, but we don't provide any commitment on how and when to avoid any unmet expectations. For a short term roadmap, you can head to the Github project.

    "},{"location":"zqa/#how-can-i-contact-the-dfir-iris-team","title":"How can I contact the DFIR-IRIS team?","text":"

    You can reach us on discord, Twitter or by email.

    "},{"location":"zqa/#cases","title":"Cases","text":""},{"location":"zqa/#can-i-recover-a-deleted-case","title":"Can I recover a deleted case?","text":"

    No. Cases are deleted from the database and changes are committed. There is no coming back unless you have made backups of the database (which we recommend).

    "},{"location":"zqa/#can-i-recover-a-deleted-case-object","title":"Can I recover a deleted case object?","text":"

    No. Every object such as IOCs, assets, events, notes, etc are immediately deleted from the database and changes are committed.

    "},{"location":"zqa/#can-i-add-a-new-asset-type","title":"Can I add a new asset type?","text":"

    Yes. With a user that have administrative rights, go to Advanced > Case Objects.

    "},{"location":"zqa/#can-i-add-a-new-ioc-type","title":"Can I add a new IOC type?","text":"

    Yes. Starting from v1.3.0, IOC types can be manipulated. Head to Advanced > Case Objects

    "},{"location":"zqa/#can-i-add-new-fields-to-case-objects-such-as-iocs-assets-etc","title":"Can I add new fields to case objects such as IOCs, Assets, etc?","text":"

    Yes. Starting from v1.4.0, all case objects can be extended thanks to custom attributes. With a user that have administrative rights, go to Advanced > Custom Attributes.

    "},{"location":"zqa/#can-i-search-into-custom-attributes-fields","title":"Can I search into custom attributes fields?","text":"

    Not for now. The searches in each case objects page are done client-side, and the attributes are not fetched. We will however implement a server side search in next releases.

    "},{"location":"zqa/#can-i-create-two-cases-with-the-same-name-for-the-same-customer","title":"Can I create two cases with the same name for the same customer?","text":"

    Yes. Cases are identified with a unique number, so they can have the same name.

    "},{"location":"zqa/#can-i-restrict-the-view-of-case-to-a-set-of-users","title":"Can I restrict the view of case to a set of users?","text":"

    Yes it is since v2.0.0. See Access control.

    "},{"location":"zqa/#can-i-change-the-name-or-customer-of-an-existing-case","title":"Can I change the name or customer of an existing case?","text":"

    Yes it is since v2.0.0.

    "},{"location":"zqa/#operations","title":"Operations","text":""},{"location":"zqa/#what-is-the-password-policy-can-it-be-changed","title":"What is the password policy? Can it be changed?","text":"

    Before v1.4.5, the password policy is hardcoded and cannot be changed. It should be 12 characters minimum and contains a capital letter and a number.

    "},{"location":"zqa/#can-i-change-my-profile-picture","title":"Can I change my profile picture?","text":"

    No, not for now. This wasn't a priority for us, it will be released in future versions.

    "},{"location":"zqa/#i-lost-the-administrator-password-can-i-recover-it","title":"I lost the administrator password, can I recover it?","text":"

    Passwords are hashed so they can't be recovered. But you can change it. Please see changing a lost password.

    "},{"location":"zqa/#can-i-delete-a-user","title":"Can I delete a user?","text":"

    No. To keep consistencies in the database, users unfortunately cannot be deleted if they have done some activities. You can however disable them to prevent them appearing in the UI and connecting to the plafeform.

    "},{"location":"zqa/#can-i-delete-a-customer","title":"Can I delete a customer?","text":"

    No. To keep consistencies in the database, customers unfortunately cannot be deleted if they are linked to cases.

    "},{"location":"zqa/#can-i-prevent-backrefs-of-assets-and-iocs","title":"Can I prevent backrefs of assets and IOCs?","text":"

    No. It might be possible in future versions but for now it is better to spin up a new instance for restricted cases. The backref is however automatically disabled for performance reasons, for cases with more than 300 assets. We are working on a more efficient way to backref.

    "},{"location":"zqa/#my-report-template-is-not-generated-and-generates-an-error","title":"My report template is not generated and generates an error","text":"

    Please triple check typos in tags as there is no fault tolerance. You can reach us in case of troubles.

    "},{"location":"zqa/#integration","title":"Integration","text":""},{"location":"zqa/#can-i-enrich-iocs-with-external-sources","title":"Can I enrich IOCs with external sources?","text":"

    Starting from v1.4.0, it is now possible to easily develop module to enrich case objects. A module Iris VT and IRIS MISP are already provided.

    "},{"location":"zqa/#is-there-an-api-client","title":"Is there an API client?","text":"

    Yes, you can find it on our Github.

    "},{"location":"zqa/#security","title":"Security","text":""},{"location":"zqa/#can-i-restrict-cases","title":"Can I restrict cases?","text":"

    Yes it is since v2.0.0. See Access control.

    "},{"location":"zqa/#can-i-expose-iris-on-the-internet","title":"Can I expose IRIS on the Internet?","text":"

    NO! Please don't. This platform should only be accessible in a restricted environment.

    "},{"location":"zqa/#i-found-a-security-issue-can-i-have-a-bounty","title":"I found a security issue, can I have a bounty?","text":"

    No - IRIS is free and open source so there is no bounty. Please report it as soon as possible so we can fix it.

    "},{"location":"zqa/#misc","title":"MISC","text":""},{"location":"zqa/#what-does-iris-stand-for","title":"What does IRIS stand for?","text":"

    Originally Incident Response Investigation System. But it can be whatever you want really.

    "},{"location":"development/","title":"Development","text":"

    This section is under construction and more elements will be added over time

    This documentation is not a detailed how-to develop IRIS. It gives some insights to help understand the basic code of the project and how to contribute.

    "},{"location":"development/#general-repositories-conventions","title":"General repositories conventions","text":""},{"location":"development/#branches","title":"Branches","text":"

    We are using the Gitflow Workflow to manage our git branches. In a nutshell :

    "},{"location":"development/#commits","title":"Commits","text":"

    The commits convention is the following :

    "},{"location":"development/#sections","title":"Sections","text":"

    The following sections are available in this documentation :

    "},{"location":"development/code-tips/","title":"Coding tips","text":""},{"location":"development/code-tips/#routes","title":"Routes","text":"

    IRIS does not defines a separate API for users, meaning the HTML pages are actually using the API themselves. Routes don't need to handle the authentication and roles. These are handles by wrappers (see snippets below).

    "},{"location":"development/code-tips/#page-route","title":"Page route","text":"

    A page returns an HTML content and should use the following code structure : Example of page route

    @blueprint.route('/a/good/route', methods=['GET']) # (1)\n@login_required # (2)\ndef view_a_good_route(caseid, url_redir):  # (3)\nif url_redir:\nreturn redirect(url_for('bluprintname.method_name', cid=caseid))  # (4)\n# route code \nreturn render_template(\"a_good_route.html\", variable_1=var_1, ...)  # (5)\n

    1. This defines which URI the route is handling as well as the methods it supports (ie GET, POST, etc). In IRIS, we try to limit one method per route.
    2. This defines the security of the endpoint. @login_required is used for users page and @admin_login_required is used for admin restricted pages.
    3. caseid and url_redir are variable provided by @login_required and @admin_login_required wraps. caseid indicates which case ID the user tried to access the route with. url_redir indicates the caseid provided wasn't valid and a redirection is needed.
    4. In case a redirection is needed, provide the URL to which the redirection should be done. It's often the page method itself except for modales.
    5. A page route needs to return an HTML template. variable_1 is a value that can be accessed from within the template itself. More variables can be added, or not at all.
    "},{"location":"development/code-tips/#api-route","title":"API route","text":"

    An API route returns a JSON content. Two types are pre-defined and should be used : Standard API returns

    response_success(msg=\"A success message\", data=<data associated with the success feedback>)\nresponse_error(msg=\"An error message\", data=<data associated with the error feedback>, status=<status code, by default 400>)\n

    Below is an example of standard API route. Example of page route

    @blueprint.route('/a/good/api_route', methods=['GET']) # (1)\n@api_login_required # (2)\ndef view_a_good_route(caseid):  # (3)\n# API route code \nreturn response_success(\"ok\", data=my_data_object)  # (4)\n

    1. This defines which URI the route is handling as well as the methods it supports (ie GET, POST, etc). In IRIS, we try to limit one method per route.
    2. This defines the security of the endpoint. @api_login_required is used for users API endpoints and @api_admin_required is used for admin restricted endpoints.
    3. caseid is provided @api_login_required and @api_admin_required wraps. It indicates which case ID the user tried to access the endpoint with.
    4. One of the standard return defined above.
    "},{"location":"development/db-migration/","title":"DB Migrations","text":"

    In case a DB migration is needed, you need to provide an alembic migration script.

    Test your migration

    Please try out your migration as this is an important piece of the upgrades. Spin up an old version of IRIS, input some data and then try to start your new version. Ensure that everything is migrated as expected.

    In a terminal and from within the IRIS virtual env :

    1. Go to source
    2. Issue the following command : alembic -c app/alembic.ini revision -m \"A few words to describe your changes\"

    This creates a new revision file source > app > alembic > versions. It's a Python file that basically describes what needs to be updated DB-wise. You can take example from the ones we already have generated in the same folder.

    Hint

    During your tests you might face the issue that Alembic does not apply your changes after you executed it once. It's because it keeps tracks of the latest applied revision in a table alembic_version. It doesn't know you changed the revision file. In that case the trick is to connect to the DB, and then delete the entry in the alembic_version. This will force it to reapply all revisions at startup. If you're using the DB docker you can use the following:

    "},{"location":"development/environment/","title":"Setup","text":"

    It follows an issue raised on the Github of the project.

    It recommends the use of a hybrid development environment, as most of the time only the web-app needs to be changed:

    "},{"location":"development/environment/#web-app","title":"Web-app","text":"

    For the webapp configuration, a specific .ini need to be created.

    That's the only configuration change needed for the app to run outside docker. The docker.priv.ini is already excluded in gitignore.

    Then Pycharm need to be setup with a dedicated environment, by adding a new configuration:

    To have pylint, right click on source in the directory tree and mark directory as > sources root. The requirements then need to be installed. Pycharm should detect the requirements.txt and propose to install the dependencies. Otherwise they can be installed with the following command (issued in the virtual environment) : pip3 install -r source\\requirements.txt

    "},{"location":"development/environment/#run","title":"Run","text":"
    1. Spin up the docker db docker-compose up db
    2. Run the Pycharm configuration you created
    3. The interface should be accessible on http://127.0.0.1:8000 (and https://127.0.0.1:4433 if you started the nginx docker)

    IRIS can now be developed and debugged on the fly.

    "},{"location":"development/environment/#tests-in-docker","title":"Tests in docker","text":"

    Once the code is working by running on Pycharm, we highly recommend testing it on Docker. To do so, the app docker need to be erased and rebuilt.

    1. docker-compose rm app
    2. docker-compose build app
    3. docker-compose up db app

    Development considerations If the development results in DB modification, please use Alembic and add a migration script so users don't loose their data when they upgrade.

    "},{"location":"development/hooks/","title":"Hooks","text":"

    Introduced in IRIS v1.4.0

    Hooks are a mean for modules to react on specific events that occurs on IRIS. By subscribing to a hook, a module is automatically notified when the associated event occurs. This offers a multitude of possibilities, from adding insight to IRIS objects, to pushing information to another platform or even changing how IRIS works.

    "},{"location":"development/hooks/#types","title":"Types","text":"

    There are 3 types of hooks.

    Danger

    on_preload hooks must run synchronously, i.e not queued in RabbitMQ. This effectively blocks the current user request until the module finishes the processing. We highly recommend to only use on_postload hooks for a better user experience. These hooks are transparent for users and rely on already verified and committed data. Handling on_preload hooks implies the received data is unsafe - directly coming from remote clients - and the module needs to process the data as fast as possible.

    "},{"location":"development/hooks/#subscribing-and-unsubscribing","title":"Subscribing and unsubscribing","text":"

    Two methods are provided by IrisModuleInterface to subscribe and unsubscribe to hooks.

      def register_to_hook(module_id: int, \niris_hook_name: str, \nmanual_hook_name: str = None, \nrun_asynchronously: bool = True)\ndef deregister_from_hook(module_id: int, \niris_hook_name: str)\n

    The registration method expects the following arguments:

    The deregistration method expects the following arguments:

    Please see the modules documentation for more details on how to implement these methods.

    "},{"location":"development/hooks/#available-hooks","title":"Available hooks","text":"

    The following hooks are natively available for subscription.

    Hook name Description on_preload_case_create Triggered on case creation, before commit in DB on_postload_case_create Triggered on case creation, after commit in DB on_preload_case_delete Triggered on case deletion, before commit in DB on_postload_case_delete Triggered on case deletion, after commit in DB on_postload_case_update Triggered on case update, before commit in DB on_manual_trigger_case Triggered upon user action on_postload_alert_create Triggered on alert creation, after commit in DB on_postload_alert_update Triggered on alert update, after commit in DB on_postload_alert_delete Triggered on alert deletion, after commit in DB on_postload_alert_escalate Triggered on alert escalation, after commit in DB on_postload_alert_merge Triggered on alert merge, after commit in DB on_postload_alert_unmerge Triggered on alert unmerge, after commit in DB on_preload_asset_create Triggered on asset creation, before commit in DB on_postload_asset_create Triggered on asset creation, after commit in DB on_preload_asset_update Triggered on asset update, before commit in DB on_postload_asset_update Triggered on asset update, after commit in DB on_preload_asset_delete Triggered on asset deletion, before commit in DB on_postload_asset_delete Triggered on asset deletion, after commit in DB on_manual_trigger_asset Triggered upon user action on_preload_note_create Triggered on note creation, before commit in DB on_postload_note_create Triggered on note creation, after commit in DB on_preload_note_update Triggered on note update, before commit in DB on_postload_note_update Triggered on note update, after commit in DB on_preload_note_delete Triggered on note deletion, before commit in DB on_postload_note_delete Triggered on note deletion, after commit in DB on_manual_trigger_note Triggered upon user action on_preload_ioc_create Triggered on ioc creation, before commit in DB on_postload_ioc_create Triggered on ioc creation, after commit in DB on_preload_ioc_update Triggered on ioc update, before commit in DB on_postload_ioc_update Triggered on ioc update, after commit in DB on_preload_ioc_delete Triggered on ioc deletion, before commit in DB on_postload_ioc_delete Triggered on ioc deletion, after commit in DB on_manual_trigger_ioc Triggered upon user action on_preload_event_create Triggered on event creation, before commit in DB on_preload_event_duplicate Triggered on event duplication, before commit in DB. This event only received the event ID which will be duplicated on_postload_event_create Triggered on event creation, after commit in DB on_preload_event_update Triggered on event update, before commit in DB on_postload_event_update Triggered on event update, after commit in DB on_preload_event_delete Triggered on event deletion, before commit in DB on_postload_event_delete Triggered on event deletion, after commit in DB on_manual_trigger_event Triggered upon user action on_preload_evidence_create Triggered on evidence creation, before commit in DB on_postload_evidence_create Triggered on evidence creation, after commit in DB on_preload_evidence_update Triggered on evidence update, before commit in DB on_postload_evidence_update Triggered on evidence update, after commit in DB on_preload_evidence_delete Triggered on evidence deletion, before commit in DB on_postload_evidence_delete Triggered on evidence deletion, after commit in DB on_manual_trigger_evidence Triggered upon user action on_preload_task_create Triggered on task creation, before commit in DB on_postload_task_create Triggered on task creation, after commit in DB on_preload_task_update Triggered on task update, before commit in DB on_postload_task_update Triggered on task update, after commit in DB on_preload_task_delete Triggered on task deletion, before commit in DB on_postload_task_delete Triggered on task deletion, after commit in DB on_manual_trigger_task Triggered upon user action on_preload_global_task_create Triggered on global task creation, before commit in DB on_postload_global_task_create Triggered on global task creation, after commit in DB on_preload_global_task_update Triggered on task update, before commit in DB on_postload_global_task_update Triggered on global task update, after commit in DB on_preload_global_task_delete Triggered on task deletion, before commit in DB on_postload_global_task_delete Triggered on global task deletion, after commit in DB on_manual_trigger_global_task Triggered upon user action on_preload_report_create Triggered on report creation, before generation in DB on_postload_report_create Triggered on report creation, before download of the document on_preload_activities_report_create Triggered on activities report creation, before generation in DB on_postload_activities_report_create Triggered on activities report creation, before download of the document on_postload_asset_commented Triggered on asset comment, after commit in DB on_postload_asset_comment_update Triggered on asset comment update, after commit in DB on_postload_asset_comment_delete Triggered on asset comment deletion, after commit in DB on_postload_evidence_commented Triggered on evidence comment, after commit in DB on_postload_evidence_comment_update Triggered on evidence comment update, after commit in DB on_postload_evidence_comment_delete Triggered on evidence comment deletion, after commit in DB on_postload_task_commented Triggered on task comment, after commit in DB on_postload_task_comment_update Triggered on task comment update, after commit in DB on_postload_task_comment_delete Triggered on task comment deletion, after commit in DB on_postload_ioc_commented Triggered on ioc comment, after commit in DB on_postload_ioc_comment_update Triggered on ioc comment update, after commit in DB on_postload_ioc_comment_delete Triggered on ioc comment deletion, after commit in DB on_postload_event_commented Triggered on event comment, after commit in DB on_postload_event_comment_update Triggered on event comment update, after commit in DB on_postload_event_comment_delete Triggered on event comment deletion, after commit in DB on_postload_note_commented Triggered on note comment, after commit in DB on_postload_note_comment_update Triggered on note comment update, after commit in DB on_postload_note_comment_delete Triggered on note comment deletion, after commit in DB on_postload_alert_commented Triggered on alert comment, after commit in DB on_postload_alert_comment_update Triggered on alert comment update, after commit in DB on_postload_alert_comment_delete Triggered on alert comment deletion, after commit in DB"},{"location":"development/structure/","title":"Structure overview","text":""},{"location":"development/structure/#flask","title":"Flask","text":"

    IRIS uses Flask for the web engine.

    "},{"location":"development/structure/#routes-and-blueprints","title":"Routes and blueprints","text":"

    Each page and API endpoints (eg /login, /dashboard, /case/assets/list, etc) refers to a route in the IRIS Flask app. They define what the application should do when Flask receives a request on an URI. To keep structure in the projects, these routes are grouped by Blueprints. The Blueprints reflects the structure shown in the IRIS UI left menu. For instance there is a case and an activities Blueprint.

    The Blueprints and thus routes are defined in source > app > blueprints. All the blueprints are registered in source > app > views.py.

    "},{"location":"development/structure/#templates","title":"Templates","text":"

    IRIS uses dynamic page templating when an URI is visited. These Jinja2 templates are filled at runtime with the needed information and then returned to the client. Each route offering a page (i.e non-API endpoints) thus relies on a template. These are set in a folder named templates in each Blueprint. For instance, for the dashboard template : source > app > blueprints > dashboard > templates > index.html.

    "},{"location":"development/structure/#static-contents","title":"Static contents","text":"

    Static content is served from a common folder under source > app > static > assets. It contains CSS, JS and images. These can be accessed by pages using \"/static/assets/<the-resource>\".

    "},{"location":"development/structure/#sqlalchemy","title":"SQLAlchemy","text":"

    For the database management, the application uses SQLAlchemy with a PostgreSQL backend. There is - normally - no need to directly deal with PostgreSQL, everything goes through SQLAlchemy. It provides a Python overlay which allows to talk to the DB with objects.

    "},{"location":"development/structure/#models","title":"Models","text":"

    Each table of the app is defined by a model. These are defined in source > app > model. When IRIS starts, it looks for the already created tables and creates the missing ones if needed. If changes are done on a table or field, then a migration is needed. This is explained in Alembic migrations.

    "},{"location":"development/structure/#requests","title":"Requests","text":"

    To help structuring the code, we are trying to move the DB code from the routes code. This is partially done and work in progress. If your route requests the DB, please put the DB code in source > app > datamgmt.

    "},{"location":"development/structure/#alembic","title":"Alembic","text":"

    To apply schema migration without the need to rebuild the DB, IRIS uses Alembic. It allows to define migration scheme and IRIS calls it when it starts so users can upgrade without too much hassles.

    "},{"location":"development/structure/#hooks-modules-and-tasks","title":"Hooks, modules and tasks","text":"

    Modules are handled via tasks thanks to Celery and RabbitMQ. More info here and here.

    "},{"location":"development/structure/#iris-startup","title":"IRIS startup","text":"

    When starting-up, IRIS initiates a bunch of DB objects, whether it is started for the first time or just restarted. Objects already created are not recreated, but the missing ones are applied. This ensure a smooth migration between versions. These are defined in source > app > post_init.py. The scripts also contains the code that runs th DB migration with Alembic.

    "},{"location":"development/modules/","title":"Modules","text":""},{"location":"development/modules/#introduction","title":"Introduction","text":"

    A DFIR-IRIS Module (DIM) is a Python package allowing to extend IRIS features. DIMs are not running constantly and are only called following specific actions done by users.

    We distinct two types of modules:

    Except for some triggers for processor modules, all tasks provided by DIMs are run asynchronously in RabbitMQ tasks, so they don't impact the UI.

    Both types of DIMs have the same structure, they only differ in their configurations and how they handle the data they receive. For that purpose, every DIM inherit from a common class named IrisModuleInterface - available here - which provides the basic structure and methods of a module.

    Hint

    To quickly start writing a new module, one can follow these tutorials.

    "},{"location":"development/modules/#overview","title":"Overview","text":"

    Modules are instantiated upon actions (hooks, triggers, user actions) and this occurs each time the said actions occur. It implies the initiation of a module has to be very quick. In most of the case, the __init__ method should not even be overwritten.

    They can live either in the worker or the web-app, depending on their type and action they are handling. They can also live in both. This implies multiple instances of the same module can run at the same time.

    The graph below shows two modules of different types running in the worker and interacting with external elements.

    Modules don't have to handle the task creations or resource locks. This is handled by IRIS. They just need to process the data they received and return results in a predefined manner.

    "},{"location":"development/modules/#common-structure","title":"Common structure","text":"

    The section below describes the common structure of modules.

    "},{"location":"development/modules/#directory-structure","title":"Directory structure","text":"
    setup.py                # Setup configuration to build the module \nREADME.md               # README \niris_example_name       # Name of the package \n    __init__.py              # Declaration of the package and main class\n    IrisExampleConfig.py     # Configuration of the module to help keep the main file clean \n    IrisExampleInterface.py  # Main class of the module \n    module_helper            # Sub module containing the helper functions of the module \n      helper.py              # for instance access to ext resource, manipulation of data \n      helper2.py             # etc. \n
    "},{"location":"development/modules/#the-initpy-file","title":"The init.py file","text":"

    Iris loads the modules dynamically. To do so, it needs to know the name of the main class of the module and relies on __init__.py to find this information.

    __iris_module_interface = \"IrisEXAMPLEInterface\"\n

    Where IrisEXAMPLEInterface is the main class of the module and inherits of the base class IrisModuleInterface.

    Caution

    Failing to provide the main class in __init__.py or having the main class inherit from IrisModuleInterface will make IRIS fail each time it attempts to load the module.

    "},{"location":"development/modules/#the-module-configuration","title":"The module configuration","text":"

    Iris needs to know what the module is doing and what services it is providing. This is done via the attributes of the main class (let's say IrisEXAMPLEInterface). The attributes are :

    pipeline_info = {\n# Name of the pipeline used for internal tracking. This \n# must be unique among all modules so pick something really unique \n\"pipeline_internal_name\": \"example_pipeline\",\n# The name of the pipeline presented to the user. Use something \n# that will help the users to identify the right pipeline\n\"pipeline_human_name\": \"Example Pipeline\",\n# Arguments presented to the users when they select the pipeline\n\"pipeline_args\": [\n['some_index', 'required'],\n['example_argument', 'optional']\n]\n}\n
    _module_configuration = [\n{\n\"param_name\": \"vt_api_key\",\n\"param_human_name\": \"VT API Key\",\n\"param_description\": \"Virus total API key\",\n\"default\": None,\n\"mandatory\": True,\n\"type\": \"sensitive_string\"\n},\n{\n\"param_name\": \"vt_key_is_premium\",\n\"param_human_name\": \"VT Key is premium\",\n\"param_description\": \"Set to True if the VT key is premium\",\n\"default\": False,\n\"mandatory\": True,\n\"type\": \"bool\"\n},\n{\n\"param_name\": \"vt_ip_assign_asn_as_tag\",\n\"param_human_name\": \"Assign ASN tag to IP\",\n\"param_description\": \"Assign a new tag to IOC IPs with the ASN fetched from VT\",\n\"default\": True,\n\"mandatory\": True,\n\"type\": \"bool\"\n}\n]\n

    The above example results in the following.

    "},{"location":"development/modules/quick_start/processor/","title":"Processor modules","text":"

    In this tutorial, we demonstrate the steps to write a basic processor module which subscribes to a hook, and log what it receives when the hook is triggered. We will also add a configuration setting to offer our users the ability disable this feature.

    We'll call it IrisDummyModule.

    "},{"location":"development/modules/quick_start/processor/#project-structure-overview","title":"Project structure overview","text":"

    As described in the development module main page, the module should have the following structure.

    setup.py                # Setup configuration to build the module \nREADME.md               # README \niris_dummy_module       # Name of the package \n__init__.py              # Declaration of the package and main class\nIrisDummyConfig.py       # Configuration of the module to help keep the main file clean \nIrisDummyModule.py    # Main class of the module \n

    While the module could have only one main file IrisDummyModule.py, we recommend splitting its configuration into a new configuration file (here IrisDummyConfig.py) to keep the code clear.

    There is no mandatory naming convention for the files or the class or the methods. We chose this one to keep things clear, and we recommend following the same. But it's up to you really.

    We will walk over these files one by one during this tutorial.

    "},{"location":"development/modules/quick_start/processor/#creating-the-interface","title":"Creating the interface","text":"

    The interface is the code that talks with IRIS. It implements methods that call and are called by the server. It needs to inherit IrisModuleInterface class from the IrisModuleInterface package. This module handles most of the methods needed by IRIS to recognize, set up and call the module. By inheriting this class in our interface, we avoid writing that part ourselves.

    Let's write our basic interface class. The name of the file has to be the name of the main class, that's the only constraint. We'll see later on why.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\npass \n

    That's it! Actually this class is not doing anything right now. We'll need to add a few methods to register our hook later.

    But first we need to indicate to IRIS what is our main interface class. Remember, there is no convention restriction, so IRIS has no way to know which class it should instantiate to call our module.

    To do so, we need to set a specific variable in our __init__.py.

    iris_dummy_module/__init__.py
    # Set the __iris_module_interface variable to the name of our main class. \n# When IRIS instantiates the python module, it looks for \"module.__iris_module_interface\"\n# And then tries to instantiate the class \"__iris_module_interface.__iris_module_interface\", here 'IrisDummyModule.IrisDummyModule'. \n# That's why the python file must have the same name as the class.  \n__iris_module_interface = \"IrisDummyModule\"\n

    Our module is now recognizable by IRIS Pretty simple right?

    "},{"location":"development/modules/quick_start/processor/#writing-the-configuration","title":"Writing the configuration","text":"

    The next step is to describe what the module is doing, its name, its configuration, etc. This is done by overwriting predefined variables of the IrisModuleInterface class.

    Let's create our Python configuration file and go through each variables.

    iris_dummy_module/IrisDummyConfig.py
    # Import the module types list,  so we can indicate the type of our module \nfrom iris_interface.IrisModuleInterface import IrisModuleTypes \n# Human name displayed in the GUI Manage > Modules. This can be anything, \n# but try to put something meaningful, so users recognize your module. \nmodule_name = \"IrisDummy\"\n# Description displayed when editing the module configuration in the UI. \n# This can be anything, \nmodule_description = \"Provides a dummy module that replies to one hook\"\n# Set the interface version used. This needs to be the version of \n# the IrisModuleInterface package. This version is check by the server to\n# to ensure our module can run on this specific server \ninterface_version = 1.1\n# The version of the module itself, it can be anything \nmodule_version = 1.0\n# The type of the module, here processor \nmodule_type = IrisModuleTypes.module_processor\n# Our module is a processor type, so it doesn't offer any pipeline \npipeline_support = False\n# Provide no pipeline information as our module don't implement any \npipeline_info = {}\n# The configuration of the module that will be displayed and configurable \n# by administrators on the UI. This describes every parameter that can \n# be set. \nmodule_configuration = [\n{\n\"param_name\": \"log_received_hook\",\n\"param_human_name\": \"Log received hook\",\n\"param_description\": \"Logs a message upon hook receiving if set to true. Otherwise do nothing.\",\n\"default\": True,\n\"mandatory\": True,\n\"type\": \"bool\"\n}\n]\n

    The module configuration parameters are the following :

    A module can have as many parameters as it needs.

    We now need to update our main class to set this configuration.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\n# Set the configuration\n_module_name = interface_conf.module_name\n_module_description = interface_conf.module_description\n_interface_version = interface_conf.interface_version\n_module_version = interface_conf.module_version\n_pipeline_support = interface_conf.pipeline_support\n_pipeline_info = interface_conf.pipeline_info\n_module_configuration = interface_conf.module_configuration\n_module_type = interface_conf.module_type\npass \n

    Done! The module is now providing enough information to IRIS, so it knows exactly what our module do and what needs to be called to run it.

    However, our module is still doing nothing. Let's make it subscribe to an IRIS hook.

    "},{"location":"development/modules/quick_start/processor/#subscribing-to-a-hook","title":"Subscribing to a hook","text":"

    Hooks allow to be notified by IRIS when a specific event occurs (IOC creation, deletion, etc). For a comprehensive description of hooks, please see the Hooks section of this documentation.

    The registration (or subscription) to a hook occurs at two moments during the life of a module:

    These registration/deregistration events are triggered by IRIS, and are propagated to modules through the IrisModuleInterface method register_hooks [ref].

    To register to a hook, we need to override this method and register our hook within this method. To do so, IrisModuleInterface offers us another method register_to_hook [ref], which we can call for each hook we want to subscribe.

    Here is a summary of the events:

    1. IRIS calls register_hooks of our module. This indicates it is time for us to register our hooks.
    2. Within this method, we call register_to_hook for each hook we want to subscribe

    Let's add this to our main class and register to the on_postload_ioc_create. This will notify use each time a new IOC is created and committed to the database.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\n# Set the configuration\n_module_name = interface_conf.module_name\n_module_description = interface_conf.module_description\n_interface_version = interface_conf.interface_version\n_module_version = interface_conf.module_version\n_pipeline_support = interface_conf.pipeline_support\n_pipeline_info = interface_conf.pipeline_info\n_module_configuration = interface_conf.module_configuration\n_module_type = interface_conf.module_type\ndef register_hooks(self, module_id: int):\n\"\"\"\n        Called by IRIS indicating it's time to register hooks.  \n        :param module_id: Module ID provided by IRIS.\n        \"\"\"\n# Call the hook registration method. We need to pass the \n# the module_id to this method, otherwise IRIS won't know \n# to whom associate the hook. \n# The hook name needs to be a well known hook name by IRIS. \nstatus = self.register_to_hook(module_id, iris_hook_name='on_postload_ioc_create')\nif status.is_failure():\n# If we have a failure, log something out \nself.log.error(status.get_message())\nelse:\n# Log that we successfully registered to the hook \nself.log.info(f\"Successfully subscribed to on_postload_ioc_create hook\")\n

    That's it! Our module has now officially subscribed to a hook and will be notified each time an IOC is created.

    So how the module is notified? Once again this is done by a method named hooks_handler [ref] that IrisModuleInterface provides, and we need to overwrite.

    This method is called each time one of the event associated to the hook we subscribed is triggered. It provides the name of the hook and as well as the data associated to it. By overwriting this method, we can process the hook and the data!

    We will add a condition in this method, that is if the administrator sets the module parameter log_received_hook to False, then the module won't log anything and simply return the data.

    Hint

    The current configuration of the module can be accessed with the attribute self._dict_conf.

    iris_dummy_module/IrisDummyModule.py
    #!/usr/bin/env python3\n# Import the IrisInterface class\nfrom iris_interface.IrisModuleInterface import IrisModuleInterface\n# Create our module class\nclass IrisDummyModule(IrisModuleInterface):\n# Set the configuration\n_module_name = interface_conf.module_name\n_module_description = interface_conf.module_description\n_interface_version = interface_conf.interface_version\n_module_version = interface_conf.module_version\n_pipeline_support = interface_conf.pipeline_support\n_pipeline_info = interface_conf.pipeline_info\n_module_configuration = interface_conf.module_configuration\n_module_type = interface_conf.module_type\ndef register_hooks(self, module_id: int):\n\"\"\"\n        Called by IRIS indicating it's time to register hooks.  \n        :param module_id: Module ID provided by IRIS.\n        \"\"\"\n# Call the hook registration method. We need to pass the \n# the module_id to this method, otherwise IRIS won't know \n# to whom associate the hook. \n# The hook name needs to be a well known hook name by IRIS. \nstatus = self.register_to_hook(module_id, iris_hook_name='on_postload_ioc_create')\nif status.is_failure():\n# If we have a failure, log something out \nself.log.error(status.get_message())\nelse:\n# Log that we successfully registered to the hook \nself.log.info(f\"Successfully subscribed to on_postload_ioc_create hook\")\ndef hooks_handler(self, hook_name: str, data):\n\"\"\"\n    Called by IRIS each time one of our hook is triggered. \n    \"\"\"\n# read the current configuration and only log the call if \n# our parameter is set to true \nif self._dict_conf.get('log_received_hook') is True:\nself.log.info(f'Received {hook_name}')\nself.log.info(f'Received data of type {type(data)}')\n# Return a standardized message to IRIS saying that everything is ok. \n# logs=list(self.message_queue) is needed, so the users can see the logs \n# our module generated during its execution.  \nreturn InterfaceStatus.I2Success(data=data, logs=list(self.message_queue))\n

    We are done! Our module is now fully ready to register, subscribe to a hook and act when notified.

    "},{"location":"development/modules/quick_start/processor/#installing-and-registering-the-module","title":"Installing and registering the module","text":"

    We need now need to build and install the module. To do so, you'll need this script and an IRIS docker instance running on the same machine.

    The script will build the module, copy it to the docker instances, install it within them and restart the dockers.

    1. From within the root directory of the module, paste the script
    2. Make it executable chmox +x buildnpush2iris.sh
    3. Execute it ./buildnpush2iris.sh -a

    The module should now be installed. We can register it in IRIS as explained here.

    "},{"location":"operations/alerts/","title":"Alerts","text":"

    This section is under construction.

    Introduced in IRIS v2.1.0

    Alerts can be fed directly into IRIS using the Alerts API. Any source can inject alerts into IRIS, as long as it can send HTTP requests and respects the alert format.

    A service account with the alert_read and alert_write permission can be used to send alerts to IRIS.

    Warning

    This section is only available for users with the alert_read and alert_write permissions.

    "},{"location":"operations/alerts/#viewing-alerts","title":"Viewing alerts","text":"

    Alerts can then be viewed in the Alerts section of IRIS. Analysts can then triage the alerts and create cases from them.

    Each alert can be expanded to show more details.

    "},{"location":"operations/alerts/#alerts-assignment","title":"Alerts assignment","text":"

    Alerts can be assigned to analysts. This can be done directly from the alert view.

    To self-assign an unassigned alert, click on the hand icon on the left.

    Clicking again on the hand icon will prompt with a list of analysts to assign the alert to.

    The right button Assign, when hovering above an alert, can also be used to assign the alert to an analyst.

    "},{"location":"operations/alerts/#merge-escalation-operations","title":"Merge / escalation operations","text":""},{"location":"operations/alerts/#creating-cases-from-alerts","title":"Creating cases from alerts","text":"

    Alerts can be escalated/merged into a new case. When hovering above an alert, a Merge button will appear.

    Once clicked, a new window appears, requesting additional information. In this window, the analyst can:

    "},{"location":"operations/alerts/#merge-alerts-into-an-existing-case","title":"Merge alerts into an existing case","text":"

    Alerts can also be escalated/merged into an existing case. When hovering above an alert, a Merge button will appear.

    Once clicked, a new window appears requesting additional information. The button Merge into existing case needs to be clicked. A new dropdown appears and allows to select the case to merge the alert into.

    Similar to the case creation, the analyst can:

    The selected IOCs and assets are then added to the selected case.

    "},{"location":"operations/alerts/#unmerge-alerts-from-a-case","title":"Unmerge alerts from a case","text":"

    Alerts can be unmerged from a case.

    Info

    When unmerging an alert, the alert is not deleted. It is only removed from the case. The alert state is not changed. The IOCs and assets are not removed from the case.

    When a case is merged, a new link appears on the alert and mentions the case it was merged into. Clicking on this link allows to browse the case or to unmerge the alert.

    "},{"location":"operations/alerts/#alerts-relationships","title":"Alerts relationships","text":"

    Each alert have a Relastionships section. This section shows the relationships between the alert and other objects in IRIS. This feature is in preview and might report false relationships.

    The relationships are computed using the following logic:

    By default the view limits the relationships to 100 nodes and looks back 7 days. This can be updated directly in the alert view.

    "},{"location":"operations/api/","title":"API","text":"

    IRIS is meant to be plug-able and be integrated with the existing environments.

    Through the REST API, one can do almost as much as it is possible to do through the web interface. Under the hood, the web interface is actually talking to the API.

    Hint

    A Python client is available here to ease the automation.

    "},{"location":"operations/api/#api-keys","title":"API Keys","text":"

    The first step is to obtain an API key. Each user is automatically attributed one when it is created. It can be found on the left panel, under username and My Settings.

    Token exposure

    In case the token is exposed and needs to be changed, a new one can be generated with the Renew option. Renewing a token revokes the previous.

    "},{"location":"operations/api/#references","title":"References","text":"

    The API constantly evolves with IRIS and thus multiple versions exists. Use the references below to check which API version applies to your IRIS version. Starting from IRIS v1.4.0, the supported API version can also be checked in the UI Advanced > Server settings.

    IRIS Version API Version & Reference v1.2.0 API v1.0.0 v1.2.1 API v1.0.0 v1.3.0 API v1.0.1 v1.3.1 API v1.0.1 v1.4.0 API v1.0.2 v1.4.1 API v1.0.2 v1.4.2 API v1.0.2 v1.4.3 API v1.0.3 v1.4.4 API v1.0.3 v1.4.5 API v1.0.3 v2.0.x API v2.0.0 v2.1.x API v2.0.1 v2.2.x API v2.0.1 v2.3.x API v2.0.2 - To come"},{"location":"operations/api/#how-to-use","title":"How to use","text":"

    The API token is used as a Bearer and needs to be present in the header Authorization when issuing requests. For example, to list all the cases:

       curl --request GET \\\n--url http://localhost:8000/manage/cases/list?cid=1 \\\n--header 'Authorization: Bearer mWpCUVNzBMU5EnbIAK50jLPhYjKBTHZjobdogc_n_yixpJTmt9tzAf8WYDI7m5XgB9wCJnlaXlHIh9RZjtp2fA' \\\n--header 'Content-Type: application/json'\n

    The only way to revoke a token is to renew the current one. Once done, the previous API token does not exist anymore in the database and it becomes ineffective.

    "},{"location":"operations/case_templates/","title":"Case templates","text":"

    Introduced in IRIS v2.1.0

    Case templates are a way to pre-configure a case with a set of predefined informations. The case templates can be managed in Advanced > Case templates.

    Info

    This section is only available for users with the administrator role.

    Case templates are made of a set of informations that will be used to pre-fill the case creation form. The following elements can be set:

    Looking for case templates?

    We are providing a set of case templates in the IRIS Resources repository.

    "},{"location":"operations/case_templates/#structure-of-templates","title":"Structure of templates","text":"

    The following defines the structure of a case template:

    {\n\"name\": \"ransomware_infection\",\n\"display_name\": \"Ransomware Infection Template\",\n\"description\": \"This case template describes first-response tasks to handle information system compromised by a ransomware.\",\n\"author\": \"DFIR-IRIS\",\n\"classification\": \"malicious-code:ransomware\",\n\"title_prefix\": \"[RANS]\",\n\"summary\": \"# Context \\n\\n\\n# Contact \\n\\n\\n# Actions \\n\\n\\n\",\n\"tags\": [\"ransomware\",\"malware\"],\n\"tasks\": [\n{\n\"title\": \"Identify the perimeter\",\n\"description\": \"The perimeter of compromise must be identified\",\n\"tags\": [\"identify\"]\n},\n{\n\"title\": \"Collect compromised hosts\",\n\"description\": \"Deploy Velociraptor and start collecting evidence\",\n\"tags\": [\"collect\", \"velociraptor\"]\n},\n{\n\"title\": \"Containment\"\n}\n],\n\"note_groups\": [\n{\n\"title\": \"Identify\",\n\"notes\": [\n{\n\"title\": \"Identify the compromised accounts\",\n\"content\": \"# Observations\\n\\n\"\n}\n]\n},\n{\n\"title\": \"Collect\",\n\"notes\": [\n{\n\"title\": \"Velociraptor deployment\"\n},\n{\n\"title\": \"Assets collected\",\n\"content\": \"# Assets collected\\n\\n# Assets not collected\"\n}\n]\n}\n]\n}\n
    "},{"location":"operations/case_templates/#using-case-templates","title":"Using case templates","text":"

    Case templates can be used when creating a new case. On the UI, when creating a case, select the case template to use in the Case template dropdown. The case will then automatically use the informations defined in the template.

    "},{"location":"operations/configuration/","title":"Configuration","text":"

    Since v2.0.0 the entire configuration is done through the .env file at the root of the IRIS directory.

    "},{"location":"operations/configuration/#default-configuration","title":"Default configuration","text":"

    The default configuration is provided through a .env.model file at the root of the IRIS directory. One need to copy this file to .env and modify it if needed.

    The default configuration is suitable for testing only. See the section below to configure IRIS for production.

    "},{"location":"operations/configuration/#production-configuration","title":"Production configuration","text":""},{"location":"operations/configuration/#secrets","title":"Secrets","text":""},{"location":"operations/configuration/#required-changes","title":"Required changes","text":"

    The following secrets in the .env need to be changed for production. We recommend using OpenSSL to generate different values from each secret: openssl rand -base64 64

    Critical configuration

    These settings are critical and need to be set properly otherwise authentication bypass may occur.

    "},{"location":"operations/configuration/#optionnal-changes","title":"Optionnal changes","text":"

    To automate the provisionning of IRIS, one might need to set the default administrator API token and password. This can be achieve with the following environment variables. If those variables are not set, random ones are generated during the very first boot of the application.

    Warning

    The administrator password is printed in the logs. It is recommended to change it as soon as possible. The set of the following environment variables has no effect once the administrator account is created, i.e after the very first boot.

    "},{"location":"operations/configuration/#certificates","title":"Certificates","text":"

    IRIS is configured to use a self-signed certificate by default. This is suitable for testing only. To use your own certificate, you need to set the following environment variables:

    Once the changes are done, nginx docker container need to be rebuilt with the following command:

    docker-compose stop nginx\ndocker-compose build nginx --no-cache\ndocker-compose up 
    "},{"location":"operations/configuration/#authentication","title":"Authentication","text":""},{"location":"operations/configuration/#ldap","title":"LDAP","text":"

    IRIS can be configured to use LDAP authentication. See the Authentication section for more details.

    "},{"location":"operations/configuration/#available-settings","title":"Available settings","text":"

    These environment variables are availabled to be set.

    Key Section Opt Description SERVER_NAME Nginx No Passed to the server_name in NGINX configuration KEY_FILENAME Nginx No SSL Cert key filename passed to the NGINX configuration CERT_FILENAME Nginx No SSL Cert filename passed to the NGINX configuration INTERFACE_HTTPS_PORT Nginx Yes Listening interface of IRIS POSTGRES_USER DB No Name of the POSTGRES user POSTGRES_PASSWORD DB No Password of the POSTGRES user POSTGRES_ADMIN_USER DB No Name of the admin user POSTGRES_ADMIN_PASSWORD DB No Password of the ADMIN user POSTGRES_DB DB No Name of the DB used by IRIS POSTGRES_SERVER DB No Hostname or IP of the DB POSTGRES_PORT DB No Port of the DB server DOCKERIZED IRIS Yes Set to 1 when using dockers (default) IRIS_SECRET_KEY IRIS No Secret key used to secure sessions - needs to be random IRIS_SECURITY_PASSWORD_SALT IRIS No Secret used to salt the passwords in DB - needs to be random IRIS_UPSTREAM_SERVER IRIS No WebApp upstream server - used to configure nginx reverse proxy IRIS_UPSTREAM_PORT IRIS No WebApp upstream server port - used to configure nginx reverse proxy IRIS_ORGANISATION_NAME IRIS No Name of the company / organisation. Used on the UI IRIS_LOGIN_BANNER_TEXT IRIS No Text displayed on the login page IRIS_LOGIN_PTFM_CONTACT IRIS No Contact information displayed on the login page IRIS_UPLOADED_PATH IRIS No Path to store uploaded data. IRIS_BACKUP_PATH IRIS No Path to store backup files. IRIS_TEMPLATES_PATH IRIS No Path of the templates IRIS_DATASTORE_PATH IRIS No Path of the datastore files IRIS_DEMO_ENABLED Demo No Set to True to switch IRIS to Demo mode IRIS_DEMO_DOMAIN Demo No URL of the demonstration server IRIS_DEMO_USER_SEED Demo No Random seed to generate demo users IRIS_DEMO_ADM_SEED Demo No Random seed to generate admin users for demo CELERY_BROKER Celery No Broker URL used to handle IRIS tasks IRIS_AUTHENTICATION_TYPE Auth No IRIS auth mode : local or ldap IRIS_ADM_PASSWORD Auth Yes Set to use as initial password of the administrator account. Only works for the very first run of IRIS. Needs to match the password policy IRIS_ADM_API_KEY Auth Yes Set to use as initial API Key of the administrator IRIS_ADM_EMAIL Auth Yes Set to use as initial email of the administrator IRIS_ADM_USERNAME Auth Yes Set to use as initial username of the administrator LDAP_SERVER Auth Yes LDAP server IP or domain LDAP_PORT Auth Yes LDAP server port LDAP_USER_PREFIX Auth Yes Prefix to search the users within LDAP_USER_SUFFIX Auth Yes Suffix to search the users within LDAP_USE_SSL Auth Yes Set to True to use LDAPS LDAP_VALIDATE_CERTIFICATE Auth Yes Set to True to verify the server certificate validity LDAP_TLS_VERSION Auth Yes TLS version to use LDAPS LDAP_SERVER_CERTIFICATE Auth Yes Path of the LDAP server certificate LDAP_PRIVATE_KEY Auth Yes Path of the LDAP private certificate LDAP_PRIVATE_KEY_PASSWORD Auth Yes Password of the private key LDAP_AUTHENTICATION_TYPE Auth Yes Simple, SASL or NTLM LDAP_CUSTOM_TLS_CONFIG Auth Yes If set to true, the TLS configuration is not set by IRIS and taken from the defined environment. Default to False"},{"location":"operations/custom_attributes/","title":"Custom Attributes","text":"

    Introduced in IRIS v1.4.0

    All the case objects can be extended with custom attributes. These attributes can be added by :

    Attributes offer the ability to :

    This section only describes how an administrator can add or delete attributes to an object.

    Tip

    We have publish a detailed article of custom attributes with advanced usage on our blog.

    "},{"location":"operations/custom_attributes/#management-page","title":"Management page","text":"

    Custom attributes can be changed in the Advanced > Custom Attributes section on the left panel.

    The page lists the objects for which custom attributes can be added or modified.

    "},{"location":"operations/custom_attributes/#attributes-structure","title":"Attributes structure","text":"

    Attributes are defined in JSON which describes tabs and fields that makes the attributes.

      {\n\"Tab Name 1\": {                     // Defines a new tab \n\"Field 1\": {                    // Defines a new field within the Tab Name 1\n\"type\": \"input_string\",     // Defines the type of field, here a standard string input\n\"mandatory\": true,          // Indicates whether the field is mandatory upon saving\n\"value\": \"\"                 // Default value if any, else empty\n},\n\"Field 2\": {                    // Defines a second field within the tab Tab Name 1\n\"type\": \"input_checkbox\",   // Defines an input checkbox\n\"mandatory\": false,         // Indicates whether the field is mandatory upon saving\n\"value\": false              // Default value - must be set for booleans\n}\n},\n\"VT report\": {                      // Defines a second tab named VT report\n\"Content\": {                    // Defines a new field Content within the VT Report\n\"type\": \"html\",             // Defines an HTML interpreted content\n\"value\": \"\"                 // Default value if any, else empty\n}\n}\n}\n

    The code above would be rendered as :

    With :

    1. The native information of the object. This cannot be changed or updated
    2. The new attribute Tab Name 1
    3. The other new attribute VT report
    "},{"location":"operations/custom_attributes/#attributes-taxonomy","title":"Attributes taxonomy","text":"

    The available fields type are available for rendering :

    "},{"location":"operations/custom_attributes/#updating-resetting-attributes","title":"Updating / resetting attributes","text":"

    When an attribute is updated, it will try to update all the existing objects with the new attributes. To prevent any data loss from previous attributes and attributes pushed by modules, the update is only made on attributes which don't have any values set or are type-compatibles (ie string to textfield).

    The migration of an attribute can however be forced in two ways, both resulting in potential attributes data loss.

    Good to know

    Migrating or overwriting attributes never change the native information of an object. It only applies to custom attributes.

    Partial overwrite basically resets all the values of every target objects that matches the current attribute definition. All associated values are lost. This does not impact attributes pushed by modules or previous configuration.

    Complete overwrite resets all attributes of every target objects, including the ones created by modules, and then applies the current attributes. All associated values are lost.

    "},{"location":"operations/custom_attributes/#example","title":"Example","text":"

    Custom attributes can be more complex than what presented above. With the html type, it is possible to build almost anything. Below is an example of the custom attributes used in the IrisVT module. The {{ }} are used withing the module to generates the page with data received from VT.

    Note : This example won't work as is, the value field is expanded here for reability.

    IrisVT default custom attribute
    {\n\"VT report\": {                      \"Content\": {                    \"type\": \"html\",             \"value\": \"<div class='row'>\n                    <div class='col-12'>\n                        <h3>Basic information</h3>\n                        <dl class='row'>\n                            {% if results.as_owner %}\n                            <dt class='col-sm-3'>AS owner</dt>\n                            <dd class='col-sm-9'>{{ results.as_owner }}</dd>\n                            {% endif %}\n                            {% if country %}\n                            <dt class='col-sm-3'>Country</dt>\n                            <dd class='col-sm-9'>{{ results.country }}</dd>\n                            {% endif %}\n                        </dl>\n                    </div>\n                </div>    \n                {% if nb_detected_urls %}\n                <div class='row'>\n                    <div class='col-12'>\n                        <h3>Detected URLS</h3>\n                        <dl class='row'>\n                            <dt class='col-sm-3'>Total detected URLs</dt>\n                            <dd class='col-sm-9'>{{ nb_detected_urls }}</dd>\n                            <dt class='col-sm-3'>Average detection ratio</dt>\n                            <dd class='col-sm-9'>{{ avg_urls_detect_ratio }}</dd>\n                        </dl>\n                    </div>\n                </div>    \n                {% endif %}\n                {% if nb_detected_samples %}\n                <div class='row'>\n                    <div class='col-12'>\n                        <h3>Detected communicating samples</h3>\n                        <dl class='row'>\n                            <dt class='col-sm-3'>Total detected samples</dt>\n                            <dd class='col-sm-9'>{{ nb_detected_samples }}</dd>\n                            <dt class='col-sm-3'>Average detection ratio</dt>\n                            <dd class='col-sm-9'>{{ avg_samples_detect_ratio }}</dd>\n                        </dl>\n                    </div>\n                </div>    \n                {% endif %}\n                <div class='row'>\n                    <div class='col-12'>\n                        <div class='accordion'>\n                            <h3>Additional information</h3>\n                            {% if results.resolutions %}\n                            <div class='card'>\n                                <div class='card-header collapsed' id='drop_res' data-toggle='collapse' data-target='#drop_resolutions' aria-expanded='false' aria-controls='drop_resolutions' role='button'>\n                                    <div class='span-icon'>\n                                        <div class='flaticon-file'></div>\n                                    </div>\n                                    <div class='span-title'>\n                                        Resolutions history\n                                    </div>\n                                    <div class='span-mode'></div>\n                                </div>\n                                <div id='drop_resolutions' class='collapse' aria-labelledby='drop_res' style=''>\n                                    <div class='card-body'>\n                                        <ul>\n                                            {% for resolution in results.resolutions %} \n                                            <li>{{ resolution.hostname }} ( Last resolved on {{resolution.last_resolved}} )</li>\n                                            {% endfor %}\n                                        </ul>\n                                    </div>\n                                </div>\n                            </div>\n                            {% endif %}\n                        </div>\n                    </div>\n                </div>\n                <div class='row'>\n                    <div class='col-12'>\n                        <div class='accordion'>\n                            <h3>Raw report</h3>\n                            <div class='card'>\n                                <div class='card-header collapsed' id='drop_r' data-toggle='collapse' data-target='#drop_raw' aria-expanded='false' aria-controls='drop_raw' role='button'>\n                                    <div class='span-icon'>\n                                        <div class='flaticon-file'></div>\n                                    </div>\n                                    <div class='span-title'>\n                                        Raw report\n                                    </div>\n                                    <div class='span-mode'></div>\n                                </div>\n                                <div id='drop_raw' class='collapse' aria-labelledby='drop_r' style=''>\n                                    <div class='card-body'>\n                                        <div id='vt_raw_ace'>{{ results| tojson(indent=4) }}</div>\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div> \n                <script>\n                var vt_in_raw = ace.edit('vt_raw_ace',\n                {\n                    autoScrollEditorIntoView: true,\n                    minLines: 30,\n                });\n                vt_in_raw.setReadOnly(true);\n                vt_in_raw.setTheme('ace/theme/tomorrow');\n                vt_in_raw.session.setMode('ace/mode/json');\n                vt_in_raw.renderer.setShowGutter(true);\n                vt_in_raw.setOption('showLineNumbers', true);\n                vt_in_raw.setOption('showPrintMargin', false);\n                vt_in_raw.setOption('displayIndentGuides', true);\n                vt_in_raw.setOption('maxLines', 'Infinity');\n                vt_in_raw.session.setUseWrapMode(true);\n                vt_in_raw.setOption('indentedSoftWrap', true);\n                vt_in_raw.renderer.setScrollMargin(8, 5);\n                </script>\"                 }\n}\n}\n
    "},{"location":"operations/datastore/","title":"Datastore","text":"

    Introduced in IRIS v1.4.5

    The datastore offers a way to store files directly in the context of a case. Documents, IOCs, evidences, etc, anything can be uploaded and managed through IRIS.

    "},{"location":"operations/datastore/#accessing-the-datastore","title":"Accessing the datastore","text":"

    The datastore can be accessed from any page with the top-right shortcut.

    A new pane will open, with a default folder tree created for the case.

    "},{"location":"operations/datastore/#files","title":"Files","text":""},{"location":"operations/datastore/#adding-a-file","title":"Adding a file","text":"

    To add a file to a folder, press the + button near a folder where you want to place it, and select Add file.

    A new window appear and allows to upload the file. The following fields are available :

    A file can be both IOC and Evidence, in which case it is handled as an IOC and also added to the Evidence tab of the case.

    Depending on the file size, the upload might take some time. We are aware that the Nginx introduces a delay compared to a direct upload. We have not yet found a configuration that does not impact the speed upload.

    Once uploaded, and depending on the options selected, the file appear in the target folder with specific icons. A mouse hover explains what each icon means.

    "},{"location":"operations/datastore/#files-operations","title":"Files operations","text":"

    Once a file is added, a left-click on it shows a dropdown with multiple options.

    Batch operations such as moving and deleting are also available by clicking on Select at the top right, and then selecting the files.

    "},{"location":"operations/datastore/#pasting-in-notes-and-summary","title":"Pasting in notes and summary","text":"

    Images can now be directly pasted in notes an summary. Only images are supported. Once an image is pasted, the file is automatically uploaded in the datastore in the folder Notes Upload and a link to the file is inserted.

    Example of pasted image

    The image is by default sized to 40%. Changing the end of the link =SIZE%xSIZE% allows to resize the image.

    The file is now available in the DS and can be replaced if needed. The ID of the file is the one provided in the link, which can help finding out when names are updated.

    Note

    Under certain conditions (browser, version, OS) the image copy/paste cannot be done directly. This is a known issue, not directly linked to IRIS but related to how browsers handle files in clipboards. If you face this issue, try to open the image and copy it from there instead of the file manager. Otherwise you need to upload it via the Datastore and then get a link from it.

    "},{"location":"operations/datastore/#folders","title":"Folders","text":""},{"location":"operations/datastore/#adding-a-folder","title":"Adding a folder","text":"

    To add folder, press the + button near a folder where you want to place it, and select Add subfolder.

    A new window appear requesting the name of the folder to create. Validate and the new folder appears in the folder tree. Files can then be added to it.

    "},{"location":"operations/datastore/#moving-folders","title":"Moving folders","text":"

    Folders can be moved within other folders. When doing so, every files and subfolders are also moved, like we are used to with files managers.

    Click on the + near the folder to move, and then select Move. The target folder is underlined in blue. Select then the target folder which should appear underline in orange. Then validate the move.

    The folder and all its children are moved in the target directory.

    "},{"location":"operations/datastore/#searching","title":"Searching","text":"

    When dozens of files are added, the filtering bar can be used to quickly find a file. The filtering mechanism is similar to the one in the timeline.

    The query schema is : target_element:search_value AND target_element2:search_value2. There is no OR condition and searching without target does not work.

    The following target elements can be used to filter :

    "},{"location":"operations/datastore/#under-the-hood","title":"Under the hood","text":"

    Here a are a few concepts to better understand how the datastore is working.

    Folders represented on the datastore are virtual and do not represent the folders on the system. This is to ensure smooth files operations. The files are never touched again (unless overwritten or deleted) once uploaded. When a file or directory is moved or renamed, only its parent references are updated.

    Files are saved by GUID instead of their real names on the system. They are saved under the mapped volume /home/iris/server_data/datastore by default. Then three directories are created :

    Within each of these, a new subdirectory with the case ID is created when a file is uploaded. This is ensure IOC, which can be harmful, are formally identified on the server itself. Files can be found on the system by looking up the Storage UUID of the file (eg: dsf-f86926ec-513d-4e47-88fa-02110e7fb412) in these directories.

    "},{"location":"operations/logging/","title":"Logging","text":"

    All components of IRIS offers by-default logging in the docker instances. Depending on the OS of the hosts, the location of these logs may differ.

    For Debian-based distributions, the logs are usually in /var/lib/docker/containers/. The usually interesting logs in IRIS are the following:

    "},{"location":"operations/logging/#setting-up-forwarding","title":"Setting up forwarding","text":"

    Logs of IRIS can be forwarded to a SIEM for monitoring. Below is discussed how to setup Splunk forwarding. Other drivers are available and detailed on the docker website.

    1. Enable HEC and get an HEC token from Splunk. See the Splunk documentation
    2. On the host where docker is running, create a file /etc/docker/daemon.json and specify the following content:
      {\n\"log-driver\": \"splunk\",\n\"log-opts\": {\n\"splunk-insecureskipverify\": \"true\", \"splunk-index\": \"iris\",\n\"splunk-token\": \"YOUR HEC TOKEN\",\n\"splunk-url\": \"https://SPLUNK_SERVER:8088\"\n}\n}\n
    3. Reload the docker daemon: systemctl reload docker. The logs should appear in the Splunk instance.
    "},{"location":"operations/reports/","title":"Reports","text":"

    IRIS has the ability to generate reports based on the data of an investigation. The reports templates can be managed in Advanced > Templates.

    Info

    This section is only available for users with the Admin role.

    There is two types of reports :

    "},{"location":"operations/reports/#supported-formats","title":"Supported formats","text":"

    The following report formats are supported:

    "},{"location":"operations/reports/#structure-of-templates","title":"Structure of templates","text":"

    Reports templates are made of tags, which are then processed and filed by the template engine of IRIS. The templates can have any forms as soon as they respect the tags. We are providing two example of reports.

    Info

    The templates includes a few lines that describes how to handle styles. These should not be removed. They are be present in the generated reports and need to be removed manually.

    "},{"location":"operations/reports/#available-tags","title":"Available tags","text":"

    The following tags are available. None are mandatory. If a tag is mistyped, the generation step will produce an error message.

    Hint

    Standard objects are accessible with {{ objectname }}. List objects can be looped:

      {% for object in object_list %}\n    {{ object.attribute }}\n  {% endfor %} \n
    "},{"location":"operations/reports/#examples","title":"Examples","text":""},{"location":"operations/reports/#full-documents","title":"Full documents","text":"

    We are providing two example of full reports.

    "},{"location":"operations/reports/#snippets","title":"Snippets","text":"

    The following snippets aimed to be placed directly in the DOCX documents.

    "},{"location":"operations/reports/#loops-and-tables","title":"Loops and tables","text":""},{"location":"operations/reports/#standard-loops","title":"Standard loops","text":"

    A loop needs to be used for list objects. Loop on IOC example

    The IOCs of this case are : \n\n{% for ioc in case.iocs %}\n    - {{ ioc.ioc_value }}\n    - {{ ioc.ioc_description }}\n{% endfor %}\n

    "},{"location":"operations/reports/#table-loops","title":"Table loops","text":"

    To use a loop in a table, a tr tag needs to be added to the loop and the loop directly integrated in the table. Loop on IOC table example

    The IOCs of this case are in the following table : \n\n{%tr for ioc in case.iocs %}\n    {{ ioc.ioc_value }}\n    {{ ioc.type_name }}\n    {{ ioc.ioc_description }}\n{%tr endfor %}\n
    Such as :

    "},{"location":"operations/reports/#nested-loops","title":"Nested loops","text":"

    Loops can be nested. Don't forget to close each loop.

    Nested loop
    {%for ioc in case.iocs %}\n\n    Custom attributes of {{ ioc.ioc_value }} :\n\n    {% for attribute in ioc.custom_attributes %}\n\n        - {{ attribute }}\n\n    {% endfor %}\n\n{% endfor %}\n
    "},{"location":"operations/reports/#conditions","title":"Conditions","text":""},{"location":"operations/reports/#standard","title":"Standard","text":"Check if asset is compromised
    {% for asset in assets %} \n\n    {% if asset.compromised %}\n        Asset {{ asset.asset_name }} is compromised\n    {% endif %}\n\n{% endfor %}\n
    "},{"location":"operations/reports/#list-is-not-empty","title":"List is not empty","text":"

    To check if a list of objects is not empty, use the processor tag count.

    Check if case has assets
    {% if assets|count %} \n    The case has assets\n{% endif %}\n
    "},{"location":"operations/reports/#markdown-handling","title":"Markdown handling","text":"

    The case summary and notes are in markdown. A processor tag should thus be added |markdown. Summary as markdown

    This is an example of summary : \n\n{{ case.description|markdown }}\n

    Loop over notes
    This is an example of recursive notes  : \n\n{% for note in case.notes %}\n\n    My note named {{ note.note_title }} : \n    {{ note.note_content|markdown }}\n\n{% endfor %}\n
    "},{"location":"operations/reports/#troubleshoot","title":"Troubleshoot","text":"

    Most of the time an error of generation is due to misspelled tag or a missing closing tag ({% endfor %}, {% endif %}, etc). In case you cannot figure out what is going wrong, don't hesitate to reach us on Discord.

    "},{"location":"operations/server_settings/","title":"Server settings","text":"

    Some basic settings can be set in the section Advanced > Server settings.

    "},{"location":"operations/tutorials/","title":"Tutorials","text":"

    The tutorials have been discared as we now provide a free demonstration instance on v200.beta.dfir-iris.org. Should you need more information or assistance to use IRIS, you can contact us here.

    "},{"location":"operations/upgrades/","title":"Upgrades","text":"

    Most of the time, Iris handles upgrades of the database automatically when a new version is started, thus no specific actions are required. However, some breaking changes might need manual intervention. Please use the selectors below to assess if a manual action is required.

    Your current version: --Please choose current version-- v1.2.1 v1.3.0 v1.3.1 v1.4.0 v1.4.1 v1.4.2 v1.4.3 v1.4.4 v1.4.5 v2.0.0 v2.0.1 v2.0.2 v2.1.0 v2.2.0 v2.2.1 v2.2.2 v2.2.3 v2.3.0 v2.3.1 v2.3.2 v2.3.3 v2.3.4 v2.3.5 v2.3.6 v2.3.7

    Upgrading to: --Please choose target version-- v1.2.1 v1.3.0 v1.3.1 v1.4.0 v1.4.1 v1.4.2 v1.4.3 v1.4.4 v1.4.5 v2.0.0 v2.0.1 v2.0.2 v2.1.0 v2.2.0 v2.2.1 v2.2.2 v2.2.3 v2.3.0 v2.3.1 v2.3.2 v2.3.3 v2.3.4 v2.3.5 v2.3.6 v2.3.7

    Check upgrades conditions

    For production environments, it is highly recommended to make backups of the DB in case any issues occur during upgrades.

    "},{"location":"operations/upgrades/#backing-up-db","title":"Backing-up DB","text":"

    Only if you run in production and/or data is critical.

    1. List the current running docker containers docker container list
    2. Spot the IRIS DB container name or ID, and execute the backup
      docker exec <container> pg_dump -U postgres iris_db | \\ \ngzip > ../iris_db_backup.gz\n
    1. Ensure the backup was successful by looking at the gz file
      zcat ../iris_db_backup.gz | less 
    "},{"location":"operations/upgrades/#upgrading","title":"Upgrading","text":"
    1. Stop the dockers

      docker-compose stop\n

    2. Remove the application dockers

      docker-compose rm app worker\n

    3. Get the last version of Iris

      git checkout <last_tagged_version>\n

      eg git checkout v2.3.6

    4. Build the new versions

      docker-compose build --no-cache app worker\n

    5. Run IRIS again. The app will handle the DB migration automatically.

      docker-compose up\n

    "},{"location":"operations/upgrades/#rolling-back","title":"Rolling back","text":"

    In case something went wrong, you can rollback to your previous version and restore data.

    1. Remove the faulty docker DB docker-compose down db --volumes
    2. Checkout to the previous version working of IRIS
    3. Rebuild the images docker-compose build --no-cache
    4. Spin up the docker DB, and ONLY this one. docker-compose up db
    5. Get the ID or name of the docker DB docker container list
    6. Restore the DB data zcat ../iris_db_backup.gz | docker exec -i <container> psql -U postgres -d iris_db
    7. Spin up the rest of the dockers docker-compose up
    8. Your data should back.
    "},{"location":"operations/upgrades/#version-specific-upgrades","title":"Version specific upgrades","text":""},{"location":"operations/upgrades/#v234","title":"v2.3.4","text":"

    \u2757 The layout of the reporting has slightly changed. Custom report templates might not work anymore. You can use https://<server>/case/export?cid=<case_id> to get all the possible fields.

    No other impact is to be expected.

    "},{"location":"operations/upgrades/#v210","title":"v2.1.0","text":"

    The default location of the SSL certificates have been changed from dockers/nginx/dev_certs to certificates/nginx/web_certificates. The docker-compose.yml has thus been updated to mount this volume on the nginx Docker.

    Except these changes, users in v2.0.x can upgrade to v2.1.0 without any manual intervention. Users in v1.4.x need to follow the v2.0.0 upgrade instructions before upgrading to v2.1.0.

    "},{"location":"operations/upgrades/#v200","title":"v2.0.0","text":""},{"location":"operations/upgrades/#breaking-changes","title":"Breaking changes","text":"

    This version brings breaking changes on the following:

    Warning

    Custom made modules need to be upgraded to IRIS Module Interface v1.2.0. Please see modules upgrade for v2.0.0

    "},{"location":"operations/upgrades/#instance-migration","title":"Instance migration","text":"

    To migrate an instance from v1.4.5, one can use the script in upgrades/upgrade_to_2.0.0.py located in the repository. These commands needs to be run from the root of the repository (pwd should return something like /iris-web):

    # Pull the lastest version \ngit pull # Checkout to iris v2.0.0\ngit checkout v2.0.0 # Check if upgrades possible\npython3 upgrades/upgrade_to_2.0.0.py --check\n\n# Run the upgrade\npython3 upgrades/upgrade_to_2.0.0.py --install\n

    The script will take care of migrating the environment variables to reflect the changes in v2.0.0. Please review the .env file afterward.

    The port have been changed 443. The script asks if the previous port should be kept or migrated to the new one.

    Once validated, one can proceed with the usual upgrade methodology.

    docker-compose stop \ndocker-compose build --no-cache \ndocker-compose up -d\n
    "},{"location":"operations/upgrades/#v200-modules-upgrades","title":"v2.0.0 modules upgrades","text":"

    This only concerns custom modules not shipped with IRIS Web App. The IRIS module interface has been upgraded to v1.2.0. No breaking changes are associated. One need to change the iris_module_interface dependency to 1.2.0 in the requirements and rebuild the module.

    "},{"location":"operations/upgrades/#python-client","title":"Python client","text":"

    The client has been updated to reflect the latest changes of the API. It also integrates features that were missing previously, such as Datastore Management. Some methods have been deprecated and some other modified. The easiest way to upgrade is to increase the version in the requirements and test. Each deprecated method will produce a warning or raise an exception.

    "},{"location":"operations/upgrades/#v145","title":"v1.4.5","text":"

    If you are coming from IRIS <= v1.3.1 please read this. Changes have been made to the NGINX docker to allow upload of big files for the datastore. It is hence necessary to also rebuild the NGINX docker this time.

    1. Stop the dockers docker-compose stop
    2. Remove the application dockers docker-compose rm app worker
    3. Get the last version of Iris git checkout <last_tagged_version> - eg git checkout v1.4.5
    4. Build the new versions docker-compose build --no-cache app worker nginx
    5. Run IRIS again. docker-compose up
    "},{"location":"operations/upgrades/#v144","title":"v1.4.4","text":"

    This only applies if you are coming from IRIS <= v1.3.1.

    This version brings breaking changes in the DB docker by adding a named volume instead of the default one. This implies that previous existing database is ignored as the new docker won't know which volume was previously used. To prevent this, please strictly follow the guide below. This will copy the data of the existing volume, to the new named one.

    1. Spot the IRIS DB container with docker container list. It should look like iris-web-db-x
    2. Fetch the current db volume ID (name field with the command below)

    docker inspect <iris_db> | grep -A5 \"Mounts\"\n# Example of output\n\"Mounts\": [\n{\n\"Type\": \"volume\",\n      \"Name\": \"a90b9998a3233a68438c8e099bd0ba98d9f62c9734e40297b8067f9fdb921eb9\",\n      \"Source\": \"/var/lib/docker/volumes/a90b9998a3233a68438c8e099bd0ba98d9f62c9734e40297b8067f9fdb921eb9/_data\",\n      \"Destination\": \"/var/lib/postgresql/data\",\n
    3. Stop all the IRIS dockers : docker-compose stop 4. Create a new empty volume : docker volume create --name iris-web_db_data 5. Run a volume copy via a dummy image :
    docker run --rm -it -v <previous_db_volume_id>:/from:ro -v iris-web_db_data:/to alpine ash -c \"cd /from ; cp -av . /to\"\n# With the example of 2., this gives \ndocker run --rm -it -v a90b9998a3233a68438c8e099bd0ba98d9f62c9734e40297b8067f9fdb921eb9:/from:ro -v iris-web_db_data:/to alpine ash -c \"cd /from ; cp -av . /to\"\n
    6. Pull the last changes from the repository, checkout to v1.4.4, build and run.

    git pull origin git checkout v1.4.4\ndocker-compose build docker-compose up 
    7. The data should be successfully transferred.

    Do not forget to clear out your browser cache, many JS files were changed.

    "},{"location":"operations/upgrades/#v143","title":"v1.4.3","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/upgrades/#v142","title":"v1.4.2","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/upgrades/#v141","title":"v1.4.1","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/upgrades/#v140","title":"v1.4.0","text":"

    A patch exists for this version. Please directly upgrade to v1.4.4

    "},{"location":"operations/access_control/","title":"Access control","text":"

    Introduced in v2.0.0

    IRIS offers a granular access control for cases and management features. Two types of access control are available :

    To ease the access control, users can be managed in :

    A user can be in one or multiple groups. The effective case access control of a user is deduced from its groups membership and its own cases access control. The effective permissions are deduced from its groups membership.

    "},{"location":"operations/access_control/#cases-access-control-overview","title":"Cases access control overview","text":"

    Cases access control offer three levels:

    As mentioned above, cases access control can be applied to groups and users. It starts with the groups and ends with atomic user access control.

    For example, the following configuration gives no access to the user since the atomic user access prevail upon the rest.

    stateDiagram-v2\n    DefaultPermission --> Group_prevail: FullAccess\n\n    state join_groups <<join>>\n    Group1 --> join_groups: ReadOnly\n    Group2 --> join_groups: DenyAll\n    join_groups --> Group_prevail: ReadOnly\n    Group_prevail --> Effective_DenyAll: ReadOnly \n\n    Effective_DenyAll: Resulting Deny All access for user\n    User_Access --> Effective_DenyAll: DenyAll

    In the next configuration, the user has Read Only access to the case because the atomic user access is not set, so the access is inherited from the group ownership.

    stateDiagram-v2\n    state join_groups <<join>>\n    Group1 --> join_groups: ReadOnly\n    Group2 --> join_groups: DenyAll\n    Group3 --> join_groups: DenyAll\n    join_groups --> Group_prevail: ReadOnly\n\n    Effective_ReadOnly: Resulting Read Only access for user\n    Group_prevail --> Effective_ReadOnly: ReadOnly \n\n    User_Access --> Effective_ReadOnly: Unset

    This notably allows to create groups which can join a set of people from different organisations to work on the same case.

    "},{"location":"operations/access_control/#permissions-control","title":"Permissions control","text":"

    Permissions allow to control the access to specific management features on the platform (adding users, cases etc.). Two permissions are available:

    "},{"location":"operations/access_control/authentication/","title":"Authentication","text":"

    IRIS supports local and LDAP authentication. In both cases, users need to be declared in IRIS.

    "},{"location":"operations/access_control/authentication/#local-authentication","title":"Local authentication","text":"

    Local authentication is the default setting. The password is validated against the local IRIS database. Passwords are stored salted and hashed, it is thus not possible to retrieve them in case they are lost. It is however possible to change them.

    "},{"location":"operations/access_control/authentication/#changing-a-lost-password","title":"Changing a lost password","text":"

    If another administrative user exists : Being logged as this user, head to the Advanced > Access Control > Users section, and change the administrator password.

    If no other administrative user exists : the change cannot be done via IRIS and an access to the backend is needed.

    Danger

    Do not delete and recreate any users directly from the DB! This will create inconsistencies in the relations and certainly corrupt everything.

    1. Generate the hash of the new password with Python BCrypt in Python prompt

      import bcrypt\nprint(bcrypt.hashpw('<new_password>'.encode('utf-8'), bcrypt.gensalt()))\n
    2. Connect to the DB docker then the Postgresql database iris_db and update the password

      docker exec -ti <db_docker_id> /bin/bash\n/ # su postgres\n/ # psql\npostgres=# \\c iris_db \npostgres=# UPDATE \"user\" SET password = '<hash>' WHERE \"user\".name = 'administrator';\npostgres=# \\q\nexit\nexit\n
    "},{"location":"operations/access_control/authentication/#ldap-authentication","title":"LDAP authentication","text":"

    LDAP authentication rely on a LDAP server to verify the password of a user. The user needs to be declared in IRIS.

    graph LR\n    A[User] -->|Authenticate| B(IRIS WebApp)\n    B --> C{User exists in DB?}\n    C -->|Yes| D{LDAP accepted password?}\n    C -->|No| E[Authentication failed]\n    D -->|Yes| F[Authentication succeeded]\n    D -->|No| E[Authentication failed]
    "},{"location":"operations/access_control/authentication/#settings","title":"Settings","text":"

    The LDAP settings are present in the .env. Once the LDAP server information is set, reboot the Iris WebApp docker needs to be restarted.

    docker-compose restart app\n
    "},{"location":"operations/access_control/authentication/#setting-up-ldap-for-the-first-runtime-of-iris","title":"Setting up LDAP for the first runtime of IRIS","text":"

    To set up LDAP without having run IRIS priorly, and as the app needs the accounts to be created first before using LDAP, one has to set the IRIS_ADM_EMAIL environment with the LDAP Email of the administrator user.

    Example of LDAP configuration for first run
    IRIS_AUTHENTICATION_TYPE=ldap\n\n## IP address or FQDN of the ldap server\nLDAP_SERVER=dc1.domain.local\n\n## Port of the LDAP server\nLDAP_PORT=636\n## LDAP Authentication type\nLDAP_AUTHENTICATION_TYPE=SIMPLE\n\n## Prefix to search the users within \nLDAP_USER_PREFIX=uid=\n## Suffix to search the users within\nLDAP_USER_SUFFIX=ou=people,dc=example,dc=com\n\n## Set to True to use LDAPS\nLDAP_USE_SSL=True\n\n## Set to True to verify the server certificate validity\nLDAP_VALIDATE_CERTIFICATE=True\n\n## TLS version to use LDAPS\nLDAP_TLS_VERSION=1.2\n\n## LDAP TLS configuration \nLDAP_CUSTOM_TLS_CONFIG=False\n\n# Set email address of the first user, that will be the admin \nIRIS_ADM_EMAIL=adm@example.com 
    "},{"location":"operations/access_control/authentication/#setting-up-for-active-directory","title":"Setting up for Active Directory","text":"

    To use LDAP with an Active Directory, the following settings can be used:

    Example of LDAP configuration for first run with Active Directory
    IRIS_AUTHENTICATION_TYPE=ldap\n\n## IP address or FQDN of the ldap server\nLDAP_SERVER=dc1.domain.local\n\n## Port of the LDAP server\nLDAP_PORT=636\n## LDAP Authentication type\nLDAP_AUTHENTICATION_TYPE=SIMPLE\n\n## Prefix to search the users within\nLDAP_USER_PREFIX=DOMAIN\\\n## Suffix to search the users within\nLDAP_USER_SUFFIX=\n## Set to True to verify the server certificate validity\nLDAP_VALIDATE_CERTIFICATE=True\n\n## TLS version to use LDAPS\nLDAP_TLS_VERSION=1.2\n\n## LDAP TLS configuration \nLDAP_CUSTOM_TLS_CONFIG=False\n\n# Set email address of the first user, that will be the admin\nIRIS_ADM_EMAIL=adm@example.com 
    "},{"location":"operations/access_control/authentication/#setting-up-ldap-after-iris-already-ran","title":"Setting up LDAP after IRIS already ran","text":"

    To set up LDAP after IRIS was already run, one only needs to set up the settings described previously without # Set email address of admin IRIS_ADM_EMAIL=adm@example.com and restart the docker.

    Usernames in IRIS have to match the ones set in LDAP for the authentication to succeed.

    "},{"location":"operations/access_control/authentication/#ldap-certificates","title":"LDAP certificates","text":"

    If the LDAP server uses a self-signed certificate, it is possible to add it to the trusted certificates of the IRIS WebApp docker.

    1. Copy the certificate to the certificates/ldap folder of the IRIS root directory.
    2. Set the LDAP_VALIDATE_CERTIFICATE environment variable to True in the .env file.
    3. Set the LDAP_CUSTOM_TLS_CONFIG environment variable to False in the .env file.
    4. Set the LDAP_CA_CERTIFICATE environment variable certificate path used by the LDAP server in the .env file.

    If the LDAP server requires a client certificate, it is possible to add it to the trusted certificates of the IRIS WebApp docker.

    1. Copy the certificate and key to the certificates/ldap folder of the IRIS root directory.
    2. Set the LDAP_VALIDATE_CERTIFICATE environment variable to True in the .env file.
    3. Set the LDAP_CUSTOM_TLS_CONFIG environment variable to True in the .env file.
    4. Set the LDAP_PRIVATE_KEY environment to the file name of the key in the .env file
    5. Set the LDAP_PRIVATE_KEY_PASSWORD environment variable to the password of the key in the .env file - if needed
    "},{"location":"operations/access_control/groups/","title":"Groups","text":"

    Groups offer the possibility to set case access as well as permissions. By default two groups are created:

    Both groups are set to give full cases access to the users.

    "},{"location":"operations/access_control/groups/#setting-up-a-new-group","title":"Setting up a new group","text":"

    Head to the Access Control page and click Add group.

    Fill the form. All the fields can be changed later on. The field Group name has to be unique on the IRIS instance. Access control and members can be set once the group is created.

    "},{"location":"operations/access_control/groups/#configuring-the-group","title":"Configuring the group","text":"

    The group can be configured once created by clicking on it in the list.

    "},{"location":"operations/access_control/groups/#users","title":"Users","text":""},{"location":"operations/access_control/groups/#adding-users-to-a-group","title":"Adding users to a group","text":"

    To add users to the group, go to the Members tab and click Manage.

    The User Manager should load and offers a list of users that can be added to the group. Select all the users you want to add to the group and press Save.

    Permissions computation

    When a user is added/removed to a group, its effective cases access are recomputed. Depending on the number of cases and users added/removed this can take some time. This process helps reducing the DB load when using IRIS during normal operation.

    "},{"location":"operations/access_control/groups/#removing-users-from-a-group","title":"Removing users from a group","text":"

    To remove users from the group, go to the Members tab and click Manage.

    The User Manager should load and present a list of both users already in the group as well as the ones that can be added. To remove one or more users, un-tick them from the list and press Save.

    Alternatively, a user can be directly removed from within the group manager. Click on the red trash next to the user to remove and confirm the deletion.

    "},{"location":"operations/access_control/groups/#cases","title":"Cases","text":""},{"location":"operations/access_control/groups/#adding-cases-to-the-group","title":"Adding cases to the group","text":"

    Access to one or multiple existing cases can be granted to a group. From within the Group Manager, go to the Cases Access tab and click Set case access.

    The Cases Access Manager loads and gives the possibility to set the access to one or more cases.

    Three choices of access are offered:

    Once the desired access is selected, press Set access.

    Permissions computation

    As for the addition of users, when a case is added/removed to a group, all the users' effective cases access are recomputed. Depending on the amount of cases added/removed and number of users this can take some time. This process helps reducing the DB load when using IRIS during normal operation.

    "},{"location":"operations/access_control/groups/#removing-cases-from-the-group","title":"Removing cases from the group","text":"

    From within the Group Manager, go to the Cases Access tab. Click on the red trash next to the case to remove and confirm the deletion.

    "},{"location":"operations/access_control/groups/#removing-a-group","title":"Removing a group","text":"

    A group can be deleted by clicking on its name in the list and then Delete at the bottom of the Info tab.

    "},{"location":"operations/access_control/users/","title":"Users","text":"

    Authentication

    Looking for authentication settings? It's here

    Whatever the authentication mechanism used (Local or LDAP), the users have to be declared in IRIS. This is done in Advanced > Access Control > Users.

    "},{"location":"operations/access_control/users/#adding-a-user","title":"Adding a user","text":"

    Head to Advanced > Access Control > Users and click Add user. All fields of the form are required. All information can be changed after the creation.

    Note

    Permissions and groups can be set once the user is created.

    Service accounts

    Service accounts users can use the API to perform any actions on the instance. They cannot login to the UI and they don't have a password.

    "},{"location":"operations/access_control/users/#editing-a-user","title":"Editing a user","text":"

    A user can be edited by clicking on its name or ID in Advanced > Access Control > Users. A window opens and display the user's information. Tabs at the top allow to configure multiple settings related to the user.

    "},{"location":"operations/access_control/users/#setting-permissions","title":"Setting permissions","text":"

    Permissions of a user cannot be set directly. They are inherited from the groups membership. The tab Permissions only displays the permissions the user has from its groups memberships. See Groups for more info.

    "},{"location":"operations/access_control/users/#setting-groups","title":"Setting groups","text":"

    Groups can be set by clicking on the Groups tab of the user's window and then Manage.

    A new window appears with the possibility to select the groups the user should belong to.

    After saving, the permissions of the user are updated. This can be verified in the Permissions tab.

    "},{"location":"operations/access_control/users/#setting-cases-access","title":"Setting cases access","text":"

    Cases access are usually set through groups membership. However for granularity they can be set per user. To set the access of a user on a case, click on the Cases access tab of the user's window and then Set case access.

    As for the Groups, a selector appears and allows to select one or multiple cases and the access to associate.

    Info

    Application of a case access is immediate, even if the user is logged in and browsing the case.

    Info

    Granular case access can also be set from a case itself, in Summary > Manage > Access.

    "},{"location":"operations/access_control/users/#deactivating-a-user","title":"Deactivating a user","text":"

    A user can be deactivated, which has the following impact:

    "},{"location":"operations/access_control/users/#deleting-a-user","title":"Deleting a user","text":"

    It is usually not possible to delete a user. This is to keep consistency in the database. A user can be deleted if it has done absolutely no actions on the platform. If a user leaves the organisation, it is recommended to rename the user and deactivate it.

    "},{"location":"operations/cases/case_operations/","title":"Case operations","text":""},{"location":"operations/cases/case_operations/#opening-a-case","title":"Opening a case","text":"

    To open a case from the dashboard, press Add case in the top right corner. Otherwise, go to the Manage Cases tab and press Add case in the top right corner.

    A new window appears, requesting additional information. The following information are required:

    The following information is optional:

    Once Create is clicked, the case is created and a popup ask whether to the get redirected to the case or to add a new one.

    "},{"location":"operations/cases/case_operations/#switching-between-cases","title":"Switching between cases","text":"

    Each case has its own context. To switch between cases/context, either click on the name of the current case at the top left, or click on the switch button on the top right.

    A popup appears and allows to select the case to switch to. By default the last 100 cases are displayed. To look further in the past, one can use the search bar. Press Save to validate the switch. The page reloads with the new context.

    "},{"location":"operations/cases/case_operations/#updating-a-case","title":"Updating a case","text":"

    A case metadata can be updated by going switching the case context and heading to Case > Summary. Clicking on Manage brings up a new window with the case metadata. The right pencil button allows to edit the metadata.

    The following information can be updated:

    "},{"location":"operations/cases/case_operations/#updating-the-access-of-a-case","title":"Updating the access of a case","text":"

    The access of a case can be updated by going to Case > Summary > Manage, and from the popup, clicking on the Access tab.

    Changes of access are immediately applied.

    "},{"location":"operations/cases/case_operations/#closing-a-case","title":"Closing a case","text":"

    A case can be closed by going to Case > Summary > Manage, and from the popup, clicking on the Close case button. Closing a case doesn't delete it and it can be reopened at any time. The case can also be modified after it has been closed.

    "},{"location":"operations/cases/case_operations/#getting-modifications-history-of-a-case","title":"Getting modifications history of a case","text":"

    The modifications history of a case can be retrieved by going to Case > Summary > Manage, and from the popup, clicking on the history icon next to the case name.

    "},{"location":"operations/cases/iocs/","title":"IOCs","text":"

    IOCs are observables that were identified during the investigation, or that led to the case creation upon monitoring activities.

    "},{"location":"operations/cases/iocs/#add-an-ioc","title":"Add an IoC","text":"

    An IoC object could be created by going to Case > IOC. Clicking on Add IOC in the top right corner brings up a new window for the IoC creation.

    A new window appears, requesting additional information. The following information is required:

    The following information is optional:

    Once Save is clicked, the ioc is created.

    "},{"location":"operations/cases/iocs/#update-an-ioc","title":"Update an IoC","text":"

    IoC object data can be updated by clicking on the IoC value in the Case > IOC table. A popup appears and allows to change required and non-required fields.

    Once Update is clicked, the IoC is updated.

    "},{"location":"operations/cases/iocs/#enrich-an-ioc","title":"Enrich an IoC","text":"

    IoC objects can be enriched in order to add valuable information to it.

    "},{"location":"operations/cases/iocs/#comment-an-ioc","title":"Comment an IoC","text":"

    To comment an IoC, one can right click on it, in the Case > IOC menu, and select Comment. A new pop-up appears and allows to leave comments. This is also achievable by clicking on the IoC value in the Case > IOC table, and by clicking on the Comment button.

    "},{"location":"operations/cases/iocs/#launch-a-module-on-an-ioc","title":"Launch a module on an IoC","text":"

    To have more information about modules, see the Modules section.

    A set of modules can be launched to enrich IoCs. To do so, one can right click on the IoC , in the Case > IOC table, and select the module of choice. This is also achievable by clicking on the IoC value in the Case > IOC table, by clicking the Option button, and selecting the desired module.

    The results of the module will appear in newly created tabs, in the IoC details. To view the tabs, click on the the IoC value.

    "},{"location":"operations/cases/iocs/#delete-an-ioc","title":"Delete an IoC","text":"

    This will permanently delete the IoC and its attributes

    To delete an IoC, one could either right click on the IoC, and select Delete, or click on the IoC value, and click on the Delete button.

    The IOC is only unlinked from the case if it references other cases

    "},{"location":"operations/cases/notes/","title":"Notes","text":"

    IRIS allows analysts to add notes to cases. Notes can be added to a case from the Notes tab. Notes are organized by groups. A note has to be within a group.

    "},{"location":"operations/cases/notes/#adding-a-group","title":"Adding a group","text":"

    To add a group, click on the Add note group button on the top right.

    The title of the group note can be edited by clicking direclty on it and typing the new title. Validated with the green checkmark.

    "},{"location":"operations/cases/notes/#adding-a-note","title":"Adding a note","text":"

    To add a note, click on the + button on the top right of the target note group. A new note is added to the group. To edit it, click on the note and type the new content.

    1. The title of the note. It is viewable in the group note list.
    2. The content editor. This is where the note should be written. The editor supports Markdown. The toolbar on top of the editor allows to format the text.
    3. The live preview of the note. This is how the note is rendered.
    4. The edit button. Clicking on it allows to edit or view the note.
    5. The zen button. Useless but allows to concentrate on the note.
    6. The comment button. Allows to set comments on the note.
    7. The options button. Allows to share the note and more.
    8. The minimize button. Allows to minimize the note, allowing to copy text from somewhere else.
    "},{"location":"operations/cases/tasks/","title":"Tasks","text":"

    Tasks allow incident handlers to split the workload into unit tasks, and to assign them to the team members.

    "},{"location":"operations/cases/tasks/#add-a-task","title":"Add a task","text":"

    A task can be created by going to Case > Tasks. Clicking on Add Task in the top right corner brings up a new window for the task creation.

    A new window appears, requesting additional information. The following information is required:

    The following information is optional:

    Once Save is clicked, the task is created.

    "},{"location":"operations/cases/tasks/#update-a-task","title":"Update a task","text":"

    Task metadata can be updated by clicking on the task title in the Case > Tasks table. A popup appears and allows to change required and non-required fields.

    Once Update is clicked, the task is updated.

    "},{"location":"operations/cases/tasks/#comment-a-task","title":"Comment a task","text":"

    Tasks can be commented. This provide the ability for analysts to give more in-deepth information on the task execution (what did they do, how did they do, what are the results, etc.)

    To comment a task, one can either right click on the task line and select Comment, or click on the task title, and click on the Comment button. A new windows appears and allows to add comments to the task.

    Once Comment is clicked, in the last window, a comment is added to the task. Comments are editable and removable.

    "},{"location":"operations/modules/","title":"Introduction","text":"

    New types of modules are introduced in IRIS v1.4.0

    IRIS can be extended with modules. They can be split in two types:

    Modules (or DIM - DFIR-IRIS Modules) are actually Python packages which must be installed in the Python environment of iris-webapp and the worker (see Quick Start). Once installed in the Python environment, modules can be managed in Advanced > Modules.

    Info

    This section is only available for users with the Admin role.

    By default IRIS is shipped with multiple modules.

    "},{"location":"operations/modules/mod_management/","title":"Management","text":"

    To add a module, the user can click on the \"+\" button:

    Then the user must enter the name of the pre-installed module. The name of the pip package must be used.

    If everything is ok, the module will appear on the list. It is currently disabled, and needs configuration before it can be enabled. To do so, the user can click on the module's name:

    A new text box appears, showing information about the module, and a list of parameters to configure. Each mandatory parameter must be configured to enable the module.

    After configuring all the mandatory parameters, the \"Enable button\" is revealed and the user can finally enable the module.

    That's all! The user can confirm in the summary that the module is indeed enabled and ready to use.

    Finally, the user can either disable or remove the module by clicking on the according buttons.

    Now that the module is configured and enabled, let's see how we can use it!

    NB: As a temporary fix, after adding and configuring a module, one must restart the IRIS services (dockers) else the worker won't have the module installed properly.

    "},{"location":"operations/modules/mod_management/#how-to-use-the-module","title":"How to use the module","text":"

    As stated in the beginning, a module extends the capabilities of IRIS. For now, it allows importing evidences of your needs into what we call a pipeline, where data will be handled in the module (checking, parsing, ingestion...). In our provided module, IrisEVTXModule ingest EVTX files, parse them as JSON, and send the results to a Splunk instance using its HTTP event collector (HEC) endpoint.

    In IRIS, the files are always imported in the context of a case. To import a file, the user can click on Manage cases then Update tab.

    In Processing pipeline, the user can pick a pipeline that will send the files to the wanted module. In our example, EVTX pipeline refers to the IrisEVTXModule module. Below, the user can fill the arguments needed by the according pipeline. Arguments can be optional. Finally, the user can import one or several files and click Update to start their processing by the module.

    You can see in the picture below that the user will import four EVTX files.

    The user can follow the upload of the different files with their respective progress bars.

    Once uploaded, the status of the task can be observed on the DIM Tasks page.

    Clicking on a Task ID shows information on the task processing.

    After the processing of the files by the module, the list of the imported files is stored in the Evidences tab of the according case.

    "},{"location":"operations/modules/natives/IrisMISP/","title":"Module IRIS MISP","text":"

    Introduced in IRIS v1.4.0

    This module offers an interface with MISP and IRIS to automatically enrich IOCs with MISP insight.

    The source code is available here. It is installed by default but needs to be configured to be enabled.

    Note

    The module is in its early stage and new features will be added over time.

    "},{"location":"operations/modules/natives/IrisMISP/#features","title":"Features","text":"

    Two types of enrichement mecanism are proposed :

    The following types of IOCs are handled by the module :

    The insight request on an IOC not handled is simply ignored.

    The insights take the form of attributes added to the IOC. They are based on configurable templates.

    "},{"location":"operations/modules/natives/IrisMISP/#configuration","title":"Configuration","text":"

    The behavior of the module can be configured as needed. Head to the Advanced > Modules > IrisMISP to change it.

    "},{"location":"operations/modules/natives/IrisMISP/#misp-configuration","title":"MISP configuration","text":"

    At the time, only one MISP can be added. Future version might handled more than one MISP. The expected structure is the following :

    {\n\"name\": \"Public_MISP\", \"type\":\"public\", \"url\":[\"https://testmisp\"],\n\"key\":[\"<apikey>\"], \"ssl\":[false]\n}\n
    "},{"location":"operations/modules/natives/IrisVT/","title":"Module IRIS VT","text":"

    Introduced in IRIS v1.4.0

    This module offers an interface with VirusTotal and IRIS to automatically enrich IOCs with VT insight. The source code is available here. It is installed by default but needs to be configured to be enabled.

    "},{"location":"operations/modules/natives/IrisVT/#features","title":"Features","text":"

    Two types of enrichment mechanism are proposed :

    The following types of IOCs are handled by the module :

    The insight request on an IOC not handled is simply ignored.

    Two types of insights are proposed :

    "},{"location":"operations/modules/natives/IrisVT/#configuration","title":"Configuration","text":"

    The behavior of the module can be configured as needed. Head to the Advanced > Modules > IrisVT to change it.

    "},{"location":"operations/modules/natives/IrisWebHooks/","title":"Module IRIS Webhooks","text":"

    This module offers webhooks support for IRIS. It can be configured to send almost any events to to an external service supporting webhooks, such as Discord, Slack or Microsoft Teams. It can also be used with automation tools such as Tines and Shufle to further automate IRIS. The source code is available here.

    "},{"location":"operations/modules/natives/IrisWebHooks/#features","title":"Features","text":"

    Slack Example

    "},{"location":"operations/modules/natives/IrisWebHooks/#configuration","title":"Configuration","text":"

    The expected configuration is a JSON file, following the structure :

    {   \"instance_url\": \"<IRIS_INSTANCE_URL>\",\n\"webhooks\": [\n{\n\"name\": \"Name of the webhook for internal reference only\",\n\"active\": false,\n\"trigger_on\": [<LIST OF HOOKS TO LISTEN TO>],\n\"request_url\": \"<URL OF THE WEBHOOK>\",\n\"use_rendering\": true,\n\"request_rendering\": \"<RENDERING TYPE OF THE MESSAGE>\", \"request_body\": {<BODY OF THE REQUET TO SEND>}\n},\n{\n\"name\": \"Another hook\",\n\"active\": false,\n\"use_rendering\": false,\n\"trigger_on\": [<LIST OF HOOKS TO LISTEN TO>],\n\"request_url\": \"<URL OF THE WEBHOOK 2>\",\n\"request_rendering\": \"<RENDERING TYPE OF THE MESSAGE>\", \"request_body\": {<BODY OF THE REQUEST TO SEND 2>}\n}\n]\n}\n
    "},{"location":"operations/modules/natives/IrisWebHooks/#checking-iris-hooks-registration","title":"Checking IRIS hooks registration","text":"

    Each time a webhook is added, the module subscribes to the specified hooks. After saving the configuration, one can check the registration was successful by filtering the Registered hooks table (don't forget to refresh the table).

    "},{"location":"operations/modules/natives/IrisWebHooks/#examples-without-rendering","title":"Examples without rendering","text":"

    The following example is a combination of webhooks that can be used to further automate IRIS. It uses Tines as an example, but this is reproductible with any automation tool that can sent HTTP requests. A Tines story is created and is set up to receive a webhook, such as https://anothertest.tines.io/webhook/xxxx/xxxxx. In this scenario, two IRIS webhooks are added:

    We use the same Tines story and thus Tines webhook for both and dispatch the incoming request depending on its parameters.

    "},{"location":"operations/modules/natives/IrisWebHooks/#todo","title":"TODO","text":""},{"location":"operations/modules/natives/IrisWebHooks/#examples-using-rendering","title":"Examples using rendering","text":"

    The following is an example of combined webhooks configuration. It can be directly imported in the module with the import feature. Please note that after import, the configuration should be opened and change to match your URL webhook receiver.

    Download webhooks combined configuration example

    "},{"location":"operations/modules/natives/IrisWebHooks/#discord","title":"Discord","text":"Discord webhook example - selection of events
    {   \"instance_url\": \"https://iris.local\",\n\"webhooks\": [\n{\n\"name\": \"Discord\",\n\"trigger_on\": [\n\"on_postload_ioc_create\",\n\"on_postload_ioc_update\",\n\"on_postload_note_create\",\n\"on_postload_note_update\"\n],\n\"request_url\": \"https://discord.com/api/webhooks/XXXX/XXXX\",\n\"request_rendering\": \"markdown\", \"request_body\": {\n\"embeds\": [{\n\"description\" : \"%DESCRIPTION%\",\n\"title\" : \"%TITLE%\"\n}]\n}\n}\n]\n}\n
    "},{"location":"operations/modules/natives/IrisWebHooks/#slack","title":"Slack","text":"Slack webhook example - all events
    {   \"instance_url\": \"https://iris.local\",\n\"webhooks\": [\n{\n\"name\": \"Slack\",\n\"trigger_on\": [\n\"all\"\n],\n\"request_url\": \"https://hooks.slack.com/services/<XXX>/<XXX>/<XXX>\",\n\"request_rendering\": \"markdown_slack\",\n\"request_body\": {\n\"text\": \"%TITLE%\",\n\"blocks\": [\n{\n\"type\": \"section\",\n\"text\": {\n\"type\": \"mrkdwn\",\n\"text\": \"*%TITLE%*\"\n}\n},\n{\n\"type\": \"section\",\n\"block_id\": \"section567\",\n\"text\": {\n\"type\": \"mrkdwn\",\n\"text\": \"%DESCRIPTION%\"\n}\n}\n]\n}\n}\n]\n}\n
    "},{"location":"operations/modules/natives/IrisWebHooks/#troubleshooting","title":"Troubleshooting","text":"

    Webhooks receivers are expecting specific message formatting to successfully process them. Please carefully read their documentations.

    The module only handles JSON POST for the moment. If the target webhook receiver needs another type of request, please contact us so we can add it.

    As any IRIS module, IrisWebhooks is logged into DIM Tasks. You can check the status of the requests made in these. Go to DIM Tasks and then filter with webhooks. You can then check details info by clicking in the Task ID. More info might be available in the Docker worker logs depending on the situation.

    "},{"location":"operations/modules/natives/IrisWebHooks/#important-notes-and-know-issues","title":"Important Notes and know issues","text":""},{"location":"python_client/","title":"Introduction","text":"

    dfir_iris_client offers a Python interface to communicate with IRIS.

    It relies exclusively on the API, which means output of the methods are the same as specified in the API reference.

    "},{"location":"python_client/#installation","title":"Installation","text":"

    It can be easily with pip : pip3 install dfir_iris_client.

    The source code of the project is available here.

    "},{"location":"python_client/#versions","title":"Versions","text":"

    The Python client version follows the API versions (until the patch level). Meaning for API v1.0.1, one need to install dfir_iris_client-1.0.1.

    "},{"location":"python_client/#examples","title":"Examples","text":"

    Examples of usage are available here.

    "},{"location":"python_client/#documentation","title":"Documentation","text":"

    The documentation of the client is available on client.docs.dfir-iris.org.

    "}]} \ No newline at end of file diff --git a/security-advisories/index.html b/security-advisories/index.html index 8a1f356..07b8885 100644 --- a/security-advisories/index.html +++ b/security-advisories/index.html @@ -1541,7 +1541,7 @@

    Workarounds

    Last update: - 2023-05-25 + 2023-12-30 diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 98dd1de..8d53bbc 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ