ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜
ื”ื™ื™ ื”ืื‘ืจ!

ืื™ืŸ ืžืึธื“ืขืจืŸ ืคืึทืงื˜, ืจืขื›ื˜ ืฆื• ื“ืขืจ ื’ืจืึธื•ื™ื ื’ ืจืึธืœืข ืคื•ืŸ โ€‹โ€‹ืงืึทื ื˜ื™ื™ื ืขืจื™ื–ืึทื˜ื™ืึธืŸ ืื™ืŸ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึทืกืขืกืึทื–, ื“ื™ ืึทืจื•ื™ืกื’ืขื‘ืŸ ืคื•ืŸ ื™ื ืฉื•ืจื™ื ื’ ื“ื™ ื–ื™ื›ืขืจื”ื™ื™ื˜ ืคื•ืŸ ืคืึทืจืฉื™ื“ืŸ ืกื˜ืึทื’ืขืก ืื•ืŸ ืขื ื˜ื™ื˜ื™ื– ืคึฟืึทืจื‘ื•ื ื“ืŸ ืžื™ื˜ ืงืึทื ื˜ื™ื™ื ืขืจื– ืื™ื– ื ื™ืฉื˜ ื“ืขืจ ืงืœืขื ืกื˜ืขืจ ื•ื•ื™ื›ื˜ื™ืง ืึทืจื•ื™ืกื’ืขื‘ืŸ. ืžืึทื ื•ืึทืœ ื˜ืฉืขืงืก ืื™ื– ืฆื™ื™ื˜-ืงืึทื ืกื•ืžื™ื ื’, ืึทื–ื•ื™ ืขืก ื•ื•ืึธืœื˜ ื–ื™ื™ืŸ ืึท ื’ื•ื˜ืข ื’ืขื“ืึทื ืง ืฆื• ื ืขืžืขืŸ ืื™ืŸ ืžื™ื ื“ืกื˜ืขืจ ื“ื™ ืขืจืฉื˜ ืกื˜ืขืคึผืก ืฆื• ืึธื˜ืึทืžื™ื™ื˜ื™ื ื’ ื“ืขื ืคึผืจืึธืฆืขืก.

ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืื™ืš ื•ื•ืขืœ ื˜ื™ื™ืœืŸ ืคืึทืจื˜ื™ืง ืกืงืจื™ืคึผืก ืคึฟืึทืจ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ืขื˜ืœืขื›ืข ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืื•ืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืฆืขื•ื•ื™ืงืœืขืŸ ืึท ืงืœื™ื™ืŸ ื“ืขืžืึธ ืฉื˜ื™ื™ืŸ ืฆื• ืคึผืจื•ื‘ื™ืจืŸ ื“ืขื ืคึผืจืึธืฆืขืก. ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ื“ื™ ืžืึทื˜ืขืจื™ืึทืœืก ืฆื• ืขืงืกืคึผืขืจื™ืžืขื ื˜ ืžื™ื˜ ื•ื•ื™ ืฆื• ืึธืจื’ืึทื ื™ื–ื™ืจืŸ ื“ืขื ืคึผืจืึธืฆืขืก ืคื•ืŸ ื˜ืขืกื˜ื™ื ื’ ื“ื™ ื–ื™ื›ืขืจื”ื™ื™ื˜ ืคื•ืŸ Dockerfile ื‘ื™ืœื“ืขืจ ืื•ืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื–. ืขืก ืื™ื– ืงืœืึธืจ ืึทื– ื“ื™ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืคื•ืŸ ื™ืขื“ืขืจ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืื•ืŸ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ ืื™ื– ืึทื ื“ืขืจืฉ, ืึทื–ื•ื™ ืื•ื ื˜ืŸ ืื™ืš ื•ื•ืขืœ ืฆื•ืฉื˜ืขืœืŸ ืขื˜ืœืขื›ืข ืžืขื’ืœืขืš ืึธืคึผืฆื™ืขืก.

ื–ื™ื›ืขืจื”ื™ื™ื˜ ื˜ืฉืขืง ื™ื•ื˜ื™ืœืึทื˜ื™ื–

