From 7da76417f7dcf1efbf10d02706428dd0c1231f32 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 13 Apr 2025 16:20:04 +0200 Subject: [PATCH 1/4] feat(ci): add DAST job configuration to GitLab CI Signed-off-by: Klagarge --- .gitlab-ci.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cebdc00..7d1c551 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,6 +8,7 @@ stages: - build-docker - lint - test + - dast job .setup_env: &setup_env before_script: @@ -74,4 +75,10 @@ docker-build: include: - template: Jobs/SAST.gitlab-ci.yml - \ No newline at end of file + - template: DAST.gitlab-ci.yml + +dast: + stage: dast job + dast_configuration: + site_profile: "dast-site-profile-devsecops-mse" + scanner_profile: "dast-scanner-profile-devsecops-mse" From c308ffd2dd362743ca3f529badd1f59f498258fe Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 13 Apr 2025 17:13:46 +0200 Subject: [PATCH 2/4] feat(ci): add Dockerfile and update CI configuration for DAST Signed-off-by: Klagarge --- .gitlab-ci.yml | 56 +++++++++++++++++++++++++++++++++++++------------- src/Dockerfile | 31 ++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 src/Dockerfile diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7d1c551..159ace1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,14 +1,18 @@ 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 + APP_PORT: 5000 + TARGET_URL: "http://app:${APP_PORT}" default: - image: $DOCKER_IMAGE + image: $DOCKER_IMAGE_TEST stages: - - build-docker + - build-docker-test + - build-docker-app - lint - test - - dast job + - dast .setup_env: &setup_env before_script: @@ -55,15 +59,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 @@ -72,13 +76,37 @@ 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 - - template: DAST.gitlab-ci.yml +# - template: DAST.gitlab-ci.yml -dast: - stage: dast job - dast_configuration: - site_profile: "dast-site-profile-devsecops-mse" - scanner_profile: "dast-scanner-profile-devsecops-mse" +#dast-ci: +# stage: dast +# dast_configuration: +# site_profile: "dast-site-profile-devsecops-mse" +# scanner_profile: "dast-scanner-profile-devsecops-mse" +#services: +# - name: $DOCKER_IMAGE_APP +# alias: app + +dast-local: + 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 + allow_failure: true # Allow failure for DAST job (because GitLab is not well configured and network didn't work) \ No newline at end of file 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"] From b170eecb16a68e6852e7233539c4efcf47140313 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 14 Apr 2025 12:41:18 +0200 Subject: [PATCH 3/4] fix: label of docker image Signed-off-by: Klagarge --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 && \ From 355865586f3290a2c1ea78ca331592deab0a6e09 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 14 Apr 2025 12:58:46 +0200 Subject: [PATCH 4/4] refactor: removed unused code docs: added answer for Q3.4 Signed-off-by: Klagarge --- .gitlab-ci.yml | 17 ++--------------- docs/questions-part3.md | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 159ace1..b0acd34 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,6 @@ variables: 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 - APP_PORT: 5000 - TARGET_URL: "http://app:${APP_PORT}" default: image: $DOCKER_IMAGE_TEST @@ -88,18 +86,8 @@ docker-build-app: include: - template: Jobs/SAST.gitlab-ci.yml -# - template: DAST.gitlab-ci.yml -#dast-ci: -# stage: dast -# dast_configuration: -# site_profile: "dast-site-profile-devsecops-mse" -# scanner_profile: "dast-scanner-profile-devsecops-mse" -#services: -# - name: $DOCKER_IMAGE_APP -# alias: app - -dast-local: +dast: stage: dast image: ghcr.io/zaproxy/zaproxy:stable services: @@ -108,5 +96,4 @@ dast-local: 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 - allow_failure: true # Allow failure for DAST job (because GitLab is not well configured and network didn't work) \ No newline at end of file + - zap-full-scan.py -t http://app:5000 -I \ No newline at end of file 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.