Skip to content
This repository has been archived by the owner on Mar 30, 2024. It is now read-only.

Commit

Permalink
Merge branch 'main' into update-requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-intuitem authored Nov 9, 2023
2 parents a891eb0 + 4a4cb6b commit c678628
Show file tree
Hide file tree
Showing 15 changed files with 6,367 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ ciso_assistant/build.json
*.sqlite3
db/django_secret_key
db/attachments/
db/data/
db/pg_password.txt
63 changes: 63 additions & 0 deletions Contributor License Agreement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# intuitem Contributor License Agreement (CLA)

## Human-Friendly Summary

This is a human-readable summary of (and not a substitute for) the full agreement. It has no legal value and you should carefully review all the terms of the actual CLA (following section **Legal Notice and Agreement**) before agreeing.

- Grant of copyright license. You give intuitem permission to use your copyrighted work in open-source and commercial products.
- Grant of patent license. If your contributed work uses a patent, you give intuitem a license to use that patent including within open-source and commercial products. You also agree that you have permission to grant this license.
- No Warranty or Support Obligations. By making a contribution, you are not obligating yourself to provide support for the contribution, and you are not taking on any warranty obligations or providing any assurances about how it will perform.

The CLA does not change the terms of the underlying license used by our software such as the AGPLv3 License. You are still free to use our projects within your own projects or businesses, republish modified source code, and more subject to the terms of the project license.

## Why Require a CLA?

Agreeing to a CLA explicitly states that you are entitled to provide a contribution, that you cannot withdraw permission to use your contribution at a later date, and that intuitem has permission to use your contribution in our open-source and commercial products.

This removes any ambiguities or uncertainties caused by not having a CLA and allows users and customers to confidently adopt our projects. At the same time, the CLA ensures that all contributions to our open source projects are licensed under the project's respective open source license, such as AGPLv3.

intuitem is committed to open-source for its non-commercial software. A CLA enables intuitem to safely commercialize its products while promoting open-source, which allows to build a sustainable business.

Requiring a CLA is a common and well-accepted practice in open source. Major open source projects require CLAs such as Apache, Kubernetes, Docker, Python, Django, and more.

## Signing the CLA

When you open a pull request ("PR") to any of our projects for the first time, a bot will comment on the PR asking you to sign the CLA if you haven't already.

Follow the steps given by the bot to sign the CLA. We will only use this information for CLA tracking; none of your submitted information will be used for marketing purposes.

You only have to sign the CLA once. Once you've signed the CLA, future contributions to any intuitem project will not require you to sign again.

## Legal Notice and Agreement

### Introduction

The purpose of this contributor agreement ("Agreement") is to clarify and document the rights granted by contributors to Intuitem SARL ("**intuitem**").

By contributing to any open-source project maintained by intuitem, you acknowledge and accept these terms and conditions.

### 1. Definitions

a. **Contributor:** "You" (or "Your") means the copyright owner or legal entity authorized by the copyright owner entering into this Agreement with intuitem. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered a single Contributor. For the purposes of this definition, "control" means (i) the authority, direct or indirect, to have the direction or management of such an entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.

b. **Contribution:** "Contribution" means any original work by the author, including any modifications or additions to an existing work, that is or has already been intentionally submitted by You to intuitem for inclusion or documentation in any of the products owned or operated by intuitem (the "Work"). For the purposes of this definition, the term "submitted" means any form of electronic, verbal, or written communication sent to intuitem or its representatives, including, but not limited to, communication on electronic mailing lists, source control systems, and issue tracking systems that are operated by or on behalf of intuitem for the purpose of discussing and improving the Work, excluding communications that are clearly marked or otherwise designated in writing by You as "not constituting a contribution."

### 2. Grant of License

a. **Copyright License:** Subject to the terms and conditions of this Agreement, You hereby grant to intuitem and the recipients of the Material distributed by intuitem a perpetual, worldwide, non-exclusive, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.