ืขืก ื–ืขื ืขืŸ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ืคืึทืจืฉื™ื“ืขื ืข ื”ืขืœืคึผืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืื•ืŸ ืกืงืจื™ืคึผืก ื•ื•ืึธืก ื“ื•ืจื›ืคื™ืจืŸ ื˜ืฉืขืงืก ืื•ื™ืฃ ืคืึทืจืฉื™ื“ืŸ ืึทืกืคึผืขืงืฅ ืคื•ืŸ ื“ื™ ื“ืึธืงืงืขืจ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ. ืขื˜ืœืขื›ืข ืคื•ืŸ โ€‹โ€‹ื–ื™ื™ ื”ืึธื‘ืŸ ืฉื•ื™ืŸ ื“ื™ืกืงืจื™ื™ื‘ื“ ืื™ืŸ ื“ืขื ืคืจื™ืขืจื“ื™ืงืŸ ืึทืจื˜ื™ืงืœ (https://habr.com/ru/company/swordfish_security/blog/518758/#docker-security), ืื•ืŸ ืื™ืŸ ื“ืขื ืžืึทื˜ืขืจื™ืึทืœ ืื™ืš ื•ื•ืึธืœื˜ ื•ื•ื™ ืฆื• ืคืึธืงื•ืก ืื•ื™ืฃ ื“ืจื™ื™ ืคื•ืŸ ื–ื™ื™, ื•ื•ืึธืก ื“ืขืงืŸ ื“ื™ ืคืึทืจื ืขื ืคื•ืŸ ื“ื™ ื–ื™ื›ืขืจื”ื™ื™ื˜ ืจืขืงื•ื•ื™ืจืขืžืขื ืฅ ืคึฟืึทืจ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ ื’ืขื‘ื•ื™ื˜ ื‘ืขืฉืึทืก ื“ื™ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก. ืื™ืŸ ืึทื“ื™ืฉืึทืŸ, ืื™ืš ื•ื•ืขืœ ืื•ื™ืš ื•ื•ื™ื™ึทื–ืŸ ืึท ื‘ื™ื™ืฉืคึผื™ืœ ืคื•ืŸ ื•ื•ื™ ื“ื™ ื“ืจื™ื™ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืงืขื ืขืŸ ื–ื™ื™ืŸ ืงืึธื ื ืขืงื˜ืขื“ ืื™ืŸ ืื™ื™ืŸ ืจืขืจื  - ืœื™ื ื™ืข ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ื–ื™ื›ืขืจื”ื™ื™ื˜ ื˜ืฉืขืงืก.

ื”ืื“ืืœื™ืŸ
https://github.com/hadolint/hadolint

ื ืคืขืจืœื™ ืคึผืฉื•ื˜ ืงืึทื ืกืึธื•ืœ ื ื•ืฆืŸ ื•ื•ืึธืก ื”ืขืœืคึผืก, ื•ื•ื™ ืึท ืขืจืฉื˜ืขืจ ืึทืคึผืจืึทืงืกืึทืžื™ื™ืฉืึทืŸ, ืึธืคึผืฉืึทืฆืŸ ื“ื™ ืจื™ื›ื˜ื™ืง ืื•ืŸ ื–ื™ื›ืขืจืงื™ื™ื˜ ืคื•ืŸ Dockerfile ืื™ื ืกื˜ืจื•ืงืฆื™ืขืก (ืœืžืฉืœ, ื ื™ืฆืŸ ื‘ืœื•ื™ื– ืึธื˜ืขืจื™ื™ื–ื“ ื‘ื™ืœื“ ืจืขื’ื™ืกื˜ืจื™ื– ืึธื“ืขืจ ื ื™ืฆืŸ ืกื•ื“ืึธ).

ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

ื“ืึธืงืœ
https://github.com/goodwithtech/dockle

ื ืงืึทื ืกืึธื•ืœ ื ื•ืฆืŸ ื•ื•ืึธืก ืึทืจื‘ืขื˜ ืžื™ื˜ ืึท ื‘ื™ืœื“ (ืึธื“ืขืจ ืžื™ื˜ ืึท ื’ืขืจืื˜ืขื•ื•ืขื˜ ื˜ืึทืจ ืึทืจืงื™ื™ื•ื• ืคื•ืŸ ืึท ื‘ื™ืœื“), ื•ื•ืึธืก ืงืึธื ื˜ืจืึธืœื™ืจืŸ ื“ื™ ืจื™ื›ื˜ื™ืง ืื•ืŸ ื–ื™ื›ืขืจื”ื™ื™ื˜ ืคื•ืŸ ืึท ื‘ืึทื–ื•ื ื“ืขืจ ื‘ื™ืœื“ ื•ื•ื™ ืึทื–ืึท, ืึทื ืึทืœื™ื™ื–ื™ื ื’ ื–ื™ื™ึทืŸ ืœื™ื™ึทืขืจืก ืื•ืŸ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ - ื•ื•ืึธืก ื™ื•ื–ืขืจื– ื–ืขื ืขืŸ ื‘ืืฉืืคืŸ, ื•ื•ืึธืก ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ื–ืขื ืขืŸ ื’ืขื ื™ืฆื˜, ื•ื•ืึธืก ื•ื•ืึทืœื™ื•ืžื– ื–ืขื ืขืŸ ืžืึธื•ื ื˜ืขื“, ื“ื™ ื‘ื™ื™ึทื–ื™ื™ึทืŸ ืคื•ืŸ ืึท ืœื™ื™ื“ื™ืง ืคึผืึทืจืึธืœ, ืืื–"ื• ื•. ื‘ื™ื– ืื™ืฆื˜ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ื˜ืฉืขืงืก ืื™ื– ื ื™ืฉื˜ ื–ื™ื™ืขืจ ื’ืจื•ื™ืก ืื•ืŸ ืื™ื– ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ืขื˜ืœืขื›ืข ืคื•ืŸ โ€‹โ€‹ืื•ื ื“ื–ืขืจ ืื™ื™ื’ืขื ืข ื˜ืฉืขืงืก ืื•ืŸ ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื– ืกื™ืก (ืฆืขื ื˜ืขืจ ืคึฟืึทืจ ืื™ื ื˜ืขืจื ืขื˜ ืกืขืงื•ืจื™ื˜ื™) ื‘ืขื ื˜ืฉืžืึทืจืง ืคึฟืึทืจ ื“ืึธืงืขืจ.
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

ื˜ืจื™ื•ื•ื™
https://github.com/aquasecurity/trivy

ื“ื™ ื ื•ืฆืŸ ืื™ื– ืึทื™ืžืขื“ ืฆื• ื’ืขืคึฟื™ื ืขืŸ ืฆื•ื•ื™ื™ ื˜ื™ื™ืคึผืก ืคื•ืŸ ื•ื•ืึทืœื ืขืจืึทื‘ื™ืœื™ื˜ื™ื– - ืคึผืจืึธื‘ืœืขืžืก ืžื™ื˜ ืึทืก ื‘ื•ื™ืขืŸ (ื’ืขืฉื˜ื™ืฆื˜ ื“ื•ืจืš ืึทืœืคึผื™ื™ืŸ, ืจืขื“ื”ืึทื˜ (EL), CentOS, Debian GNU, Ubuntu) ืื•ืŸ ืคึผืจืึธื‘ืœืขืžืก ืžื™ื˜ ื“ื™ืคึผืขื ื“ืึทื ืกื™ื– (Gemfile.lock, Pipfile.lock, composer.lock, ืคึผืขืงืœ -lock.json, yarn.lock, cargo.lock). ื˜ืจื™ื•ื•ื™ ืงืขื ืขืŸ ื™ื‘ืขืจืงื•ืงืŸ ื‘ื™ื™ื“ืข ืึท ื‘ื™ืœื“ ืื™ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืื•ืŸ ืึท ื”ื™ื’ืข ื‘ื™ืœื“, ืื•ืŸ ืงืขื ืขืŸ ืื•ื™ืš ื™ื‘ืขืจืงื•ืงืŸ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ื“ื™ ื˜ืจืึทื ืกืคืขืจื“ .ื˜ืึทืจ ื˜ืขืงืข ืžื™ื˜ ื“ื™ ื“ืึธืงืงืขืจ ื‘ื™ืœื“.

ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

ืึธืคึผืฆื™ืขืก ืคึฟืึทืจ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื–

ืื™ืŸ ืกื“ืจ ืฆื• ืคึผืจื•ื‘ื™ืจืŸ ื“ื™ ื“ื™ืกืงืจื™ื™ื‘ื“ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืื™ืŸ ืึทืŸ ืืคื’ืขื–ื•ื ื“ืขืจื˜ ืกื•ื•ื™ื•ื•ืข, ืื™ืš ื•ื•ืขืœ ืฆื•ืฉื˜ืขืœืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืคึฟืึทืจ ื™ื ืกื˜ืึธืœื™ื ื’ ืึทืœืข ื“ื™ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืื™ืŸ ืึท ื‘ื™ืกืœ ืกื™ืžืคึผืœืึทืคื™ื™ื“ ืคึผืจืึธืฆืขืก.

ื“ืขืจ ื”ื•ื™ืคึผื˜ ื’ืขื“ืึทื ืง ืื™ื– ืฆื• ื‘ืึทื•ื•ื™ื™ึทื–ืŸ ื•ื•ื™ ืื™ืจ ืงืขื ืขืŸ ื™ื ืกื˜ืจื•ืžืขื ื˜ ืึธื˜ืึทืžืึทื˜ื™ืง ืื™ื ื”ืึทืœื˜ ื•ื•ืขืจืึทืคืึทืงื™ื™ืฉืึทืŸ ืคื•ืŸ Dockerfiles ืื•ืŸ Docker ื‘ื™ืœื“ืขืจ ื•ื•ืึธืก ื–ืขื ืขืŸ ื‘ืืฉืืคืŸ ื‘ืขืฉืึทืก ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’.

ื“ืขืจ ื˜ืฉืขืง ื–ื™ืš ื‘ืืฉื˜ื™ื™ื˜ ืคื•ืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ืกื˜ืขืคึผืก:

  1. ืงืึธื ื˜ืจืึธืœื™ืจืŸ ื“ื™ ืจื™ื›ื˜ื™ืง ืื•ืŸ ื–ื™ื›ืขืจืงื™ื™ื˜ ืคื•ืŸ Dockerfile ืื™ื ืกื˜ืจื•ืงืฆื™ืขืก ืžื™ื˜ ืึท ืœื™ื ื˜ืขืจ ื ื•ืฆืŸ ื”ืื“ืืœื™ืŸ
  2. ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ื™ ืงืขืจืขืงื˜ื ืึทืก ืื•ืŸ ื–ื™ื›ืขืจืงื™ื™ึทื˜ ืคื•ืŸ ื“ื™ ืœืขืฆื˜ ืื•ืŸ ื™ื ื˜ืขืจืžื™ื“ื™ื™ื˜ ื‘ื™ืœื“ืขืจ ื ื™ืฆืŸ ืึท ื ื•ืฆืŸ ื“ืึธืงืœ
  3. ื˜ืฉืขืง ืคึฟืึทืจ ื“ื™ ื‘ื™ื™ึทื–ื™ื™ึทืŸ ืคื•ืŸ ืขืคื ื˜ืœืขืš ื‘ืึทื•ื•ื•ืกื˜ ื•ื•ืึทืœื ืขืจืึทื‘ื™ืœื™ื˜ื™ื– (CVE) ืื™ืŸ ื“ื™ ื‘ืึทื–ืข ื‘ื™ืœื“ ืื•ืŸ ืึท ื ื•ืžืขืจ ืคื•ืŸ ื“ื™ืคึผืขื ื“ืึทื ืกื™ื– - ื ื™ืฆืŸ ื“ื™ ื ื•ืฆืŸ ื˜ืจื™ื•ื•ื™

ืฉืคึผืขื˜ืขืจ ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื™ืš ื•ื•ืขืœ ื’ืขื‘ืŸ ื“ืจื™ื™ ืึธืคึผืฆื™ืขืก ืคึฟืึทืจ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื“ื™ ืกื˜ืขืคึผืก:
ื“ืขืจ ืขืจืฉื˜ืขืจ ืื™ื– ื“ื•ืจืš ืงืึทื ืคื™ื’ื™ืขืจื™ื ื’ ื“ื™ ืกื™ / ืกื™ ืจืขืจื  - ืœื™ื ื™ืข ื ื™ืฆืŸ GitLab ื•ื•ื™ ืึท ื‘ื™ื™ืฉืคึผื™ืœ (ืžื™ื˜ ืึท ื‘ืึทืฉืจื™ื™ึทื‘ื•ื ื’ ืคื•ืŸ ื“ืขื ืคึผืจืึธืฆืขืก ืคื•ืŸ ืจื™ื™ื–ื™ื ื’ ืึท ืคึผืจืึธื‘ืข ื‘ื™ื™ึทืฉืคึผื™ืœ).
ื“ื™ ืจื’ืข ืื™ื– ื ื™ืฆืŸ ืึท ืฉืึธืœ ืฉืจื™ืคื˜.
ื“ื™ ื“ืจื™ื˜ ื™ื ื•ื•ืึทืœื•ื•ื– ื‘ื•ื™ืขืŸ ืึท ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืฆื• ื™ื‘ืขืจืงื•ืงืŸ ื“ืึธืงืขืจ ื‘ื™ืœื“ืขืจ.
ืื™ืจ ืงืขื ืขืŸ ืงืœื™ื™ึทื‘ืŸ ื“ื™ ืึธืคึผืฆื™ืข ื•ื•ืึธืก ืกื•ืฅ ืื™ืจ ื‘ืขืกื˜ืขืจ, ืึทืจื™ื‘ืขืจืคื™ืจืŸ ืขืก ืฆื• ื“ื™ื™ืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืื•ืŸ ืึทื“ืึทืคึผื˜ ืขืก ืฆื• ื“ื™ื™ืŸ ื‘ืื“ืขืจืคืขื ื™ืฉืŸ.

ืึทืœืข ื ื™ื™ื˜ื™ืง ื˜ืขืงืขืก ืื•ืŸ ื ืึธืš ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ื–ืขื ืขืŸ ืื•ื™ืš ืœื™ื’ืŸ ืื™ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™: https://github.com/Swordfish-Security/docker_cicd

ื™ื ืึทื’ืจื™ื™ืฉืึทืŸ ืื™ืŸ GitLab CI / CD

ืื™ืŸ ื“ืขืจ ืขืจืฉื˜ืขืจ ืึธืคึผืฆื™ืข, ืžื™ืจ ื•ื•ืขืœืŸ ืงื•ืงืŸ ื•ื•ื™ ืื™ืจ ืงืขื ืขืŸ ื™ื ืกื˜ืจื•ืžืขื ื˜ ื–ื™ื›ืขืจื”ื™ื™ื˜ ื˜ืฉืขืงืก ื ื™ืฆืŸ ื“ื™ GitLab ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืกื™ืกื˜ืขื ื•ื•ื™ ืึท ื‘ื™ื™ืฉืคึผื™ืœ. ื“ืึธ ืžื™ืจ ื•ื•ืขืœืŸ ื“ื•ืจื›ื’ื™ื™ืŸ ื“ื™ ืกื˜ืขืคึผืก ืื•ืŸ ืจืขื›ืขื ืขืŸ ืื•ื™ืก ื•ื•ื™ ืฆื• ื™ื ืกื˜ืึทืœื™ืจืŸ ืึท ืคึผืจืึธื‘ืข ืกื•ื•ื™ื•ื•ืข ืžื™ื˜ GitLab ืคึฟื•ืŸ ืงืจืึทืฆืŸ, ืฉืึทืคึฟืŸ ืึท ืกืงืึทื ื™ื ื’ ืคึผืจืึธืฆืขืก ืื•ืŸ ืงืึทื˜ืขืจ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ื™ ืคึผืจืึธื‘ืข Dockerfile ืื•ืŸ ืึท ื˜ืจืึทืค ื‘ื™ืœื“ - ื“ื™ JuiceShop ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ.

ื™ื ืกื˜ืึธืœื™ื ื’ GitLab
1. ื™ื ืกื˜ืึทืœื™ืจืŸ ื“ืึธืงืงืขืจ:

sudo apt-get update && sudo apt-get install docker.io

2. ืœื™ื™ื’ ื“ืขื ืงืจืึทื ื˜ ื‘ืึทื ื™ืฆืขืจ ืฆื• ื“ื™ ื“ืึธืงืงืขืจ ื’ืจื•ืคึผืข ืึทื–ื•ื™ ืึทื– ืื™ืจ ืงืขื ืขืŸ ืึทืจื‘ืขื˜ืŸ ืžื™ื˜ ื“ืึธืงืขืจ ืึธืŸ ื ื™ืฆืŸ ืกื•ื“ืึธ:

sudo addgroup <username> docker

3. ื’ืขืคึฟื™ื ืขืŸ ื“ื™ื™ืŸ IP:

ip addr

4. ื™ื ืกื˜ืึทืœื™ืจืŸ ืื•ืŸ ืงืึทื˜ืขืจ GitLab ืื™ืŸ ื“ืขื ืงืึทื ื˜ื™ื™ื ืขืจ, ืจื™ืคึผืœื™ื™ืกื™ื ื’ ื“ื™ 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 ืื•ืŸ ื™ื ื™ืฉืึทืœื™ื™ื– ืขืก ืžื™ื˜ ื“ื™ ืึธื ื”ื™ื™ื‘ ื˜ืขืงืข README.md:
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜
7. ืื™ืฆื˜ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื™ื ืกื˜ืึทืœื™ืจืŸ GitLab Runner: ืึทืŸ ืึทื’ืขื ื˜ ื•ื•ืึธืก ื•ื•ืขื˜ ืœื•ื™ืคืŸ ืึทืœืข ื“ื™ ื ื™ื™ื˜ื™ืง ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืื•ื™ืฃ ื‘ืขื˜ืŸ.
ืืจืืคืงืืคื™ืข ื“ื™ ืœืขืฆื˜ืข ื•ื•ืขืจืกื™ืข (ืื™ืŸ ื“ืขื ืคืึทืœ, ืคึฟืึทืจ ืœื™ื ื•ืงืก 64-ื‘ื™ืกืœ):

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. ืœื™ื™ื’ ืึทืŸ ืึทืก ื‘ืึทื ื™ืฆืขืจ ืคึฟืึทืจ ืจืึทื ืขืจ ืื•ืŸ ืึธื ื”ื™ื™ื‘ ื“ื™ ื“ื™ื ืกื˜:

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 ื‘ื™ื™ึทืฉืคึผื™ืœ.
ืฆื• ื˜ืึธืŸ ื“ืึธืก, ืขืคึฟืขื ืขืŸ ื“ื™ ืกืขื˜ื˜ื™ื ื’ืก-ืกื™ / ืงืึธืžืคึผืึทืงื˜ื“ื™ืกืง ื‘ืœืึทื˜ (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) ืื•ืŸ ืื•ื™ืฃ ื“ื™ ืจืึทื ืขืจื– ืงื•ื•ื™ื˜ืœ ื’ืขืคึฟื™ื ืขืŸ ื“ื™ URL ืื•ืŸ ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ืกื™ืžืขืŸ:
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜
11. ืคืึทืจืฉืจื™ื™ึทื‘ืŸ ืจืึทื ืขืจ ื“ื•ืจืš ืคืึทืจื‘ื™ื™ึทื˜ืŸ ื“ื™ URL ืื•ืŸ ืคืึทืจืฉืจื™ื™ื‘ื•ื ื’ ืกื™ืžืขืŸ:

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"

ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ืึท ื’ืจื™ื™ื˜-ื’ืขืžืื›ื˜ ืืจื‘ืขื˜ืŸ ื’ื™ื˜ืœืึทื‘, ืื™ืŸ ื•ื•ืึธืก ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืœื™ื™ื’ืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืฆื• ืึธื ื”ื™ื™ื‘ืŸ ืื•ื ื“ื–ืขืจ ื™ื•ื˜ื™ืœืึทื˜ื™ื–. ืื™ืŸ ื“ืขื ื“ืขืžืึธ, ืžื™ืจ ื˜ืึธืŸ ื ื™ื˜ ื”ืึธื‘ืŸ ื“ื™ ืกื˜ืขืคึผืก ืฆื• ื‘ื•ื™ืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืื•ืŸ ืงืึทื ื˜ืึทืžืึทื ื™ื™ื– ืขืก, ืึธื‘ืขืจ ืื™ืŸ ืึท ืคืึทืงื˜ื™ืฉ ืกื•ื•ื™ื•ื•ืข, ื“ืึธืก ื•ื•ืึธืœื˜ ื–ื™ื™ืŸ ืคึผืจื™ื™ื“ื™ื“ ื“ื™ ืกืงืึทื ื™ื ื’ ืกื˜ืขืคึผืก ืื•ืŸ ื“ื–ืฉืขื ืขืจื™ื™ื˜ ื‘ื™ืœื“ืขืจ ืื•ืŸ ืึท Dockerfile ืคึฟืึทืจ ืึทื ืึทืœื™ืกื™ืก.

ืจืขืจื  - ืœื™ื ื™ืข ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ

1. ืœื™ื™ื’ ื˜ืขืงืขืก ืฆื• ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ mydockerple.df (ื“ืึธืก ืื™ื– ืึท ืคึผืจืึธื‘ืข Dockerfile ื•ื•ืึธืก ืžื™ืจ ื•ื•ืขืœืŸ ืงืึธื ื˜ืจืึธืœื™ืจืŸ) ืื•ืŸ ื“ื™ GitLab CI / CD ืคึผืจืึธืฆืขืก ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื˜ืขืงืข .gitlab-cicd.yml, ื•ื•ืึธืก ืจืฉื™ืžื•ืช ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืคึฟืึทืจ ืกืงืึทื ืขืจื– (ื˜ืึธืŸ ื“ื™ ืคึผื•ื ืงื˜ ืื™ืŸ ื“ื™ ื˜ืขืงืข ื ืึธืžืขืŸ).

ื“ื™ YAML ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื˜ืขืงืข ื›ึผื•ืœืœ ืื™ื ืกื˜ืจื•ืงืฆื™ืขืก ืฆื• ืœื•ื™ืคืŸ ื“ืจื™ื™ ื™ื•ื˜ื™ืœืึทื˜ื™ื– (Hadolint, Dockle ืื•ืŸ Trivy) ื•ื•ืึธืก ื•ื•ืขื˜ ืึทื ืึทืœื™ื™ื– ื“ื™ ืื•ื™ืกื’ืขืงืœื™ื‘ืŸ Dockerfile ืื•ืŸ ื“ื™ ื‘ื™ืœื“ ืกืคึผืขืกื™ืคื™ืขื“ ืื™ืŸ ื“ื™ DOCKERFILE ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง. ื›ืœ ื ื™ื™ื˜ื™ืง ื˜ืขืงืขืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื ื•ืžืขืŸ ืคึฟื•ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™: https://github.com/Swordfish-Security/docker_cicd/

ืื•ื™ืกืฆื•ื’ ืคื•ืŸ mydockerple.df (ื“ืึธืก ืื™ื– ืึทืŸ ืึทื‘ืกื˜ืจืึทืงื˜ ื˜ืขืงืข ืžื™ื˜ ืึท ืกื›ื•ื ืคื•ืŸ ืึทืจื‘ื™ื˜ืจืึทืจื™ืฉ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ื‘ืœื•ื™ื– ืฆื• ื‘ืึทื•ื•ื™ื™ึทื–ืŸ ื“ื™ ืึธืคึผืขืจืึทืฆื™ืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ื ื•ืฆืŸ). ื“ื™ืจืขืงื˜ ืœื™ื ืง ืฆื• ื“ืขืจ ื˜ืขืงืข: mydockerple.df

ืื™ื ื”ืึทืœื˜ ืคื•ืŸ mydockerple.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

ืื•ื™ื‘ ื ื™ื™ื˜ื™ืง, ืื™ืจ ืงืขื ืขืŸ ืื•ื™ืš ื™ื‘ืขืจืงื•ืงืŸ ื’ืขืจืื˜ืขื•ื•ืขื˜ ื‘ื™ืœื“ืขืจ ืื™ืŸ ื“ื™ ืคืึธืจืขื ืคื•ืŸ ืึท .ื˜ืึทืจ ืึทืจืงื™ื™ื•ื• (ืึธื‘ืขืจ, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื˜ื•ื™ืฉืŸ ื“ื™ ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืคึฟืึทืจ ื“ื™ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืื™ืŸ ื“ื™ YAML ื˜ืขืงืข)

NB: ื˜ืจื™ื•ื•ื™ ืจื™ืงื•ื•ื™ื™ืขืจื– ืื™ื ืกื˜ืึทืœื™ืจืŸ ืจืคึผื ะธ ื’ื™ื™ืŸ. ืึทื ื“ืขืจืฉ, ืขืก ื•ื•ืขื˜ ื“ื–ืฉืขื ืขืจื™ื™ื˜ ืขืจืจืึธืจืก ื•ื•ืขืŸ ืกืงืึทื ื™ื ื’ RedHat-ื‘ืื–ื™ืจื˜ ื‘ื™ืœื“ืขืจ ืื•ืŸ ืจื™ืกื™ื•ื•ื™ื ื’ ื“ืขืจื”ื™ื™ึทื ื˜ื™ืงื•ื ื’ืขืŸ ืฆื• ื“ื™ ื•ื•ืึทืœื ืขืจืึทื‘ื™ืœื™ื˜ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก.

2. ื ืึธืš ืึทื“ื™ื ื’ ื˜ืขืงืขืก ืฆื• ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™, ืœื•ื™ื˜ ื“ื™ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืื™ืŸ ืื•ื ื“ื–ืขืจ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื˜ืขืงืข, GitLab ื•ื•ืขื˜ ืื•ื™ื˜ืึธืžืึทื˜ื™ืฉ ืึธื ื”ื™ื™ื‘ืŸ ื“ืขื ื‘ื•ื™ืขืŸ ืื•ืŸ ื™ื‘ืขืจืงื•ืงืŸ ืคึผืจืึธืฆืขืก. ืื•ื™ืฃ ื“ื™ ืกื™ / ืกื™ โ†’ ืคึผื™ื™ืคึผืœื™ื™ื ื– ืงื•ื•ื™ื˜ืœ ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ ื“ื™ ืคึผืจืึธื’ืจืขืก ืคื•ืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื–.

ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ืžื™ืจ ื”ืึธื‘ืŸ ืคื™ืจ ื˜ืึทืกืงืก. ื“ืจื™ื™ ืคื•ืŸ ื–ื™ื™ ื”ืึทื ื“ืœืขืŸ ื’ืœื™ื™ึทืš ืžื™ื˜ ืกืงืึทื ื™ื ื’, ืื•ืŸ ื“ื™ ืœืขืฆื˜ืข (ืจืขืคึผืึธืจื˜) ืงืึทืœืขืงืฅ ืึท ืคึผืฉื•ื˜ ื‘ืึทืจื™ื›ื˜ ืคื•ืŸ ืฆืขื•ื•ืึธืจืคืŸ ื˜ืขืงืขืก ืžื™ื˜ ืกืงืึทื ื™ื ื’ ืจืขื–ื•ืœื˜ืึทื˜ืŸ.
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜
ื“ื•ืจืš ืคืขืœื™ืงื™ื™ึทื˜, ื˜ืจื™ื•ื•ื™ ืกื˜ืึทืคึผืก ืคืœื™ืกื ื“ื™ืง ืื•ื™ื‘ ืงืจื™ื˜ื™ืฉ ื•ื•ืึทืœื ืขืจืึทื‘ื™ืœื™ื˜ื™ื– ื–ืขื ืขืŸ ื“ื™ื˜ืขืงื˜ืึทื“ ืื™ืŸ ื“ื™ ื‘ื™ืœื“ ืึธื“ืขืจ ื“ื™ืคึผืขื ื“ืึทื ืกื™ื–. ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, Hadolint ืฉื˜ืขื ื“ื™ืง ืงืขืจื˜ ืึท ื”ืฆืœื—ื” ืงืึธื“ ื•ื•ื™ื™ึทืœ ืขืก ืฉื˜ืขื ื“ื™ืง ืจืขื–ื•ืœื˜ืึทื˜ืŸ ืื™ืŸ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ, ื•ื•ืึธืก ื– ื“ื™ ื‘ื•ื™ืขืŸ ืฆื• ื”ืึทืœื˜ืŸ.

ื“ืขืคึผืขื ื“ื™ื ื’ ืื•ื™ืฃ ื“ื™ื™ืŸ ืกืคึผืขืฆื™ืคื™ืฉ ืจืขืงื•ื•ื™ืจืขืžืขื ืฅ, ืื™ืจ ืงืขื ืขืŸ ืงืึทื ืคื™ื’ื™ืขืจ ืึท ืึทืจื•ื™ืกื’ืึทื ื’ ืงืึธื“ ืึทื–ื•ื™ ืึทื– ื•ื•ืขืŸ ื“ื™ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ื“ืขื˜ืขืงื˜ ืคึผืจืึธื‘ืœืขืžืก ืคื•ืŸ ืึท ื–ื™ื›ืขืจ ืงืจื™ื˜ื™ืงืึทื˜ื™, ื–ื™ื™ ืื•ื™ืš ื”ืึทืœื˜ืŸ ื“ื™ ื‘ื•ื™ืขืŸ ืคึผืจืึธืฆืขืก. ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ, ื“ื™ ื‘ื•ื™ืขืŸ ื•ื•ืขื˜ ื”ืึทืœื˜ืŸ ื‘ืœื•ื™ื– ืื•ื™ื‘ ื˜ืจื™ื•ื•ื™ ื“ื™ื˜ืขืงืฅ ืึท ื•ื•ืึทืœื ืขืจืึทื‘ื™ืœื™ื˜ื™ ืžื™ื˜ ื“ื™ ืงืจื™ื˜ื™ืงื™ื™ื˜ ืึทื– ืžื™ืจ ืกืคึผืขืกื™ืคื™ืขื“ ืื™ืŸ ื“ื™ SHOWSTOPPER ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง ืื™ืŸ .ื’ื™ื˜ืœืื‘-ืกื™.ื™ืžืœ.
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

ื“ืขืจ ืจืขื–ื•ืœื˜ืึทื˜ ืคื•ืŸ ื™ืขื“ืขืจ ื ื•ืฆืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื–ืŸ ืื™ืŸ ื“ื™ ืงืœืึธืฅ ืคื•ืŸ ื™ืขื“ืขืจ ืกืงืึทื ื™ื ื’ ืึทืจื‘ืขื˜, ื’ืœื™ื™ืš ืื™ืŸ ื“ื™ json ื˜ืขืงืขืก ืื™ืŸ ื“ื™ ืึทืจื˜ืึทืคืึทืงืฅ ืึธืคึผื˜ื™ื™ืœื•ื ื’, ืึธื“ืขืจ ืื™ืŸ ืึท ืคึผืฉื•ื˜ HTML ื‘ืึทืจื™ื›ื˜ (ืžืขืจ ืื•ื™ืฃ ื“ืขื ืื•ื ื˜ืŸ):
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

3. ืฆื• ืคืึธืจืฉื˜ืขืœืŸ ื™ื•ื˜ื™ืœืึทื˜ื™ ืจื™ืคึผืึธืจืฅ ืื™ืŸ ืึท ื‘ื™ืกืœ ืžืขืจ ืžืขื ื˜ืฉ-ืœื™ื™ื ืขื•ื•ื“ื™ืง ืคืึธืจืขื, ืึท ืงืœื™ื™ืŸ ืคึผื™ื˜ื”ืึธืŸ ืฉืจื™ืคื˜ ืื™ื– ื’ืขื ื™ืฆื˜ ืฆื• ืงืึธื ื•ื•ืขืจื˜ ื“ืจื™ื™ JSON ื˜ืขืงืขืก ืื™ืŸ ืื™ื™ืŸ HTML ื˜ืขืงืข ืžื™ื˜ ืึท ื˜ื™ืฉ ืคื•ืŸ ื—ืกืจื•ื ื•ืช.
ื“ืขืจ ืฉืจื™ืคื˜ ืื™ื– ืœืึธื ื˜ืฉื˜ ื“ื•ืจืš ืึท ื‘ืึทื–ื•ื ื“ืขืจ ื‘ืืจื™ื›ื˜ ืึทืจื‘ืขื˜, ืื•ืŸ ื–ื™ื™ืŸ ืœืขืฆื˜ ืึทืจื˜ืึทืคืึทืงื˜ ืื™ื– ืึท HTML ื˜ืขืงืข ืžื™ื˜ ืึท ื‘ืึทืจื™ื›ื˜. ื“ืขืจ ืฉืจื™ืคื˜ ืžืงื•ืจ ืื™ื– ืื•ื™ืš ืื™ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืื•ืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืฆื•ื’ืขืคืืกื˜ ืฆื• ื“ื™ื™ืŸ ื‘ืื“ืขืจืคืขื ื™ืฉืŸ, ืคืืจื‘ืŸ, ืขื˜ืง.
ืžืขื˜ื”ืึธื“ืก ืื•ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ืึธืงืงืขืจ ื–ื™ื›ืขืจื”ื™ื™ื˜

ืฉืึธืœ ืฉืจื™ืคื˜

ื“ื™ ืจื’ืข ืึธืคึผืฆื™ืข ืื™ื– ืคึผืึทืกื™ืง ืคึฟืึทืจ ืงืึทืกืขืก ื•ื•ืขืŸ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืงืึธื ื˜ืจืึธืœื™ืจืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ ืึทืจื•ื™ืก ืคื•ืŸ ื“ื™ ืกื™ / ืกื™ ืกื™ืกื˜ืขื ืึธื“ืขืจ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื”ืึธื‘ืŸ ืึทืœืข ื“ื™ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืื™ืŸ ืึท ืคืึธืจืขื ื•ื•ืึธืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ืขืงืกืึทืงื™ื•ื˜ืึทื“ ื’ืœื™ื™ึทืš ืื•ื™ืฃ ื“ืขืจ ื‘ืึทืœืขื‘ืึธืก. ื“ืขืจ ืึธืคึผืฆื™ืข ืื™ื– ื‘ืื“ืขืงื˜ ื“ื•ืจืš ืึท ืคืึทืจื˜ื™ืง ืฉืึธืœ ืฉืจื™ืคื˜ ื•ื•ืึธืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ืœื•ื™ืคืŸ ืื•ื™ืฃ ืึท ืจื™ื™ืŸ ื•ื•ื™ืจื˜ื•ืึทืœ (ืึธื“ืขืจ ืืคื™ืœื• ืคืึทืงื˜ื™ืฉ) ืžืึทืฉื™ืŸ. ื“ืขืจ ืฉืจื™ืคื˜ ืขืงืกืึทืงื™ื•ืฅ ื“ื™ ื–ืขืœื‘ืข ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ื•ื•ื™ ื“ื™ ื’ื™ื˜ืœืึทื‘-ืจืึทื ืขืจ ื“ื™ืกืงืจื™ื™ื‘ื“ ืื•ื™ื‘ืŸ.

ืคึฟืึทืจ ื“ื™ ืฉืจื™ืคื˜ ืฆื• ืœื•ื™ืคืŸ ื”ืฆืœื—ื”, Docker ืžื•ื–ืŸ ื–ื™ื™ืŸ ืื™ื ืกื˜ืึทืœื™ืจืŸ ืื•ื™ืฃ ื“ื™ ืกื™ืกื˜ืขื ืื•ืŸ ื“ืขืจ ืงืจืึทื ื˜ ื‘ืึทื ื™ืฆืขืจ ืžื•ื–ืŸ ื–ื™ื™ืŸ ืื™ืŸ ื“ื™ ื“ืึธืงืงืขืจ ื’ืจื•ืคึผืข.

ื“ื™ ืฉืจื™ืคื˜ ื–ื™ืš ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขืคึฟื•ื ืขืŸ ื“ืึธ: docker_sec_check.sh

ืื™ืŸ ื“ื™ ืึธื ื”ื™ื™ื‘ ืคื•ืŸ ื“ืขืจ ื˜ืขืงืข, ื•ื•ืขืจื™ืึทื‘ืึทืœื– ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ื•ื•ืึธืก ื‘ื™ืœื“ ื“ืึทืจืฃ ื–ื™ื™ืŸ ืกืงืึทื ื“ ืื•ืŸ ื•ื•ืึธืก ืงืจื™ื˜ื™ืงื™ื™ื˜ ื—ืกืจื•ื ื•ืช ื•ื•ืขื˜ ืคืึทืจืฉืึทืคืŸ ื“ื™ ื˜ืจื™ื•ื•ื™ ื ื•ืฆืŸ ืฆื• ืึทืจื•ื™ืกื’ืึทื ื’ ืžื™ื˜ ื“ื™ ืกืคึผืขืกื™ืคื™ืขื“ ื˜ืขื•ืช ืงืึธื“.

ื‘ืขืฉืึทืก ืฉืจื™ืคื˜ ื“ื•ืจื›ืคื™ืจื•ื ื’, ืึทืœืข ื™ื•ื˜ื™ืœืึทื˜ื™ื– ื•ื•ืขื˜ ื–ื™ื™ืŸ ื“ืึทื•ื ืœืึธื•ื“ื™ื“ ืฆื• ื“ืขืจ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ docker_tools, ื“ื™ ืจืขื–ื•ืœื˜ืึทื˜ืŸ ืคื•ืŸ ื–ื™ื™ืขืจ ืึทืจื‘ืขื˜ ื–ืขื ืขืŸ ืื™ืŸ ื“ื™ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ docker_tools/json, ืื•ืŸ ื“ื™ HTML ืžื™ื˜ ื“ืขื ื‘ืึทืจื™ื›ื˜ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืื™ืŸ ื“ืขืจ ื˜ืขืงืข ืจืขื–ื•ืœื˜ืึทื˜ืŸ.html.

ื‘ื™ื™ึทืฉืคึผื™ืœ ืฉืจื™ืคื˜ ืจืขื–ื•ืœื˜ืึทื˜

~/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

ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ ืึทืœืข ื™ื•ื˜ื™ืœืึทื˜ื™ื–

ื•ื•ื™ ืึท ื“ืจื™ื˜ ืึธืœื˜ืขืจื ืึทื˜ื™ื•ื•, ืื™ืš ืฆื•ื ื•ื™ืคื’ืขืฉื˜ืขืœื˜ ืฆื•ื•ื™ื™ ืคึผืฉื•ื˜ ื“ืึธืงืขืจืคื™ืœืขืก ืฆื• ืฉืึทืคึฟืŸ ืึท ื‘ื™ืœื“ ืžื™ื˜ ื–ื™ื›ืขืจื”ื™ื™ื˜ ื™ื•ื˜ื™ืœืึทื˜ื™ื–. ืื™ื™ืŸ Dockerfile ื•ื•ืขื˜ ื”ืขืœืคึฟืŸ ื‘ื•ื™ืขืŸ ืึท ืกื›ื•ื ืคึฟืึทืจ ืกืงืึทื ื™ื ื’ ืึท ื‘ื™ืœื“ ืคึฟื•ืŸ ืึท ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™, ื“ื™ ืจื’ืข (Dockerfile_tar) ื•ื•ืขื˜ ื”ืขืœืคึฟืŸ ื‘ื•ื™ืขืŸ ืึท ื’ืึทื ื’ ืคึฟืึทืจ ืกืงืึทื ื™ื ื’ ืึท ื˜ืึทืจ ื˜ืขืงืข ืžื™ื˜ ืึท ื‘ื™ืœื“.

1. ื ืขืžืขืŸ ื“ื™ ืงืึธืจืึทืกืคึผืึทื ื“ื™ื ื’ ื“ืึธืงืงืขืจ ื˜ืขืงืข ืื•ืŸ ืกืงืจื™ืคึผืก ืคื•ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ https://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfile.
2. ืžื™ืจ ืงืึทื˜ืขืจ ืขืก ืคึฟืึทืจ ืคึฟืึทืจื–ืึทืžืœื•ื ื’:

docker build -t dscan:image -f docker_security.df .

3. ื ืึธืš ื“ื™ ืคึฟืึทืจื–ืึทืžืœื•ื ื’ ืื™ื– ื’ืขืขื ื“ื™ืงื˜, ืžื™ืจ ืžืึทื›ืŸ ืึท ืงืึทื ื˜ื™ื™ื ืขืจ ืคื•ืŸ ื“ื™ ื‘ื™ืœื“. ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, ืžื™ืจ ืคืึธืจืŸ ื“ื™ DOCKERIMAGE ืกื•ื•ื™ื•ื•ืข ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง ืžื™ื˜ ื“ื™ ื ืึธืžืขืŸ ืคื•ืŸ ื“ื™ ื‘ื™ืœื“ ื•ื•ืึธืก ืžื™ืจ ื–ืขื ืขืŸ ืื™ื ื˜ืขืจืขืกื™ืจื˜ ืื™ืŸ ืื•ืŸ ืึธื ืงืœืึทืคึผืŸ ื“ื™ 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

ืจืขื–ื•ืœื˜ืึทื˜ืŸ

ืžื™ืจ ื’ืขืงื•ืงื˜ ืื•ื™ืฃ ื‘ืœื•ื™ื– ืื™ื™ืŸ ื™ืงืขืจื“ื™ืง ื’ืึทื ื’ ืคื•ืŸ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืคึฟืึทืจ ืกืงืึทื ื™ื ื’ ื“ืึธืงืงืขืจ ืึทืจื˜ืึทืคืึทืงืฅ, ื•ื•ืึธืก, ืื™ืŸ ืžื™ื™ืŸ ืžื™ื™ื ื•ื ื’, ืงืึธื•ื•ืขืจืก ื–ื™ื™ืขืจ ื™ืคืขืงื˜ื™ื•ื•ืœื™ ืึท ืœื™ื™ึทื˜ื™ืฉ ื˜ื™ื™ืœ ืคื•ืŸ ื“ื™ ื‘ื™ืœื“ ื–ื™ื›ืขืจื”ื™ื™ื˜ ืจืขืงื•ื•ื™ืจืขืžืขื ืฅ. ืขืก ื–ืขื ืขืŸ ืื•ื™ืš ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ื‘ืึทืฆืึธืœื˜ ืื•ืŸ ืคืจื™ื™ ืžื›ืฉื™ืจื™ื ื•ื•ืึธืก ืงืขื ืขืŸ ื“ื•ืจื›ืคื™ืจืŸ ื“ื™ ื–ืขืœื‘ืข ื˜ืฉืขืงืก, ืฆื™ืขืŸ ืฉื™ื™ืŸ ืจื™ืคึผืึธืจืฅ ืึธื“ืขืจ ืึทืจื‘ืขื˜ ืจื™ื™ืŸ ืื™ืŸ ืงืึทื ืกืึธื•ืœ ืžืึธื“ืข, ื“ืขืงืŸ ืงืึทื ื˜ื™ื™ื ืขืจ ืคืึทืจื•ื•ืึทืœื˜ื•ื ื’ ืกื™ืกื˜ืขืžืขืŸ, ืืื–"ื• ื•. ืึทืŸ ืื™ื‘ืขืจื‘ืœื™ืง ืคื•ืŸ ื“ื™ ืžื›ืฉื™ืจื™ื ืื•ืŸ ื•ื•ื™ ืฆื• ื•ื™ืกืฉื˜ื™ืžืขืŸ ื–ื™ื™ ืงืขืŸ ื“ืขืจืฉื™ื™ึทื ืขืŸ ืึท ื‘ื™ืกืœ ืฉืคึผืขื˜ืขืจ .

ื“ื™ ื’ื•ื˜ืข ื–ืึทืš ื•ื•ืขื’ืŸ ื“ืขื ื’ืึทื ื’ ืคื•ืŸ ืžื›ืฉื™ืจื™ื ื“ื™ืกืงืจื™ื™ื‘ื“ ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื™ื– ืึทื– ื–ื™ื™ ื–ืขื ืขืŸ ืึทืœืข ืึธืคึฟืŸ ืžืงื•ืจ ืื•ืŸ ืื™ืจ ืงืขื ืขืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ืžื™ื˜ ื–ื™ื™ ืื•ืŸ ืื ื“ืขืจืข ืขื ืœืขืš ืžื›ืฉื™ืจื™ื ืฆื• ื’ืขืคึฟื™ื ืขืŸ ื•ื•ืึธืก ืกื•ืฅ ื“ื™ื™ืŸ ื“ืึทืจืฃ ืื•ืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ. ืคื•ืŸ ืงื•ืจืก, ืึทืœืข ื•ื•ืึทืœื ืขืจืึทื‘ื™ืœื™ื˜ื™ื– ื•ื•ืึธืก ื–ืขื ืขืŸ ื’ืขืคึฟื•ื ืขืŸ ื–ืึธืœ ื–ื™ื™ืŸ ื’ืขืœืขืจื ื˜ ืคึฟืึทืจ ืึธื ื•ื•ืขื ื“ืœืขืš ืื™ืŸ ืกืคึผืขืฆื™ืคื™ืฉ ื˜ื ืึธื™ื, ืึธื‘ืขืจ ื“ืึธืก ืื™ื– ืึท ื˜ืขืžืข ืคึฟืึทืจ ืึท ืฆื•ืงื•ื ืคึฟื˜ ื’ืจื•ื™ืก ืึทืจื˜ื™ืงืœ.

ืื™ืš ื”ืึธืคึฟืŸ ืึทื– ื“ืขืจ ืคื™ืจืขืจ, ืกืงืจื™ืคึผืก ืื•ืŸ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ื•ื•ืขื˜ ื”ืขืœืคึฟืŸ ืื™ืจ ืื•ืŸ ื•ื•ืขืจืŸ ืึท ืกื˜ืึทืจื˜ื™ื ื’ ืคื•ื ื˜ ืคึฟืึทืจ ืงืจื™ื™ื™ื˜ื™ื ื’ ืึท ืžืขืจ ื–ื™ื›ืขืจ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืื™ืŸ ื“ืขืจ ื’ืขื’ื ื˜ ืคื•ืŸ ืงืึทื ื˜ืึทื™ื ืขืจื™ื–.

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’