áá±áž áá¬á!
áá±ááºáá áºáááºááœá±á·ááœááºá ááœá¶á·ááŒáá¯ážááá¯ážáááºááŸá¯áá¯ááºáááºážá ááºáá»á¬ážááœáẠááœááºááááºáá¬ááŒá¯áá¯ááºááŒááºážáá¡áááºážááá¹á ááŒá®ážááœá¬ážáá¬ááŒááºážááŒá±á¬áá·áºá ááœááºááááºáá¬ááŸáá·áºáááºá ááºáá±á¬ á¡ááá·áºá¡áá»áá¯ážáá»áá¯ážááŸáá·áº áááºá ááºáá á¹á ááºážáá»á¬ážááá¯á¶ááŒá¯á¶áá±ážááᯠáá±áá»á¬á á±áá±ážááá á¹á ááẠá¡áá±ážá¡ááŒá®ážáá¯á¶ážááŒá¿áá¬ááá¯ááºáá±á ááá¯ááºááá¯ááºá á áºáá±ážááŸá¯áá»á¬ážáá¯ááºáá±á¬ááºááŒááºážááẠá¡áá»áááºáá¯ááºáá±á¬ááŒá±á¬áá·áº á€áá¯ááºáááºážá ááºááᯠá¡ááá¯á¡áá»á±á¬ááºááŒá áºá á±áááºá¡ááœáẠá¡áááºážáá¯á¶áž áááŠážááŒá±ááŸááºážáá»á¬ážááᯠáá¯ááºáá±á¬ááºááẠá¡ááŒá¶áá¬ááºáá±á¬ááºážáá áºáá¯ááŒá áºáááºá
á€áá±á¬ááºážáá«ážááœááºá á€áá¯ááºáááºážá
ááºááá¯á
ááºážáááºáááºá¡ááœáẠDocker áá¯á¶ááŒá¯á¶áá±áž utilities á¡áá»á¬ážá¡ááŒá¬ážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºáááºá¡ááœáẠá¡áááºááá·áºáá¯ááºáá¬ážáá±á¬ scripts áá»á¬ážááŸáá·áº á€áá¯ááºáááºážá
ááºááá¯á
ááºážáááºáááºá¡ááœáẠdemo stand á¡áá±ážáá
áºáá¯ááᯠáááºááá¯á·á¡áá¯á¶ážáá»ááááºááᯠáá»áŸáá±áá«áááºá Dockerfile áá¯ááºáá¯á¶áá»á¬ážááŸáá·áº ááœáŸááºááŒá¬ážáá»ááºáá»á¬ážá áá¯á¶ááŒá¯á¶áá±ážááᯠá
ááºážáááºááá·áº áá¯ááºáááºážá
ááºááᯠáááºááá¯á·á
á®á
ááºááááºááᯠá
ááºážáááºááẠáá
á¹á
ááºážáá»á¬ážá¡á¬áž áááºá¡áá¯á¶ážááŒá¯ááá¯ááºáá«áááºá áá°ááá¯ááºážá ááœá¶á·ááŒáá¯ážááá¯ážáááºááŸá¯ááŸáá·áº á¡áá±á¬ááºá¡áááºáá±á¬áºááŸá¯ááá¯ááºáᬠá¡ááŒá±áá¶á¡áá±á¬ááºá¡á¡á¯á¶áá»á¬áž ááá°áá®ááŒá±á¬ááºáž ááŸááºážááŸááºážáááºážáááºáž áááá¬áááºááŸá¬ážááŸáááºá ááá¯á·ááŒá±á¬áá·áº á¡á±á¬ááºááœáẠááŒá
áºááá¯ááºááŒá±ááŸááá±á¬ ááœá±ážáá»ááºá
áá¬áá»á¬ážá
áœá¬ááᯠáá±á¬áºááŒáá±ážáá«áááºá
áá¯á¶ááŒá¯á¶áá±ážá á áºáá±ážááŸá¯áá»á¬áž
Docker á¡ááŒá±áá¶á¡áá±á¬ááºá¡á¡á¯á¶á ááŸá¯áá±á¬áá·áºá¡áá»áá¯ážáá»áá¯ážááᯠá
á
áºáá±ážááŸá¯áá»á¬ážááŒá¯áá¯ááºááá·áº ááœá²ááŒá¬ážááŒá¬ážáá¬ážáá±á¬ á¡áá°á¡áá®áá±ážááá·áºá¡ááºááºáá®áá±ážááŸááºážáá»á¬ážááŸáá·áº script á¡áá»á¬ážá¡ááŒá¬ážááŸááááºá áááºážááá¯á·áá²á០á¡áá»áá¯á·ááᯠááááºáá±á¬ááºážáá«ážááœáẠáá±á¬áºááŒáá²á·ááŒá®ážááŒá
áºááẠ(
Hadolint
áááá¡áá®ážá ááºáá¯á¶ážá¡áá±ááŒáá·áº Dockerfile áááºážááœáŸááºáá»ááºáá»á¬ážá ááŸááºáááºááŸá¯ááŸáá·áº áá±ážáááºážááŸá¯ááᯠá¡áá²ááŒááºááẠáá°áá®áá±ážááá·áº ááá¯ážááŸááºážáá±á¬ ááœááºááá¯ážáẠá¡áá¯á¶ážáááºááŸá¯áá áºáᯠ(á¥ááá¬á ááœáá·áºááŒá¯áá»ááºááá¬ážáá±á¬ áá¯ááºáá¯á¶á á¬áááºážááœááºážááŒááºážáá»á¬ážááá¯áᬠá¡áá¯á¶ážááŒá¯ááŒááºáž ááá¯á·ááá¯áẠsudo á¡áá¯á¶ážááŒá¯ááŒááºáž)á
á¡ááá¯ááº
áá¯á¶áá
áºáá¯á¶ (ááá¯á·ááá¯áẠáá¯á¶áá
áºáá¯á ááááºážáááºážáá¬ážáá±á¬ ááá¹ááá¬á
á±ážááŸááºáááºážááŸáá·áºá¡áá°) á¡áá¯ááºáá¯ááºáá±á¬ ááœááºááá¯ážááºá¡áá¯á¶ážá¡áá±á¬ááºáá
áºáá¯ááŒá
áºááá·áº áá¯á¶áá
áºáá¯á¶á ááŸááºáááºááŸá¯ááŸáá·áº áá¯á¶ááŒá¯á¶áá±ážááᯠá
á
áºáá±ážáá±ážááá·áº á¡ááœáŸá¬áá»á¬ážááŸáá·áº áá¯á¶á
á¶ááœá²á·á
ááºážáá¯á¶ááᯠááá¯ááºážááŒá¬ážá
áááºááŒá¬ááŒááºáž- á¡áá¯á¶ážááŒá¯áá°áá»á¬áž áááºáá®ážáá¬ážááá·áº ááœáŸááºááŒá¬ážáá»ááºáá»á¬ážááᯠá¡áá¯á¶ážááŒá¯áá¬ážááá·áºá ááá¬ááá»á¬ážááᯠáááºáááºáá¬ážáááºá á¡ááœááºá
áá¬ážááŸááºáá
áºáᯠááŸááá±ááŒááºáž á
áááºááŒáá·áº áá ááá¯á¡áá»áááºá¡áá á
á
áºáá±ážááŸá¯á¡áá±á¡ááœááºááẠá¡ááœááºáááŒá®ážáá±ážáá² áá»áœááºá¯ááºááá¯á·á ááá¯ááºááá¯ááºá
á
áºáá±ážááŸá¯áá»á¬ážááŸáá·áº á¡ááŒá¶ááŒá¯áá»ááºáá»á¬ážá
áœá¬á¡áá±á«áº á¡ááŒá±áá¶áá¬ážáááºá
áá¬ááºá
ááºáž
á€á¡áá¯á¶ážá¡áá±á¬ááºááẠá¡á¬ážáááºážáá»ááºááŸá áºáá»áá¯ážááᯠááŸá¬ááœá±ááẠáááºááœááºááẠ- OS áááºáá±á¬ááºááŸá¯ááá¯ááºáᬠááŒá¿áá¬áá»á¬áž (Alpineá RedHat (EL)á CentOSá Debian GNUá Ubuntu) ááŸáá·áº ááŸá®ááá¯ááŸá¯ááá¯ááºáᬠááŒá¿áá¬áá»á¬áž (Gemfile.locká Pipfile.locká composer.locká package -lock.jsoná yarn.locká cargo.lock)á Trivy ááẠrepository ááŸá áá¯á¶áá áºáá¯á¶ááŸáá·áº local image ááŸá áºáá¯áá¯á¶ážááᯠá áááºááºáááºááá¯ááºááŒá®áž Docker áá¯á¶ááŒáá·áº ááœáŸá²ááŒá±á¬ááºážáá¬ážáá±á¬ .tar ááá¯ááºááᯠá¡ááŒá±áá¶á á áááºááºáááºááá¯ááºáááºá
á¡áá¯á¶ážá¡áá±á¬ááºáá»á¬ážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááẠááœá±ážáá»ááºááŸá¯áá»á¬áž
áá®ážááŒá¬ážáááºáááºážáá»ááºááœáẠáá±á¬áºááŒáá¬ážáá±á¬ á¡ááá®áá±ážááŸááºážáá»á¬ážááᯠá ááºážáá¯á¶ážááŒáá·áºáááºá¡ááœáẠá¡áááºážáááºááá¯ážááŸááºážáá±á¬ áá¯ááºáááºážá ááºááœáẠutilities á¡á¬ážáá¯á¶ážááᯠááá·áºááœááºážááŒááºážá¡ááœáẠááœáŸááºááŒá¬ážáá»ááºáá»á¬ážááᯠáá»áœááºá¯ááºáá±ážáá«áááºá
á¡ááá á¡áá¯ááºáá®áá¬ááŸá¬ ááœá¶á·ááŒáá¯ážááá¯ážáááºááŸá¯á¡ááœááºáž áááºáá®ážáá¬ážááá·áº Dockerfiles ááŸáá·áº Docker áá¯á¶áá»á¬ážá á¡ááá¯á¡áá»á±á¬áẠá¡ááŒá±á¬ááºážá¡áᬠá¡áááºááŒá¯ááŒááºážá¡á¬áž áááºáááºáá²á·ááá¯á· á¡áá±á¬ááºá¡ááẠáá±á¬áºááá¯ááºáááºááᯠááá¯ááºááŒááẠááŒá áºáááºá
á á áºáá±ážáá»ááºááœáẠá¡á±á¬ááºáá«á¡ááá·áºáá»á¬áž áá«áááºáá«áááºá
- linter utility ááᯠá¡áá¯á¶ážááŒá¯á Dockerfile ááœáŸááºááŒá¬ážáá»ááºáá»á¬ážá ááŸááºáááºááŸá¯ááŸáá·áº áá±ážáááºážááŸá¯ááᯠá á áºáá±ážááŒááºážá Hadolint
- utility ááᯠá¡áá¯á¶ážááŒá¯á áá±á¬ááºáá¯á¶ážááŸáá·áº á¡áááºá¡áááºáá¯á¶áá»á¬ážá ááŸááºáááºááŸá¯ááŸáá·áº áá±ážáááºážááŸá¯ááᯠá á áºáá±ážááŒááºážá á¡ááá¯ááº
- á¡ááŒá±áá¶áá¯á¶ááœáẠáá°ááááŸááºááŒá¬ážááááá¯ááºáá±á¬ á¡á¬ážáááºážáá»ááºáá»á¬áž (CVE) ááŸáá·áº ááŸá®ááá¯ááŸá¯áá»á¬ážá áœá¬ááᯠá á áºáá±ážááŒááºáž - utility ááᯠá¡áá¯á¶ážááŒá¯á áá¬ááºá ááºáž
áá±á¬ááºááá¯ááºážááœáẠá€á¡ááá·áºáá»á¬ážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºáááºá¡ááœáẠááœá±ážáá»ááºá
áá¬áá¯á¶ážáá¯ááᯠáá±á¬ááºážáá«ážááœáẠáá±á¬áºááŒáá±ážáá«áááºá
áááá¡áá»ááºááŸá¬ GitLab ááᯠá¡áá¯á¶ážááŒá¯á CI/CD ááá¯ááºááá¯ááºážááᯠá
á¶ááá°áá¬á¡ááŒá
ẠáááºááŸááºááŒááºáž (á
ááºážáááºááŸá¯áá
áºáᯠááŒá¯áá¯ááºááŒááºáž áá¯ááºáááºážá
ááºá áá±á¬áºááŒáá»ááºááŸáá·áºá¡áá°)á
áá¯ááááá
áºáá¯ááá±á¬á· shell script ááá¯áá¯á¶ážáá«áááºá
áááááá
áºáá¯ááŸá¬ Docker áá¯á¶áá»á¬ážááá¯á
áááºááºáááºááẠDocker áá¯á¶áá
áºáá¯áááºáá±á¬ááºááŒááºážáá«áááºáááºá
ááá·áºá¡ááœáẠá¡ááá·áºáá±á¬áºáá¯á¶áž ááœá±ážáá»ááºááŸá¯ááᯠáááºááœá±ážáá»ááºááá¯ááºááŒá®áž áááºážááᯠáááºáá¡ááŒá±áá¶á¡áá±á¬ááºá¡á¡á¯á¶ááá¯á· ááœáŸá²ááŒá±á¬ááºážááŒá®áž ááá·áºááá¯á¡ááºáá»ááºáá»á¬ážááŸáá·áº ááá¯ááºáá»á±á¬áá®ááœá±ááŒá
áºá¡á±á¬áẠááŒá¯áá¯ááºááá¯ááºáááºá
ááá¯á¡ááºáá±á¬ ááá¯ááºáá»á¬ážááŸáá·áº áááºáá±á¬ááºážááœáŸááºááŒá¬ážáá»ááºáá»á¬ážá¡á¬ážáá¯á¶ážááᯠááá¯ááŸá±á¬ááºáá¯á¶ááœáẠáááºááŸááááº-
GitLab CI/CD ááœáẠáá±á«ááºážá ááºááŒááºážá
áááááœá±ážáá»ááºááŸá¯ááœááºá á¥ááá¬áá áºáá¯á¡áá±ááŒáá·áº GitLab repository system ááá¯á¡áá¯á¶ážááŒá¯á áá¯á¶ááŒá¯á¶áá±ážá á áºáá±ážááŸá¯áá»á¬ážááᯠáááºáááºáá²á·ááá¯á·á¡áá±á¬ááºá¡áááºáá±á¬áºááá¯ááºáááºááᯠááŒáá·áºááŸá¯áá«áááºá á€ááœáẠáá»áœááºá¯ááºááá¯á·ááẠá¡ááá·áºáá»á¬ážááá¯ááŒááºáááºážááŒá®áž GitLab ááŒáá·áº á ááºážáááºááŸá¯áááºáááºážáá»ááºááᯠá¡á ááŸá¡áá¯á¶áž áááºááá¯á·ááá·áºááœááºážááááºááᯠááœááºáááŒá®ážá á áááºááºáááºááŒááºážáá¯ááºáááºážá ááºááá¯áááºáá®ážáᬠá ááºážáááºááŸá¯ Dockerfile ááŸáá·áº áá»áááºážáá¯á¶- JuiceShop á¡ááá®áá±ážááŸááºážááá¯á á áºáá±ážáááºá¡ááœáẠá áááºáá¯ááºáá±á¬ááºáááá·áº á¡áá¯á¶ážáááºááŸá¯áá»á¬ážá
GitLab ááᯠááá·áºááœááºážááŒááºážá
1. Docker ááᯠááá·áºááœááºážáá«-
sudo apt-get update && sudo apt-get install docker.io
2. sudo ááá¯á¡áá¯á¶ážáááŒá¯áá² docker ááŸáá·áºá¡áá¯ááºáá¯ááºááá¯ááºá á±ááẠáááºááŸáá¡áá¯á¶ážááŒá¯áá°ááᯠdocker á¡á¯ááºá á¯ááá¯á·ááá·áºáá«-
sudo addgroup <username> docker
3. áááºá IP ááᯠââááŸá¬áá«-
ip addr
4. GitLab ááᯠááœááºááááºáá¬ááœáẠááá·áºááœááºážááŒá®áž á áááºá¡áá¯á¶ážááŒá¯áᬠhostname ááŸá IP ááááºá á¬ááᯠááá·áºááá¯ááºááá¯ááºááŒáá·áº á¡á á¬ážááá¯ážáá«-
docker run --detach
--hostname 192.168.1.112
--publish 443:443 --publish 80:80
--name gitlab
--restart always
--volume /srv/gitlab/config:/etc/gitlab
--volume /srv/gitlab/logs:/var/log/gitlab
--volume /srv/gitlab/data:/var/opt/gitlab
gitlab/gitlab-ce:latest
GitLab ááẠááá¯á¡ááºáá±á¬ áááºáááºááŸá¯áá¯ááºáááºážá ááºáá»á¬ážá¡á¬ážáá¯á¶ážááᯠááŒá®ážááŒá±á¬ááºáááºá¡áá áá»áœááºá¯ááºááá¯á· á á±á¬áá·áºáá»áŸá±á¬áºáá±áá«ááẠ(ááŸááºáááºážááá¯ááºá¡ááœááºááŸáá áºááá·áº áá¯ááºáááºážá ááºááᯠá á±á¬áá·áºááŒáá·áºááá¯ááºáááº- docker logs -f gitlab)á
5. áááºááá±ááᶠIP ááᯠââááá±á¬ááºáá¬ááœááºááœáá·áºááŒá®áž á¡ááŒá
áºá¡áá¯á¶ážááŒá¯áá°á¡ááœáẠá
áá¬ážááŸááºááᯠááŒá±á¬ááºážáá²ááẠáá±á¬ááºážááá¯áá±á¬ á
á¬áá»ááºááŸá¬ááá¯ááŒáá·áºáá«-
á
áá¬ážááŸááºá¡áá
áºáá
áºáá¯áááºááŸááºááŒá®áž GitLab ááá¯á·ááœá¬ážáá«á
6. ááá±á¬áá»ááºá¡áá
áºáá
áºáᯠáááºáá®ážáá«á á¥ááᬠcicd-test ááŸáá·áº start file ááŒáá·áº á¡á
ááŒá¯áá«á README.md:
7. ááᯠáá»áœááºá¯ááºááá¯á·ááẠGitLab Runner ááᯠáááºáááºááẠááá¯á¡ááºáááº- áá±á¬ááºážááá¯ááŸá¯á¡á ááá¯á¡ááºáá±á¬ áá¯ááºáá±á¬ááºááŸá¯áá»á¬ážá¡á¬ážáá¯á¶ážááᯠáá¯ááºáá±á¬ááºáá±ážááá·áº á¡á±ážáá»áá·áºáá
áºáá¯ááŒá
áºáááºá
áá±á¬ááºáá¯á¶ážáá¬ážááŸááºážááᯠáá±á«ááºážáá¯ááºáá¯ááºáá« (á€ááá
á¹á
ááœááºá Linux 64-bit á¡ááœááº)
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
8. áááºážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááá¯ááºá á±áááº-
sudo chmod +x /usr/local/bin/gitlab-runner
9. Runner á¡ááœáẠOS á¡áá¯á¶ážááŒá¯áá°áá áºáŠážááᯠáá±á«ááºážááá·áºáᬠáááºáá±á¬ááºááŸá¯ááᯠá áááºáá«-
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
áááºážáááºá€áá²á·ááá¯á·áá±á¬áá¯á¶ááá¹áá¬ááºááŸáááá·áºáááº-
local@osboxes:~$ sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
Runtime platform arch=amd64 os=linux pid=8438 revision=0e5417a3 version=12.0.1
local@osboxes:~$ sudo gitlab-runner start
Runtime platform arch=amd64 os=linux pid=8518 revision=0e5417a3 version=12.0.1
10. ááᯠáá»áœááºá¯ááºááá¯á·ááẠáá»áœááºá¯ááºááá¯á·á GitLab á
á¶ááá°áá¬ááŸáá·áº á¡ááŒááºá¡ááŸááºá¡áá»áá¯ážáááºáá±á¬ááºááá¯ááºá
á±ááẠRunner ááᯠááŸááºáá¯á¶áááºááá¯ááºáá«á
áá«ááá¯áá¯ááºááá¯á·á Settings-CI/CD á
á¬áá»ááºááŸá¬ (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) ááá¯ááœáá·áºááŒá®áž Runners tab áá±á«áºááŸá¬ URL áá²á· Registration token ááá¯ááŸá¬áá«á
11. URL ááŸáá·áº ááŸááºáá¯á¶áááºááŒááºážááá¯áááºááᯠá¡á
á¬ážááá¯ážááŒááºážááŒáá·áº Runner ááᯠááŸááºáá¯á¶áááºáá«-
sudo gitlab-runner register
--non-interactive
--url "http://<URL>/"
--registration-token "<Registration Token>"
--executor "docker"
--docker-privileged
--docker-image alpine:latest
--description "docker-runner"
--tag-list "docker,privileged"
--run-untagged="true"
--locked="false"
--access-level="not_protected"
ááááºá¡áá±ááŒáá·áºá áá»áœááºá¯ááºááá¯á·ááẠáá»áœááºá¯ááºááá¯á·á utilities ááá¯á áááºááẠááœáŸááºááŒá¬ážáá»ááºáá»á¬ážááá·áºááẠááá¯á¡ááºááá·áº á¡áááºááá·áºáá¯ááºáá¬ážáá±á¬ GitLab ááá¯áááŸááá¬ážáá«áááºá á€ááá¯ááºááŒááœáẠáá»áœááºá¯ááºááá¯á·ááœáẠá¡ááá®áá±ážááŸááºážááá¯áááºáá±á¬ááºááŒá®áž ááááºážáááºážááẠá¡ááá·áºáá»á¬ážáááŸááá±á¬áºáááºáž áááá·áºáááºáááºážáá»ááºááœáẠáááºážááá¯á·ááẠá áááºáááºá á áºáá±ážááŒááºážá¡ááá·áºáá»á¬ážááẠáá»á±á¬áºááœááºááœá¬ážáᬠááœá²ááŒááºážá áááºááŒá¬áááºá¡ááœáẠáá¯á¶áá»á¬ážááŸáá·áº Dockerfile áá áºáá¯ááᯠáá¯ááºáá±ážáááºááŒá áºáááºá
ááá¯ááºááá¯ááºážááœá²á·á ááºážááŸá¯
1. ááá¯ááŸá±á¬ááºááŸá¯ááá¯á· ááá¯ááºáá»á¬ážááá·áºáá«á mydockerfile.df (áá«á á ááºážáááºá á áºáá±ážááá·áº Dockerfile) áá²á· GitLab CI/CD áá¯ááºáááºážá ááºááœá²á·á ááºážáá¯á¶ááá¯áẠ.gitlab-cicd.ymlá áááºáá¬áá»á¬ážá¡ááœáẠááœáŸááºááŒá¬ážáá»ááºáá»á¬ážááᯠá á¬áááºážááŒá¯á á¯ááẠ(ááá¯ááºá¡áááºááœáẠá¡á ááºááᯠááŸááºáá¬ážáá«)á
YAML ááœá²á·á
ááºážááŸá¯áá¯á¶á
á¶ááá¯ááºááœáẠááœá±ážáá»ááºáá¬ážáá±á¬ Dockerfile ááŸáá·áº DOCKERFILE ááœá²ááœá²áá»ááºááœááºáá±á¬áºááŒáá¬ážáá±á¬áá¯á¶ááá¯á·ááᯠááá¯ááºážááŒá¬ážá
áááºááŒá¬áá±ážááá·áº utilities áá¯á¶ážáᯠ(Hadolintá Dockle ááŸáá·áº Trivy) ááᯠrun ááẠáááºážááœáŸááºáá»ááºáá»á¬ážáá«ááŸááááºá ááá¯á¡ááºáá±á¬ááá¯ááºá¡á¬ážáá¯á¶ážááᯠrepository ááŸáá°ááá¯ááºáááº-
á០áá°ážáá°áá±á¬áºááŒáá«áááºá mydockerfile.df (á€ááẠutility ááááºáááºááŸá¯ááá¯ááŒááááºáá¬áááºáááá¯ááœáŸááºááŒá¬ážáá»ááºáá»á¬ážáá«ááŸááá±á¬ abstract ááá¯ááºáá
áºáá¯ááŒá
áºáááºá) ááá¯ááºááá¯á· ááá¯ááºááá¯ááºááá·áºááº-
mydockerfile.df á á¡ááŒá±á¬ááºážá¡áá¬áá»á¬áž
FROM amd64/node:10.16.0-alpine@sha256:f59303fb3248e5d992586c76cc83e1d3700f641cbcd7c0067bc7ad5bb2e5b489 AS tsbuild
COPY package.json .
COPY yarn.lock .
RUN yarn install
COPY lib lib
COPY tsconfig.json tsconfig.json
COPY tsconfig.app.json tsconfig.app.json
RUN yarn build
FROM amd64/ubuntu:18.04@sha256:eb70667a801686f914408558660da753cde27192cd036148e58258819b927395
LABEL maintainer="Rhys Arkins <[email protected]>"
LABEL name="renovate"
...
COPY php.ini /usr/local/etc/php/php.ini
RUN cp -a /tmp/piik/* /var/www/html/
RUN rm -rf /tmp/piwik
RUN chown -R www-data /var/www/html
ADD piwik-cli-setup /piwik-cli-setup
ADD reset.php /var/www/html/
## ENTRYPOINT ##
ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
USER root
ááœá²á·á
ááºážááŸá¯ YAML ááẠá€áá²á·ááá¯á· ááŒá
áºááẠ(ááá¯ááºááá¯ááºááá¯ááºá á€áá±áá¬ááœáẠááá¯ááºááá¯ááºááá·áºááºááŸáá
áºááá·áº ááœá±á·ááá¯ááºáááº-
.gitlab-ci.yml á á¡ááŒá±á¬ááºážá¡áá¬áá»á¬áž
variables:
DOCKER_HOST: "tcp://docker:2375/"
DOCKERFILE: "mydockerfile.df" # name of the Dockerfile to analyse
DOCKERIMAGE: "bkimminich/juice-shop" # name of the Docker image to analyse
# DOCKERIMAGE: "knqyf263/cve-2018-11235" # test Docker image with several CRITICAL CVE
SHOWSTOPPER_PRIORITY: "CRITICAL" # what level of criticality will fail Trivy job
TRIVYCACHE: "$CI_PROJECT_DIR/.cache" # where to cache Trivy database of vulnerabilities for faster reuse
ARTIFACT_FOLDER: "$CI_PROJECT_DIR"
services:
- docker:dind # to be able to build docker images inside the Runner
stages:
- scan
- report
- publish
HadoLint:
# Basic lint analysis of Dockerfile instructions
stage: scan
image: docker:git
after_script:
- cat $ARTIFACT_FOLDER/hadolint_results.json
script:
- export VERSION=$(wget -q -O - https://api.github.com/repos/hadolint/hadolint/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/1/')
- wget https://github.com/hadolint/hadolint/releases/download/v${VERSION}/hadolint-Linux-x86_64 && chmod +x hadolint-Linux-x86_64
# NB: hadolint will always exit with 0 exit code
- ./hadolint-Linux-x86_64 -f json $DOCKERFILE > $ARTIFACT_FOLDER/hadolint_results.json || exit 0
artifacts:
when: always # return artifacts even after job failure
paths:
- $ARTIFACT_FOLDER/hadolint_results.json
Dockle:
# Analysing best practices about docker image (users permissions, instructions followed when image was built, etc.)
stage: scan
image: docker:git
after_script:
- cat $ARTIFACT_FOLDER/dockle_results.json
script:
- export VERSION=$(wget -q -O - https://api.github.com/repos/goodwithtech/dockle/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/1/')
- wget https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.tar.gz && tar zxf dockle_${VERSION}_Linux-64bit.tar.gz
- ./dockle --exit-code 1 -f json --output $ARTIFACT_FOLDER/dockle_results.json $DOCKERIMAGE
artifacts:
when: always # return artifacts even after job failure
paths:
- $ARTIFACT_FOLDER/dockle_results.json
Trivy:
# Analysing docker image and package dependencies against several CVE bases
stage: scan
image: docker:git
script:
# getting the latest Trivy
- apk add rpm
- export VERSION=$(wget -q -O - https://api.github.com/repos/knqyf263/trivy/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/1/')
- wget https://github.com/knqyf263/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz && tar zxf trivy_${VERSION}_Linux-64bit.tar.gz
# displaying all vulnerabilities w/o failing the build
- ./trivy -d --cache-dir $TRIVYCACHE -f json -o $ARTIFACT_FOLDER/trivy_results.json --exit-code 0 $DOCKERIMAGE
# write vulnerabilities info to stdout in human readable format (reading pure json is not fun, eh?). You can remove this if you don't need this.
- ./trivy -d --cache-dir $TRIVYCACHE --exit-code 0 $DOCKERIMAGE
# failing the build if the SHOWSTOPPER priority is found
- ./trivy -d --cache-dir $TRIVYCACHE --exit-code 1 --severity $SHOWSTOPPER_PRIORITY --quiet $DOCKERIMAGE
artifacts:
when: always # return artifacts even after job failure
paths:
- $ARTIFACT_FOLDER/trivy_results.json
cache:
paths:
- .cache
Report:
# combining tools outputs into one HTML
stage: report
when: always
image: python:3.5
script:
- mkdir json
- cp $ARTIFACT_FOLDER/*.json ./json/
- pip install json2html
- wget https://raw.githubusercontent.com/shad0wrunner/docker_cicd/master/convert_json_results.py
- python ./convert_json_results.py
artifacts:
paths:
- results.html
ááá¯á¡ááºáá«á áááºááẠ.tar archive áá¯á¶á á¶ááŒáá·áº ááááºážáááºážáá¬ážáá±á¬ áá¯á¶áá»á¬ážááᯠá áááºááºáááºááá¯ááºááẠ(ááá¯á·áá±á¬áº YAML ááá¯ááºááŸá utilities á¡ááœáẠinput parameters áá»á¬ážááᯠááŒá±á¬ááºážáá²ááẠááá¯á¡ááºáá«áááº)
NB- áá¬ááºá ááºážáá« ááá·áºááœááºážááẠááá¯á¡ááºáááºá rpm á᫠О git. ááá¯ááºáá«áá RedHat-based áá¯á¶áá»á¬ážááá¯á áááºááºáááºááŒá®áž á¡á¬ážáááºážáá»ááºáá±áá¬áá±á·á áºááá¯á· á¡ááºááááºáá»á¬ážáááºáá¶áá±á¬á¡áá«ááœáẠá¡ááŸá¬ážá¡ááœááºážáá»á¬ážááŒá áºáá±á«áºáá¬áááá·áºáááºá
2. repository ááœáẠááá¯ááºáá»á¬ážááᯠáá±á«ááºážááá·áºááŒá®ážáá±á¬ááºá áá»áœááºá¯ááºááá¯á·á configuration file ááŸá áááºážááœáŸááºáá»ááºáá»á¬ážá¡áá GitLab ááẠáááºáá±á¬ááºááŒááºážááŸáá·áº á áááºáááºááŒááºáž áá¯ááºáááºážá ááºááᯠá¡ááá¯á¡áá»á±á¬áẠá áááºáááºááŒá áºáá«áááºá CI/CD â ááá¯ááºááá¯ááºážáá»á¬áž áááºááºááœáẠááœáŸááºááŒá¬ážáá»ááºáá»á¬ážá ááá¯ážáááºááŸá¯ááᯠáááºááœá±á·ááŒááºááá¯ááºáá«áááºá
ááá¯á·ááŒá±á¬áá·áº áá»áœááºá¯ááºááá¯á·ááœáẠá¡áá¯ááºáá±ážáá¯ááŸááááºá áááºážááá¯á·áá²á០áá¯á¶ážáŠážááẠá
áááºáááºááŒááºážááœáẠááá¯ááºááá¯ááºáá¯ááºáá±á¬ááºááŒááŒá®áž áá±á¬ááºáá¯á¶ážáá
áºáᯠ(á¡á
á®áááºáá¶á
á¬) ááẠááŒáá·áºáá»á²áá±áá±á¬ ááá¯ááºáá»á¬ážá០ááá¯ážááŸááºážáá±á¬ á¡á
á®áááºáá¶á
á¬ááᯠá
áááºáááºááŒááºážááááºáá»á¬ážááŒáá·áº á
á¯áá±á¬ááºážáá«áááºá
áá¯á¶ááá¹áá¬áẠááá¯á·ááá¯áẠááŸá®ááá¯ááŸá¯ááœáẠá¡áá±ážááŒá®ážáá±á¬ á¡á¬ážáááºážáá»ááºáá»á¬ážááᯠááœá±á·ááŸááá«á Trivy ááẠáááºáááºááŸá¯ááᯠáááºááœá¬ážáá«áááºá áá
áºáá»áááºáááºážááŸá¬áááºá Hadolint ááẠáááºáá±á¬ááºááŸá¯ááᯠáááºááá·áºááœá¬ážá
á±ááá·áº ááŸááºáá»ááºáá»á¬ážááœáẠá¡ááŒá²ááááºááœááºáá±á«áºáá±áá±á¬ááŒá±á¬áá·áº á¡á±á¬ááºááŒááºááŸá¯áá¯ááºááᯠá¡ááŒá²ááŒááºáá±ážáá«áááºá
áááºá áá®ážááŒá¬ážááá¯á¡ááºáá»ááºáá»á¬ážá¡áá±á«áºáá°áááºá ဠutilities áá»á¬ážááẠá¡áá»áá¯á·áá±á¬ áá±áááºááá¯ááºážááŒá¬ážááŸá¯ááá¯ááºáᬠááŒá¿áá¬áá»á¬ážááᯠááœá±á·ááŸááá±á¬á¡áá«á áááºáá±á¬ááºááŸá¯áá¯ááºáááºážá
ááºááá¯áááºáž áááºááá·áºá
á±áááºá¡ááœáẠááœááºáá±á«ááºáá¯ááºáá
áºáá¯ááᯠááẠconfigure áá¯ááºááá¯ááºáá«áááºá áá»áœááºá¯ááºááá¯á·áá¡ááŒá±á¡áá±ááœááºá Trivy ááœáẠáá»áœááºá¯ááºááá¯á·áááºááŸááºáá¬ážáá±á¬ SHOWSTOPPER ááááºážááŸááºááœáẠáááºááŸááºáá¬ážáá±á¬ áá±áááºááá¯ááºážááŒá¬ážááŸá¯ááŸáá·áºá¡áá° á¡á¬ážáááºážáá»ááºáá
áºáá¯ááᯠááœá±á·ááŸáááŸáᬠáááºáá±á¬ááºááŸá¯áááºááá·áºááœá¬ážáááºááŒá
áºáááºá .gitlab-ci.yml.
á¡áá¯á¶ážáááºááŸá¯áá
áºáá¯á
á®áááááºááᯠá
áááºáááºááŒááºážáá¯ááºáááºážáá
áºáá¯á
á®á ááŸááºáááºážááœááºá artifacts ááá¹áááŸá json ááá¯ááºáá»á¬ážááœáẠááá¯ááºááá¯ááºááŒáá·áºááŸá¯ááá¯ááºááẠááá¯á·ááá¯áẠááá¯ážááŸááºážáá±á¬ HTML á¡á
á®áááºáá¶á
á¬áá
áºáᯠ(á¡á±á¬ááºáá«á¡áá»ááºá¡áá±á«áº ááá¯ááá¯ááááŸáááá¯ááºáááº)á
3. á¡áá¯á¶ážáááºáá¯á¶á¡á
á®áááºáá¶á
á¬áá»á¬ážááᯠá¡áááºážáááºááá¯ááá¯áá°áá¬ážáááºááá¯ááºáá±á¬áá¯á¶á
á¶ááŒáá·áºáááºááŒáááºá áá»áá¯á·ááœááºážáá»ááºááá¬ážáá
áºáá¯áá«ááŸááá±á¬ JSON ááá¯ááºáá¯á¶ážáá¯ááᯠHTML ááá¯ááºáá
áºáá¯á¡ááŒá
áºááá¯á· ááŒá±á¬ááºážáááºá¡ááœáẠPython script á¡áá±ážááᯠá¡áá¯á¶ážááŒá¯áááºá
á€á
ááá
áºááᯠáá®ážááŒá¬ážá¡á
á®áááºáá¶ááŒááºážáá¯ááºáááºážá á
áááºáá¯ááºáá±á¬ááºááŒá®áž áááºážááá±á¬ááºáá¯á¶ážáááºáá®ážááŸá¯ááŸá¬ á¡á
á®áááºáá¶á
á¬áá« HTML ááá¯ááºáá
áºáá¯ááŒá
áºáááºá script source ááẠrepository ááœááºáááºážááŸáááŒá®áž ááá·áºááá¯á¡ááºáá»ááºáá»á¬ážá á¡áá±á¬ááºáá»á¬áž á
áááºááá¯á·ááᯠááá¯ááºáá»á±á¬áá®ááœá±ááŒá
áºá
á±ááá¯ááºáááºá
Shell áá²áá»á
CI/CD á áá áºá¡ááŒááºááẠDocker áá¯á¶áá»á¬ážááᯠá á áºáá±ážááẠááá¯á¡ááºáá±á¬á¡áá«ááœááºá ááá¯á·ááá¯áẠhost ááœáẠááá¯ááºááá¯ááºáá¯ááºáá±á¬ááºááá¯ááºáá±á¬ áá±á¬ááºááœáẠááœáŸááºááŒá¬ážáá»ááºáá»á¬ážá¡á¬ážáá¯á¶ážááᯠááá¯á¡ááºááá·áºá¡áá«ááœáẠáá¯áááááœá±ážáá»ááºááœáá·áºááẠááá·áºáá»á±á¬áºáááºá á€ááœá±ážáá»ááºááŸá¯ááᯠááá·áºááŸááºážáá±á¬ virtual (ááá¯á·ááá¯áẠá¡á á áºá¡ááŸááºáááº) á ááºáá±á«áºááœáẠáá¯ááºáá±á¬ááºááá¯ááºááá·áº á¡áááºááá·áºáá¯ááºáá¬ážáá±á¬ shell script ááŒáá·áº á¡áá»á¯á¶ážáááºáá«áááºá script ááẠá¡áááºááœááºáá±á¬áºááŒáá¬ážáá±á¬ gitlab-runner áá²á·ááá¯á·áá°áá®áá±á¬ááœáŸááºááŒá¬ážáá»ááºáá»á¬ážááá¯áá¯ááºáá±á¬ááºáááºá
script ááá¯á¡á±á¬ááºááŒááºá áœá¬áááºáááºáááºá¡ááœáẠDocker ááá¯á áá áºááœááºááá·áºááœááºážááááºááŒá áºááŒá®áž áááºááŸáá¡áá¯á¶ážááŒá¯áá°ááẠdocker á¡á¯ááºá á¯ááœááºááŸáááááºááŒá áºáááºá
áá¬ááºááœáŸááºážááᯠá€áá±áá¬ááœáẠááœá±á·ááá¯ááºáááº-
ááá¯ááºáá¡á ááœááºá ááááºážááŸááºáá»á¬ážááẠáááºááá·áºáá¯á¶ááá¯á áááºááºáááºááẠááá¯á¡ááºáááºááᯠáááºááŸááºáá±ážááŒá®áž áááºááá·áºáá±áááºáá»ááºáá»áá¯á·ááœááºážáá»ááºáá»á¬ážááẠáááºááŸááºáá¬ážáá±á¬ á¡ááŸá¬ážá¡ááœááºážáá¯ááºááŒáá·áº ááœááºáá±á«ááºááŒá áºá á±ááá·áº Trivy utility ááᯠáááºááŸááºáá±ážáá«áááºá
áá¬ááºááœáŸááºážááᯠáá¯ááºáá±á¬ááºáá±á ááºá¡ááœááºáž á¡áá¯á¶ážáááºááŸá¯á¡á¬ážáá¯á¶ážááᯠáááºážááœáŸááºááá¯á· áá±á«ááºážáá¯ááºáá¯ááºáá«áááºá docker_toolsáá°ááá¯á·áá²á· á¡áá¯ááºááááºááœá±á áááºážááœáŸááºáá²ááŸá¬ ááŸááá±áááºá docker_tools/jsoná ááŸáá·áº á¡á á®áááºáá¶á á¬áá«ááŸááá±á¬ HTML ááẠááá¯ááºáá²ááœáẠááŸááááá·áºáááºá results.html.
á¥ááᬠscript output
~/docker_cicd$ ./docker_sec_check.sh
[+] Setting environment variables
[+] Installing required packages
[+] Preparing necessary directories
[+] Fetching sample Dockerfile
2020-10-20 10:40:00 (45.3 MB/s) - âDockerfileâ saved [8071/8071]
[+] Pulling image to scan
latest: Pulling from bkimminich/juice-shop
[+] Running Hadolint
...
Dockerfile:205 DL3015 Avoid additional packages by specifying `--no-install-recommends`
Dockerfile:248 DL3002 Last USER should not be root
...
[+] Running Dockle
...
WARN - DKL-DI-0006: Avoid latest tag
* Avoid 'latest' tag
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
...
[+] Running Trivy
juice-shop/frontend/package-lock.json
=====================================
Total: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 2, CRITICAL: 0)
+---------------------+------------------+----------+---------+-------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | VERSION | TITLE |
+---------------------+------------------+----------+---------+-------------------------+
| object-path | CVE-2020-15256 | HIGH | 0.11.4 | Prototype pollution in |
| | | | | object-path |
+---------------------+------------------+ +---------+-------------------------+
| tree-kill | CVE-2019-15599 | | 1.2.2 | Code Injection |
+---------------------+------------------+----------+---------+-------------------------+
| webpack-subresource | CVE-2020-15262 | LOW | 1.4.1 | Unprotected dynamically |
| | | | | loaded chunks |
+---------------------+------------------+----------+---------+-------------------------+
juice-shop/package-lock.json
============================
Total: 20 (UNKNOWN: 0, LOW: 1, MEDIUM: 6, HIGH: 8, CRITICAL: 5)
...
juice-shop/package-lock.json
============================
Total: 5 (CRITICAL: 5)
...
[+] Removing left-overs
[+] Making the output look pretty
[+] Converting JSON results
[+] Writing results HTML
[+] Clean exit ============================================================
[+] Everything is done. Find the resulting HTML report in results.html
á¡áá¯á¶ážáááºááŸá¯á¡á¬ážáá¯á¶ážááŸáá·áºá¡áá° Docker áá¯á¶
áááááááºážáá áºáá¯á¡áá±ááŒáá·áºá áá¯á¶ááŒá¯á¶áá±ážá¡áá¯á¶ážá¡áá±á¬ááºáá»á¬ážááŒáá·áº áá¯á¶áá áºáá¯á¶áááºáá®ážááẠááá¯ážááŸááºážáá±á¬ Dockerfiles ááŸá áºáá¯ááᯠááŒá¯á á¯áá²á·áááºá Dockerfile áá áºáá¯ááẠrepository áá áºáá¯ááŸáá¯á¶áá áºáá¯á¶ááá¯á áááºááºáááºáááºá¡ááœáẠset ááá¯áááºáá±á¬ááºáááºáá°áá®áááá·áºáááºá áá¯ááá (Dockerfile_tar) ááẠimage áá áºáá¯ááŸáá·áº tar ááá¯ááºááá¯á áááºááºáááºáááºá¡ááœáẠset áá áºáá¯ááá¯áááºáá±á¬ááºáá¬ááœááºáá°áá®áááá·áºáááºá
1. áááºááá¯ááºáᬠDocker ááá¯ááºááŸáá·áº script áá»á¬ážááᯠrepository á០áá°áá«á
2. áá»áœááºá¯ááºááá¯á·ááẠáááºážááᯠá
ááºážáá±ážááœá²á¡ááœáẠá
áááºááá¯ááºáááº-
docker build -t dscan:image -f docker_security.df .
3. á ááºážáá±ážááœá²ááŒá®ážáá±á¬á¡áá«á áá»áœááºá¯ááºááá¯á·ááẠáá¯á¶áá²á០container áá áºáá¯ááᯠáááºáá®ážáá«á áá áºáá»áááºáááºážááŸá¬áááºá áá»áœááºá¯ááºááá¯á·ááẠáá»áœááºá¯ááºááá¯á·á áááºáááºá á¬ážáá±á¬ áá¯á¶áá¡áááºááŒáá·áº DOCKERIMAGE áááºáááºážáá»ááºááŒá±á¬ááºážáá²ááŸá¯ááᯠááŒááºáááºážááŒá®áž áá»áœááºá¯ááºááá¯á·áá ááºá០ááœá²ááŒááºážá áááºááŒá¬ááá¯áá±á¬ Dockerfile ááᯠááá¯ááºááá¯á· áááºáááºáááºá /Dockerfile (á€ááá¯ááºááá¯á· áááááááºážááŒá±á¬ááºáž ááá¯á¡ááºááŒá±á¬ááºáž áááááŒá¯áá«)á
docker run --rm -v $(pwd)/results:/results -v $(pwd)/docker_security.df:/Dockerfile -e DOCKERIMAGE="bkimminich/juice-shop" dscan:image
[+] Setting environment variables
[+] Running Hadolint
/Dockerfile:3 DL3006 Always tag the version of an image explicitly
[+] Running Dockle
WARN - DKL-DI-0006: Avoid latest tag
* Avoid 'latest' tag
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : juice-shop/node_modules/sqlite3/Dockerfile
* unnecessary file : juice-shop/node_modules/sqlite3/tools/docker/architecture/linux-arm64/Dockerfile
* unnecessary file : juice-shop/node_modules/sqlite3/tools/docker/architecture/linux-arm/Dockerfile
[+] Running Trivy
...
juice-shop/package-lock.json
============================
Total: 20 (UNKNOWN: 0, LOW: 1, MEDIUM: 6, HIGH: 8, CRITICAL: 5)
...
[+] Making the output look pretty
[+] Starting the main module ============================================================
[+] Converting JSON results
[+] Writing results HTML
[+] Clean exit ============================================================
[+] Everything is done. Find the resulting HTML report in results.html
ááááºáá»á¬ážááá¯
áá»áœááºá¯ááºááá¯á·ááẠDocker artifacts ááá¯á áááºááºáááºáááºá¡ááœáẠá¡ááŒá±áá¶á¡áá¯á¶ážá¡áá±á¬ááºáá á¹á ááºážá¡á á¯á¶á¡áááºáá áºáá¯ááá¯áᬠááŒáá·áºááŸá¯áá²á·ááŒá®ážá áá»áœááºá¯ááºáá¡ááŒááºá¡áá áá¯ááºáá¯á¶áá¯á¶ááŒá¯á¶áá±ážááá¯á¡ááºáá»ááºáá»á¬ážá ááá·áºáá»á±á¬áºáá±á¬á¡á áááºá¡ááá¯ááºážáá áºáá¯ááᯠá¡ááœááºáááá±á¬ááºá áœá¬ áá¯á¶ážá¡á¯ááºáá±ážááá·áº Docker ááŸá±ážáá±á¬ááºážáá á¹á ááºážáá»á¬ážááᯠáá»áœááºá¯ááºááá¯á·ááŒáá·áºááŸá¯áá²á·áááºá áá°áá®ááá·áºá á áºáá±ážááŸá¯áá»á¬ážá ááŸááá±á¬á¡á á®áááºáá¶á á¬áá»á¬ážááœá²ááŒááºáž ááá¯á·ááá¯áẠááœááºááá¯ážáá¯ááºááœáẠáááºáááºá¡áá¯ááºáá¯ááºááá¯ááºáá±á¬ á¡ááá±ážááŸáá·áº á¡ááá²á· áááááá¬áá»á¬ážá áœá¬áááºáž ááŸááá«áááºá á€áááááá¬áá»á¬ážá ááŒá¯á¶áá¯á¶áá¯á¶ážáááºáá»ááºááŸáá·áº áááºážááá¯á·ááᯠáá±á«ááºážá ááºážáá¯á¶ááẠá¡áááºážáááºáá±á¬ááºáá»ááŸáá±á«áºáá¬áá«áááºá .
á€áá±á¬ááºážáá«ážááœááºáá±á¬áºááŒáá¬ážáá±á¬ áááááá¬á¡á á¯á¶á áá±á¬ááºážáá±á¬á¡áá»ááºááŸá¬ áááºážááá¯á·á¡á¬ážáá¯á¶ážááẠopen source ááŒá áºááŒá®áž ááá·áºááá¯á¡ááºáá»ááºááŸáá·áº á¡ááŒá±áá¶á¡áá±á¬ááºá¡á¡á¯á¶ááŸáá·áº ááá¯ááºáá®áá±á¬á¡áá¬ááᯠááŸá¬ááœá±ááẠáááºážááá¯á·ááŸáá·áº á¡ááŒá¬ážá¡áá¬ážáá°áááááá¬áá»á¬ážááŸáá·áº á ááºážáááºááá¯ááºáááºá áá±áá»á¬áá«áááºá ááœá±á·ááŸááááá·áº á¡á¬ážáááºážáá»ááºá¡á¬ážáá¯á¶ážááᯠáá®ážááŒá¬ážá¡ááŒá±á¡áá±áá»á¬ážááœáẠá¡áá¯á¶ážáá»ááá¯ááºá á±ááẠáá±á·áá¬ááá·áºáááºá ááá¯á·áá±á¬áº á€á¡áá¬ááẠá¡áá¬áááºáá±á¬ááºážáá«ážááŒá®ážáá áºáá¯á¡ááœáẠáá±á«ááºážá ááºáá áºáá¯ááŒá áºáááºá
á€áááºážááœáŸááºáá»ááºá scripts ááŸáá·áº utilities áá»á¬ážááẠááá·áºá¡á¬áž áá°áá®áá±ážááŒá®áž ááœááºááááºáá¬á§áááá¬ááœáẠááá¯ááá¯áá¯á¶ááŒá¯á¶áá±á¬ á¡ááŒá±áá¶á¡áá±á¬ááºá¡áŠáá
áºáᯠáááºáá®ážáááºá¡ááœáẠá¡á
ááŸááºááŒá
áºáá¬áááá·áºáááºáᯠáá»áŸá±á¬áºááá·áºáá«áááºá
source: www.habr.com