b. **Patent License:** Subject to the terms and conditions of this Agreement, You hereby grant to intuitem and the recipients of the Material distributed by intuitem a perpetual, worldwide, non-exclusive, royalty-free, irrevocable patent license (except as otherwise provided in this section) to make, have made, use, offer for sale, sell, import, and otherwise transfer the Work. This license applies only to patent claims that may be licensed by You and that are necessarily infringed by Your Contribution(s) alone or by the combination of Your Contribution(s) with the work to which such Contribution(s) has been submitted. If an entity brings a patent lawsuit against You or any other entity (including a counterclaim or counterclaim in a legal action) alleging that Your Contribution, or the Work to which you contributed, constitutes direct or contributory patent infringement, then all patent licenses granted to that entity under this Agreement for such Contribution or Work will take effect on the date on which this dispute is filed.

### 3. Representations

You represent that You are legally authorized to grant the above license. If Your employer(s) have rights to the intellectual property that You create that include Your Contributions, You represent that You have received permission to make Contributions on behalf of that employer, that You have received permission from Your current and future employers for all future Contributions, or that Your applicable employer has waived such rights for all of Your current and future Contributions to intuitem.

You represent that each of Your contributions is Your original creation and that Your Contribution Submissions include full details of any third-party licenses or other restrictions (including, but not limited to, related patents and trademarks) of which You are personally aware and that are associated with any portion of Your Contributions.

### 4. Support and Warranties

You are not required to provide support for Your contributions, except to the extent that You wish to provide support. You can provide support for free, paid, or not at all. Unless required by applicable law or agreed to by You in writing, You provide Your Contributions "AS IS," WITHOUT WARRANTY OR CONDITION OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.

### 5. Reporting

You agree to inform intuitem of any facts or circumstances of which you become aware that cause such statements to be inaccurate in any respect.
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ Read the [full article](https://intuitem.com/blog/we-are-going-open-source/) abo

## Supported frameworks

- ISO 27001
- ISO 27001:2022
- NIST Cyber Security Framework (CSF) v1.1
- NIS2
- SOC2
- PCI DSS 4.0
- CMMC v2

Checkout the [library](/library/libraries/) for the Domain Specific Language used and how you can define your own.
### Coming soon

- CMMC
- GDPR checklist
- ANSSI CyberScore
- NIST CSF v2

## Community

Join our [open Discord community](https://discord.gg/qvkaMdQ8da) to interact with the team and other GRC experts.
Expand All @@ -50,7 +53,7 @@ To install gettext and pango, do `sudo apt update && sudo apt install gettext li

### Quick start 🚀

There are two methods to run CISO locally: using Python or using Docker.
There are three methods to run CISO locally: using Python, using Docker or using docker-compose.

By default, Django secret key is generated randomly at each start of Mira. This is convenient for quick test, but not recommended for production, as it can break the sessions (see this [topic](https://stackoverflow.com/questions/15170637/effects-of-changing-djangos-secret-key) for more information). To set a fixed secret key, use the environment variable DJANGO_SECRET_KEY.

Expand Down Expand Up @@ -102,12 +105,12 @@ python manage.py collectstatic
python manage.py createsuperuser
```

5. Run CISO
5. Run CISO Assistant

```sh
python manage.py runserver
```
You can then reach CISO using your web brower at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)
You can then reach CISO Assistant using your web brower at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)

#### Using Docker

Expand All @@ -127,7 +130,7 @@ docker run --rm -it --env CREATE_SUPERUSER=true -p 8000:8000 -v ./db:/code/db c

When asked for, enter your email and password for your superuser.

You can then reach CISO using your web brower at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)
You can then reach CISO Assistant using your web brower at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)

For the following executions, simply run:

