Skip to content

Commit

Permalink
Merge branch 'main' into feat/manage-strength-of-knowledge
Browse files Browse the repository at this point in the history
  • Loading branch information
nas-tabchiche committed Feb 26, 2024
2 parents 6085a1f + dd7d212 commit 33c500e
Show file tree
Hide file tree
Showing 99 changed files with 22,080 additions and 10,968 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ on:
pull_request:
branches: [main, develop]
types: [opened, synchronize]
paths:
- 'frontend/tests/**'
workflow_dispatch:

env:
Expand Down
19 changes: 10 additions & 9 deletions .github/workflows/startup-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,13 @@ jobs:
docker compose exec backend /bin/bash -c "[email protected] DJANGO_SUPERUSER_PASSWORD=1234 python manage.py createsuperuser --noinput && exit 0"
- name: Run tests
working-directory: ${{ env.working-directory }}
run: npx playwright test tests/functional/startup.test.ts
- uses: actions/upload-artifact@v4
if: always()
with:
name: startup-docker-test-report
path: |
${{ env.working-directory }}/tests/reports/
${{ env.working-directory }}/tests/results/
retention-days: 5
run: |
response=$(curl -d "[email protected]&password=1234" -H "Origin: https://localhost:8443" https://localhost:8443/login -k)
server_reponse='{"type":"redirect","status":302,"location":"/analytics"}'
if [[ "$response" == "$server_reponse" ]]; then
echo "Success"
exit 0
else
echo "Failure"
exit 1
fi
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
**/node_modules/
.vscode
*.sqlite3
django_secret_key
temp/
db/
81 changes: 45 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ CISO Assistant brings a different take on Cyber Security Posture Management:
![](posture.png)

This decoupling allows you to save considerable amount of time:

- reuse previous assessments,
- assess a scope against multiple frameworks at the same time,
- assess a scope against multiple frameworks at the same time,
- leave the reporting formatting and sanity check to CISO assistant and focus on your remediations

Read the [full article](https://intuitem.com/blog/we-are-going-open-source/) about the community editions on our blog.
Expand All @@ -29,7 +30,8 @@ Read the [full article](https://intuitem.com/blog/we-are-going-open-source/) abo
- CMMC v2
- PSPF

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

### Coming soon

- GDPR checklist
Expand Down Expand Up @@ -69,10 +71,12 @@ cd ciso-assistant-community

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

You can then reach CISO Assistant using your web brower at [http://localhost:3000/](http://localhost:3000/)
You can then reach CISO Assistant using your web brower at [https://localhost:8443/](https://localhost:8443/)

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

If you want to restart a fresh install, simply delete the db directory, where the database is stored.

## Setting up CISO Assistant for development

### Requirements
Expand Down Expand Up @@ -130,14 +134,18 @@ export EMAIL_HOST_USER_RESCUE=<XXX>
export EMAIL_HOST_PASSWORD_RESCUE=<XXX>
export EMAIL_USE_TLS_RESCUE=True

# You can define the email of the first superuser, useful for automation
# You can define the email of the first superuser, useful for automation. A mail is sent to the superuser for password initlization
export CISO_SUPERUSER_EMAIL=<XXX>

# By default, Django secret key is generated randomly at each start of CISO Assistant. 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).
# By default, Django secret key is generated randomly at each start of CISO Assistant. 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.
export DJANGO_SECRET_KEY=...

# Logging configuration
export LOG_LEVEL=INFO # optional, default value is INFO. Available options: DEBUG, INFO, WARNING, ERROR, CRITICAL
export LOG_FORMAT=plain # optional, default value is plain. Available options: json, plain
```

3. Choose the tool of your choice, either python-venv or virtualenv. For example:
Expand All @@ -162,14 +170,14 @@ pip install -r requirements.txt
5. If you want to setup Postgres:

- Launch one of these commands to enter in Postgres:
- ```psql as superadmin```
- ```sudo su postgres```
- ```psql```
- `psql as superadmin`
- `sudo su postgres`
- `psql`
- Create the database "ciso-assistant"
- ```create database ciso-assistant;```
- `create database ciso-assistant;`
- Create user "ciso-assistantuser" and grant it access
- ```create user ciso-assistantuser with password '<POSTGRES_PASSWORD>';```
- ```grant all privileges on database ciso-assistant to ciso-assistantuser;```
- `create user ciso-assistantuser with password '<POSTGRES_PASSWORD>';`
- `grant all privileges on database ciso-assistant to ciso-assistantuser;`

6. Apply migrations.

Expand All @@ -185,17 +193,16 @@ python manage.py migrate
python manage.py createsuperuser
```


8. Run development server.

```sh
python manage.py runserver
```

9. Configure the git hooks for generating the build name.
9. Configure the git hooks for generating the build name.

```sh
cd .git/hooks
cd .git/hooks
ln -fs ../../git_hooks/post-commit .
ln -fs ../../git_hooks/post-merge .
```
Expand All @@ -221,8 +228,8 @@ OR
```bash
export PUBLIC_BACKEND_API_URL=http://localhost:8000/api
```
Note: for docker compose, or if you use a proxy like caddy, the ORIGIN variable has to be declared too (see https://kit.svelte.dev/docs/configuration#csrf).

Note: for docker compose, or if you use a proxy like caddy, the ORIGIN variable has to be declared too (see https://kit.svelte.dev/docs/configuration#csrf).

3. Install dependencies

Expand All @@ -236,26 +243,9 @@ npm install
npm run dev
```

5. If you want to setup Postgres:

- Launch one of these commands to enter in Postgres:
- ```psql as superadmin```
- ```sudo su postgres```
- ```psql```
- Create the database "mira"
- ```create database mira;```
- Create user "mirauser" and grant it access
- ```create user mirauser with password '<POSTGRES_PASSWORD>';```
- ```grant all privileges on database mira to mirauser;```
5. Reach the frontend on http://localhost:5173

6. Prepare and apply migrations.

```sh
(venv)$ cd backend
(venv)$ pytest
```

Coming soon.
Note: Safari will not properly work in this setup, as it requires https for secure cookies. The simplest solution is to use Chrome or Firefox. An alternative is to use a caddy proxy. This is the solution used in docker-compose, so you can use it as an example.

## Managing migrations

Expand All @@ -279,6 +269,25 @@ python manage.py migrate

These migration files should be tracked by version control.

## Test harness

To run API tests on the backend, simply type "pytest" in a shell in the backend folder.

To run functional tests on the frontend, do the following actions:
- in the backend folder, launch the following commands:
```shell
[email protected] DJANGO_SUPERUSER_PASSWORD=1234 python manage.py createsuperuser --noinput
CISO_ASSISTANT_URL=http://localhost:4173 python manage.py runserver
```
- in parallel, in the frontend folder, launch the following command:
```shell
PUBLIC_BACKEND_API_URL=http://localhost:8000/api npx playwright test
```

For tests requiring mail sending, it is necessary to launch mailhog in a separate terminal.

The goal of the test harness is to prevent any regression, i.e. all the tests shall be successful. This is achieved for API tests, and will be soon achieved for functional tests.

## Built With

- [Django](https://www.djangoproject.com/) - Python Web Development Framework
Expand Down
1 change: 1 addition & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ __pycache__
*.DS_Store
*~$*
staticfiles/*
static/
*.mo
.env
.vscode
Expand Down
7 changes: 7 additions & 0 deletions backend/app_tests/api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,13 @@ def create_object(
# Uses the API endpoint to create an object with authentication
response = authenticated_client.post(url, build_params, format=query_format)

if fails:
# Asserts that the object was not created
assert (
response.status_code == expected_status
), f"{verbose_name} can not be created with authentication"
return

# Asserts that the object was created successfully
assert (
response.status_code == expected_status
Expand Down
27 changes: 22 additions & 5 deletions backend/app_tests/api/test_api_requirement_assessments.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from rest_framework.status import HTTP_400_BAD_REQUEST
from rest_framework.test import APIClient
from core.models import (
ComplianceAssessment,
Expand Down Expand Up @@ -41,7 +42,9 @@ def test_get_requirement_assessments(self, authenticated_client):
project=Project.objects.create(name="test", folder=folder),
framework=Framework.objects.all()[0],
),
"requirement": RequirementNode.objects.create(name="test", folder=folder, assessable=False),
"requirement": RequirementNode.objects.create(
name="test", folder=folder, assessable=False
),
},
)

Expand Down Expand Up @@ -76,7 +79,9 @@ def test_update_requirement_assessments(self, authenticated_client):
project=Project.objects.create(name="test", folder=folder),
framework=Framework.objects.all()[0],
),
"requirement": RequirementNode.objects.create(name="test", folder=folder, assessable=False),
"requirement": RequirementNode.objects.create(
name="test", folder=folder, assessable=False
),
},
{
"status": REQUIREMENT_ASSESSMENT_STATUS2,
Expand Down Expand Up @@ -113,14 +118,18 @@ def test_get_requirement_assessments(self, authenticated_client):
},
{
"folder": str(folder.id),
"compliance_assessment": {"id": str(compliance_assessment.id), "str": compliance_assessment.name},
"compliance_assessment": {
"id": str(compliance_assessment.id),
"str": compliance_assessment.name,
},
"requirement": str(RequirementNode.objects.all()[0].id),
},
-1,
)

def test_create_requirement_assessments(self, authenticated_client):
"""test to create requirement assessments with the API with authentication"""
"""nobody has permission to do that, so it will fail"""

EndpointTestsQueries.Auth.import_object(authenticated_client, "Framework")
folder = Folder.objects.create(name="test")
Expand All @@ -144,9 +153,14 @@ def test_create_requirement_assessments(self, authenticated_client):
"security_measures": [str(security_measure.id)],
},
{
"compliance_assessment": {"id": str(compliance_assessment.id), "str": compliance_assessment.name}
"compliance_assessment": {
"id": str(compliance_assessment.id),
"str": compliance_assessment.name,
}
},
base_count=-1,
fails=True,
expected_status=HTTP_400_BAD_REQUEST
)

def test_update_requirement_assessments(self, authenticated_client):
Expand Down Expand Up @@ -189,7 +203,10 @@ def test_update_requirement_assessments(self, authenticated_client):
},
{
"folder": str(Folder.get_root_folder().id),
"compliance_assessment": {"id": str(compliance_assessment.id), "str": compliance_assessment.name},
"compliance_assessment": {
"id": str(compliance_assessment.id),
"str": compliance_assessment.name,
},
"requirement": str(RequirementNode.objects.all()[0].id),
},
)
Expand Down
2 changes: 1 addition & 1 deletion backend/cal/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.2 on 2024-02-10 02:00
# Generated by Django 5.0.2 on 2024-02-25 00:59

from django.db import migrations, models

Expand Down
2 changes: 1 addition & 1 deletion backend/ciso_assistant/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.9.8
0.9.9
8 changes: 0 additions & 8 deletions backend/ciso_assistant/asgi.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
"""
<<<<<<<< HEAD:backend/ciso_assistant/asgi.py
ASGI config for ciso_assistant project.
========
ASGI config for mira project.
>>>>>>>> main:mira/asgi.py
It exposes the ASGI callable as a module-level variable named ``application``.
Expand All @@ -15,10 +11,6 @@

from django.core.asgi import get_asgi_application

<<<<<<<< HEAD:backend/ciso_assistant/asgi.py
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ciso_assistant.settings")
========
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mira.settings')
>>>>>>>> main:mira/asgi.py

application = get_asgi_application()
Loading

0 comments on commit 33c500e

Please sign in to comment.