diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cebdc00..b0acd34 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,13 +1,16 @@ variables: - DOCKER_IMAGE: registry.forge.hefr.ch/klagarge/mse2425-grp09/python-pdm:latest + DOCKER_IMAGE_TEST: registry.forge.hefr.ch/klagarge/mse2425-grp09/python-pdm:latest + DOCKER_IMAGE_APP: registry.forge.hefr.ch/klagarge/mse2425-grp09/devsecops-app:latest default: - image: $DOCKER_IMAGE + image: $DOCKER_IMAGE_TEST stages: - - build-docker + - build-docker-test + - build-docker-app - lint - test + - dast .setup_env: &setup_env before_script: @@ -54,15 +57,15 @@ pages: - main # This job runs only when Dockerfile changes -docker-build: +docker-build-test: image: docker:latest - stage: build-docker + stage: build-docker-test services: - docker:dind script: - - docker build -t $DOCKER_IMAGE -f Dockerfile . + - docker build -t $DOCKER_IMAGE_TEST -f Dockerfile . - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY - - docker push $DOCKER_IMAGE + - docker push $DOCKER_IMAGE_TEST rules: - if: $GITLAB_CI == 'false' # Only run in GitLab CI when: never @@ -71,7 +74,26 @@ docker-build: - src/pyproject.toml - src/pdm.lock +docker-build-app: + image: docker:latest + stage: build-docker-app + services: + - docker:dind + script: + - docker build -t $DOCKER_IMAGE_APP -f src/Dockerfile . + - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY + - docker push $DOCKER_IMAGE_APP include: - template: Jobs/SAST.gitlab-ci.yml - \ No newline at end of file + +dast: + stage: dast + image: ghcr.io/zaproxy/zaproxy:stable + services: + - name: $DOCKER_IMAGE_APP + alias: app + script: + - echo "Waiting for the app to start on http://app:5000" + - timeout 60 bash -c 'until curl -s http://app:5000; do echo "Waiting..."; sleep 3; done' + - zap-full-scan.py -t http://app:5000 -I \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 17385ff..41bd0be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM python:3.10-slim -LABEL maintener="Rémi Heredero " +LABEL org.opencontainers.image.authors="remi.heredero@hevs.ch" RUN apt-get update && \ pip install --no-cache-dir -U pdm && \ diff --git a/docs/questions-part3.md b/docs/questions-part3.md index b569c4d..e830b02 100644 --- a/docs/questions-part3.md +++ b/docs/questions-part3.md @@ -2,7 +2,7 @@ ## Part 3 -- **Q3.1**: Setup your CI/CD pipeline with an additional SAST solution. I propose that you use `semgrep` for this task. Get your inspiration here: https://semgrep.dev/for/gitlab and https://docs.gitlab.com/ee/user/application_security/sast/ +- **Q3.1**: Setup your CI/CD pipeline with an additional SAST solution. I propose that you use `semgrep` for this task. Get your inspiration here: https://semgrep.dev/for/gitlab and https://docs.gitlab.com/ee/user/application_security/sast/ - **Q3.2**: Describe the found problems (alerts) in the `calculator app` (in the original code, git tag `v3.0`) - **Q3.3**: Install DAST OWASP ZAP on your host or in a Docker. Play with OWASP ZAP, analyze the calculator code - **Q3.4**: Implement a DAST solution in your pipeline. Get some inspiration here https://docs.gitlab.com/ee/user/application_security/dast/ . Describe what you have integrated in your pipeline. *Note: you must ensure that your application is running while you are testing!* @@ -14,7 +14,7 @@ ## Q3.2 -For some reasons, semgrep works locally, but not on GitLab. Here is the report when runned locally. +For some reasons, semgrep works locally, but not on GitLab. Here is the report when runned locally. ![SAST-report](figures/SAST-report.png) @@ -22,4 +22,14 @@ For some reasons, semgrep works locally, but not on GitLab. Here is the report w After performing a scan, we can see a few alerts as seen on this screenshot : -![alt text](figures/OWASP-ZAP.png) \ No newline at end of file +![alt text](figures/OWASP-ZAP.png) + +## Q3.4 +The integrate DAST in Github doesn't work on our version, we need the _Ultimate_ version of GitLab selfhosted. + +We create a new Docker image for the application. This image auto launch the flask app when the container is started. + +We used this image as a service for the DAST stage on our CI. +The stage use zaproxy to test the application. Warning do not return wailure, so the stage pass if no error is found by the OWASP ZAP. + +We don't understand why the stage fail when we try to provide the html report as artifact. So if the stage fail, we can see the error in the logs. diff --git a/src/Dockerfile b/src/Dockerfile new file mode 100644 index 0000000..d92b7c0 --- /dev/null +++ b/src/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.10-slim +LABEL org.opencontainers.image.authors="remi.heredero@hevs.ch" + +RUN apt-get update && \ + pip install --no-cache-dir -U pdm && \ + rm -rf /var/lib/apt/lists/* + + +ENV PATH="/root/.local/bin:$PATH" \ + PDM_USE_VENV=false + +WORKDIR /app + +COPY src/pyproject.toml src/pdm.lock ./ + +RUN pdm config python.use_venv false && \ + pdm install + +ENV PYTHONPATH="/app/__pypackages__/3.9/lib" \ + PATH="/app/__pypackages__/3.9/bin:$PATH" + +############################################################ +# Everything above should be imported from the test image, # +# but GitLab can't pull it, so I copy-paste the content # +############################################################ + +COPY src ./ + +ENV FLASK_RUN_HOST=0.0.0.0 + +CMD ["pdm", "run", "flask"]