Expand All @@ -137,7 +140,21 @@ docker run --rm -p 8000:8000 -v ./db:/code/db ciso-assistant:$(<ciso_assistant/

⚠️ *WARNING*: If you're using WSL you'll need to activate *Systemd*. Check out this [topic](https://stackoverflow.com/questions/65400999/enable-systemd-in-wsl-2) to do it.

### How to set up CISO for development? ✍️

#### Using docker-compose with a Postgres database

Simply launch:
```sh
./docker-compose-pg.sh
```

When asked for, enter your email and password for your superuser.

You can then reach CISO Assistant using your web brower at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)

For the following executions, use "docker-compose up" directly.

### How to set up CISO Assistant for development? ✍️

1. Clone the repository.

Expand Down Expand Up @@ -168,15 +185,16 @@ export EMAIL_HOST=localhost
export EMAIL_PORT=1025

```
> As said in the quickstart section, CISO generates a random Django secret key if not specified. To avoid broken sessions, it is preferable to set a fixed random value using the DJANGO_SECRET_KEY environment variable.
> As said in the quickstart section, CISO Assistant generates a random Django secret key if not specified. To avoid broken sessions, it is preferable to set a fixed random value using the DJANGO_SECRET_KEY environment variable.
**Optional variables**

```sh
# CISO will use SQLite by default, but you can setup PostgreSQL by declaring these variables
# CISO Assistant will use SQLite by default, but you can setup PostgreSQL by declaring these variables
export POSTGRES_NAME=ciso-assistant
export POSTGRES_USER=ciso-assistantuser
export POSTGRES_PASSWORD=<XXX>
export POSTGRES_PASSWORD_FILE=<XXX> # alternative way to specify password
export DB_HOST=localhost
export DB_PORT=5432 # optional, default value is 5432

Expand Down
2 changes: 1 addition & 1 deletion ciso_assistant/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.9.2
0.9.4
4 changes: 3 additions & 1 deletion ciso_assistant/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@

if 'POSTGRES_NAME' in os.environ:
print("Postgresql database engine")
fp = os.environ.get('POSTGRES_PASSWORD_FILE')
if fp:
os.environ['POSTGRES_PASSWORD'] = Path(fp).read_text().strip()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
Expand All @@ -248,7 +251,6 @@
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
print("Postgresql database engine")
else:
print("sqlite database engine")
DATABASES = {
Expand Down
24 changes: 6 additions & 18 deletions core/base_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,7 @@ class Meta:

def __str__(self) -> str:
return self.name

def clean(self) -> None:
scope = self.get_scope()
field_errors = {}
_fields_to_check = self.fields_to_check if hasattr(self, 'fields_to_check') else ['name']
if not self.is_unique_in_scope(scope=scope, fields_to_check=_fields_to_check):
field_errors['name'] = _('This name is already in use.')
super().clean()
if field_errors:
raise ValidationError(field_errors)


class AbstractBaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
Expand Down Expand Up @@ -89,16 +80,13 @@ def get_scope(self):
def clean(self) -> None:
scope = self.get_scope()
field_errors = {}
_fields_to_check = self.fields_to_check if hasattr(self, 'fields_to_check') else []
_fields_to_check = self.fields_to_check if hasattr(self, 'fields_to_check') else ['name']
if not self.is_unique_in_scope(scope=scope, fields_to_check=_fields_to_check):
for field in _fields_to_check:
if not self.is_unique_in_scope(scope=scope, fields_to_check=[field]):
field_errors[field] = ValidationError(
_(
f"{getattr(self, field)} is already in use in this scope. Please choose another value."
),
code="unique",
)
field_errors[field] = ValidationError(
_("Value already used in this scope."),
code="unique",
)
super().clean()
if field_errors:
raise ValidationError(field_errors)
Expand Down
20 changes: 10 additions & 10 deletions core/locale/fr/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ msgstr "Rechercher une preuve..."

#: core/filters.py:490
msgid "Search framework..."
msgstr "Rechercher un cadre..."
msgstr "Rechercher un référentiel..."

#: core/forms.py:32
msgid "Invalid link"
Expand Down Expand Up @@ -295,7 +295,7 @@ msgstr "Menaces"

#: core/models.py:77
msgid "Version of the framework (eg. 1.0, 2.0, etc.)"
msgstr "Version du cadre (eg. 1.0, 2.0, etc.)"
msgstr "Version du référentiel (eg. 1.0, 2.0, etc.)"

#: core/models.py:83 core/models.py:110 core/models.py:128 core/models.py:152
#: core/models.py:331 core/templates/core/assessment_list.html:109
Expand All @@ -305,14 +305,14 @@ msgstr "Version du cadre (eg. 1.0, 2.0, etc.)"
#: core/templates/core/requirement_list.html:110
#: core/templates/library/library_detail.html:97
msgid "Framework"
msgstr "Cadre"
msgstr "Référentiel"

#: core/models.py:84 core/templates/core/framework_list.html:6
#: core/templates/core/security_function_list.html:109
#: core/templates/core/sidebar.html:119
#: core/templates/core/threat_list.html:111 core/views.py:2422
msgid "Frameworks"
msgstr "Cadres"
msgstr "Référentiels"

#: core/models.py:116 core/models.py:158
msgid "Parent URN"
Expand Down Expand Up @@ -987,23 +987,23 @@ msgstr "Aucune mesure pour le moment."

#: core/templates/core/framework_list.html:105
msgid "Import framework"
msgstr "Importer un cadre"
msgstr "Importer un référentiel"

#: core/templates/core/framework_list.html:155
msgid "Delete framework?"
msgstr "Supprimer le cadre ?"
msgstr "Supprimer le référentiel ?"

#: core/templates/core/framework_list.html:165
msgid "No framework found."
msgstr "Aucun cadre trouvé."
msgstr "Aucun référentiel trouvé."

#: core/templates/core/framework_update.html:4
msgid "Edit framework"
msgstr "Modifier le cadre"
msgstr "Modifier le référentiel"

#: core/templates/core/framework_update.html:10
msgid "Framework information"
msgstr "Informations du cadre"
msgstr "Informations du référentiel"

#: core/templates/core/group_create.html:4
msgid "New user group"
Expand Down Expand Up @@ -2520,7 +2520,7 @@ msgstr ""
#~ msgstr "Nom de la preuve"

#~ msgid "Framework Name"
#~ msgstr "Nom du cadre"
#~ msgstr "Nom du référentiel"

#~ msgid "Library name"
#~ msgstr "Nom de la bibliothèque"
Expand Down
17 changes: 0 additions & 17 deletions core/migrations/0018_alter_evidence_options.py

This file was deleted.

7 changes: 7 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class Meta:
verbose_name = _("Framework")
verbose_name_plural = _("Frameworks")

fields_to_check = ['urn']

def get_next_order_id(self, obj_type: models.Model, _parent_urn: str = None) -> int:
"""
Returns the next order id for a given object type
Expand Down Expand Up @@ -117,6 +119,7 @@ class RequirementGroup(AbstractBaseModel, I18nMixin, NameDescriptionMixin, Folde
)
order_id = models.IntegerField(null=True, blank=True, verbose_name=_("Order ID"))
level = models.IntegerField(null=True, blank=True, verbose_name=_("Level"))
fields_to_check = ['urn']


class RequirementLevel(AbstractBaseModel, I18nMixin, FolderMixin):
Expand All @@ -132,6 +135,7 @@ class RequirementLevel(AbstractBaseModel, I18nMixin, FolderMixin):
)
level = models.IntegerField(null=False, blank=False, verbose_name=_("Level"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description"))
fields_to_check = ['urn']


class Requirement(AbstractBaseModel, I18nMixin, NameDescriptionMixin, FolderMixin):
Expand Down Expand Up @@ -165,6 +169,7 @@ class Requirement(AbstractBaseModel, I18nMixin, NameDescriptionMixin, FolderMixi
blank=True,
verbose_name=_("Informative reference"),
)
fields_to_check = ['urn']

class Meta:
verbose_name = _("Requirement")
Expand Down Expand Up @@ -454,6 +459,8 @@ class Status(models.TextChoices):
related_name="requirement_assessments",
)

fields_to_check = []

def __str__(self) -> str:
if self.requirement.name not in ("", "-"):
return f"{self.assessment} - {self.requirement.get_requirement_group()}. {self.requirement.get_requirement_group().description}/{self.requirement}"
Expand Down
12 changes: 12 additions & 0 deletions docker-compose-pg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#! /usr/bin/env bash

if [ -d db/data ] ; then
echo "the database seems already created"
echo "you should launch docker-compose up -d"
else
uuidgen > ./db/pg_password.txt
docker-compose up -d
echo "initialize your superuser account..."
docker-compose exec ciso-assistant python manage.py createsuperuser
echo "for successive runs you can now use docker compose up"
fi
Loading

0 comments on commit c678628

Please sign in to comment.