# Secure System Development Lab 1
**Team Members:**
* Daniyar Cherekbashev (d.cherekbashev@innopolis.university)
* Gleb Statkevich (g.statkevich@innopolis.university)
* Daria Kalashnikova (d.kalashnikova@innopolis.university)
## Part I - Continuous Integration
### Task 1
**1. Q: What is the pipeline method of software development?**
A: The pipeline method is a software development strategy that divides the process into units - stages (build, test, deploy). They are responsible for specific aspects, and each stage takes place sequentially.
**2. Q: What tasks and problems does the CI/CD process solve?**
A: CI - Continuos Integration (mainly building and testing software artifacts), CD - Continuos Deployment (stage, at that we deploy artifacts/image to environment). The CI/CD process automates projects's code management tasks. It allows to: integrate code updates into a shared repository regularly, automatically test ensure quality (tests, security, etc.), quickly and efficiently deploy applications to production. CI/CD process minimizes manual human-factor errors, enhances teamwork, and speeds up software updates.
**3. Q: What kind of general stages are there in the CI/CD pipeline? List them in the correct sequence and then describe them.**
A: Building - build software artifacts and then scan for vulnerabilities, Testing - test newly created artifacts. After that we can push artifacts to some artifacts repo (Nexus, Artifactory, e.g.), Deploying - deploy artifacts to environment.
**4. Q: Describe the difference(s) between unit testing and coverage testing.**
A: Unit testing - test one or more software modules and focuses on individual components of code in isolation to ensure they work as expected. Often, this is a first stage of testing job in pipeline. Coverage testing usually measures proportion of source code being tested via autotests. While unit testing focuses on the correctness of individual units of code, coverage testing measures the effectiveness of the tests in covering the codebase.
**5. Q: What are Job Artifacts and Artifacts Storage?**
A: Job Artifacts - built software in pipeline workspace, a result of the CI/CD stages (compiled code, test reports, or deployment packages). Artifacts Storage - a repository that store built artifacts for future reference/use (for troubleshooting, auditing, or rollback purposes.), also used for caching build dependencies and others.
### Task 2
1. Created user for our team:

2. Application:
<span style="color: green">main.py</span>
```python=
from flask import Flask
import datetime
import pytz
app = Flask(__name__)
@app.route('/')
def display_time() -> str:
# Retrieving Innopolis (Moscow) timezone info
timezone: datetime.tzinfo = pytz.timezone('Europe/Moscow')
inno_time: str = datetime.datetime.now(timezone).strftime("%d %B, %H:%M:%S")
return f'Hello Human! Time is: {inno_time}'
if __name__ == '__main__':
app.run()
```
<span style="color: green">requirements.txt</span>
```
pytz~=2022.7
flask~=2.2.2
```
Pushed changes to remote repo after adding public ssh key to the team user:

3. Deploying a Gitlab Runner:
Internal gitlab host was retrieved with `ip r` command.

After deploying:

Docker compose file of the previous steps:
<span style="color: green">docker-compose.yml</span>
```yaml=
version: '3.5'
services:
gitlab:
image: gitlab/gitlab-ee:latest
hostname: ssd.inno.local
restart: always
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['gitlab_shell_ssh_port'] = 8022
external_url 'http://ssd.inno.local'
ports:
- "8022:22"
- "8080:80"
- "8443:443"
volumes:
- ./config/gitlab:/etc/gitlab
- ./data/gitlab:/var/opt/gitlab
- ./logs:/var/log/gitlab
networks:
gitlab:
aliases:
- 'ssd.inno.local'
gitlab-runner:
image: gitlab/gitlab-runner:alpine
restart: unless-stopped
depends_on:
- gitlab
volumes:
- ./config/gitlab-runner:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
networks:
- gitlab
networks:
gitlab:
driver: 'bridge'
```
## Part II - Continuous Deployment
### Task 3
<span style="color: green">Dockerfile</span>
```dockerfile
FROM docker.io/library/python:3.9.2 as build
COPY requirements.txt /
WORKDIR /app
RUN adduser --disabled-password puppet && chown -R puppet /app
COPY main.py ./
COPY requirements.txt ./
USER puppet
RUN python -m pip install -r /requirements.txt
EXPOSE 5000
CMD ["python", "main.py"]
```
Best practices used:
* The use of stable base image: Precise version python:3.9.2 is used to ensure consistency and avoid potential compatibility issues between different versions.
* Keeping layers immutable: Files or dependencies are not changed in the middle of the Dockerfile, as it can lead to inconsistencies and security vulnerabilities.
* Run as a non-root user: Application is run as a non-root user to minimize the potential security risks.
### Task 4
<span style="color: green">.gitlab-ci.yml</span>
```yaml=
stages:
- build
- deploy
default:
image: docker:24.0.5
services:
- docker:24.0.5-dind
before_script:
- docker info
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
build-job:
stage: build
tags:
- docker
script:
- docker build -t $DOCKERHUB_IMAGE -f Dockerfile .
- docker login -u $DOCKERHUB_USER -p $DOCKERHUB_TOKEN docker.io
- docker tag $DOCKERHUB_IMAGE:latest $DOCKERHUB_USER/$DOCKERHUB_IMAGE:latest
- docker push $DOCKERHUB_USER/$DOCKERHUB_IMAGE:latest
deploy-job:
image: ubuntu:latest
stage: deploy
tags:
- default
only:
- master
before_script:
- apt-get -yq update
- apt-get -yqq install ssh
- install -m 600 -D /dev/null ~/.ssh/id_rsa
- echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
- ssh-keyscan -H $SSH_HOST > ~/.ssh/known_hosts
script:
- ssh $SSH_USER@$SSH_HOST "docker run -d -p 5000:5000 $DOCKERHUB_USER/$DOCKERHUB_IMAGE:latest"
```
To make runner work and correctly resolve hosts, we should add `network_mode = "srv_gitlab"` (network name can be found with `docker network ls`) to the `/etc/gitlab-runner/config.toml` of our runner in `gitlab-runner` container. We should also add `privileged = true` to correctly run docker-in-docker container.
```toml
[[runners]]
...
[runners.docker]
privileged = true
...
network_mode = "srv_gitlab"
```
Also, we should create CI/CD variables for our CI file:

Passed jobs:


