“앤코어”라고 불리우는 DevSecOps 도구의 사용법과 Jenkins상에서 Anchore와 연계된 CICD pipeline을
만드는 과정에 대해 알아보도록 하겠습니다.
Anchore 는?
컨테이너 이미지에 대한 검증, 분석, 검사에 대한 중앙화된 서비스를 제공하는 오픈소스 프로젝트입니다.
Docker V2 호환 컨테이너 저장소들로부터 컨테이너 이미지를 다운로드 받고 분석합니다.
그리고 사용자가 지정한 정책에 기반해 평가를 수행합니다.
CI/CD와 통합된 서비스로 빌드 파이프라인 상에서 보안 및 규정에 대한 체크를 시행할수 있고
RESTful API와의 연동을 통해 컨테이너 모니터링과의 연동의 구성요소로도 사용될수 있습니다.
Anchore Engine 은?
Anchore는 상용버전과 open source 버전이 있는데 Anchore Engine은 오픈소스 버전으로
깊이있는 이미지 검사와 취약점 스캐닝을 수행할수 있고 Anchore Enterprise 버전은 상용버전으로
대규모 팀을 위한 포괄적인 워크 플로우 및 감사를 수행하는 솔루션 입니다.
Anchore Engine은 다음과 같은 component들로 구성되어 있습니다.
- API service
- catalog service
- queuing service
- policy engine service
- kubernetes webhook service
실제 동작은 다음과 같은 행위를 기반으로 수행됩니다.
이미지를 가져와 -> 분석하고 -> 데이터베이스에 저장하고 -> 평가를 수행 -> 평가결과에 대한 알림 -> 반복
아래 링크들은 anchore 공식 문서들로 위 내용들을 좀더 상세히 알아볼수 있습니다.
- https://docs.anchore.com/current/docs/engine/general/
- https://docs.anchore.com/current/docs/engine/engine_installation/
- https://github.com/anchore/anchore-engine
Anchore Engine 설치
우리는 kubernetes 환경을 사용할 예정이기에 helm chart를 사용하여 배포를 진행해보도록 하겠습니다.
반갑게도 helm3를 지원하고 있고 helm3를 통한 배포예제도 제공되고 있으니 참고하여 배포를 진행합니다.
helm chart의 value 값을 변경하기 위해 아래와 같이 values.yaml template 파일을 가져옵니다.
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests$ helm fetch stable/anchore-engine
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests$ ll
total 60
drwxr-xr-x 2 jacob jacob 4096 3월 16 18:17 ./
drwxr-xr-x 9 jacob jacob 4096 3월 16 18:16 ../
-rw-r--r-- 1 jacob jacob 52937 3월 16 18:17 anchore-engine-1.4.2.tgz
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests$ tar xvzf anchore-engine-1.4.2.tgz
anchore-engine/Chart.yaml
anchore-engine/values.yaml
...
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests$ cd anchore-engine/
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ vim values.yaml
## OR
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests$ curl -O https://raw.githubusercontent.com/helm/charts/master/stable/anchore-engine/values.yaml
가져온 values.yaml 파일의 내용을 아래와 같이 수정합니다.
(개인적으로 필요한 정보만을 넣어준것이기에 추가적으로 변경이 필요한 부분은 확인하여 변경하시기를 권장합니다.)
...
#defaultAdminPassword: foobar
defaultAdminPassword: password
...
anchoreApi:
replicaCount: 1
# Set extra environment variables. These will be set on all api containers.
extraEnv: []
# - name: foo
# value: bar
# kubernetes service configuration for anchore external API
service:
#type: ClusterIP
type: LoadBalancer
port: 8228
이제 배포를 진행합니다.
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ k create ns anchore
namespace/anchore created
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ helm install anchore -f values.yaml stable/anchore-engine -n anchore
NAME: anchore
LAST DEPLOYED: Mon Mar 16 18:20:01 2020
NAMESPACE: anchore
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
To use Anchore Engine you need the URL, username, and password to access the API.
Anchore Engine can be accessed via port 8228 on the following DNS name from within the cluster:
anchore-anchore-engine-api.anchore.svc.cluster.local
Here are the steps to configure the anchore-cli (`pip install anchorecli`). Use these same values for direct API access as well.
To configure your anchore-cli run:
ANCHORE_CLI_USER=admin
ANCHORE_CLI_PASS=$(kubectl get secret --namespace anchore anchore-anchore-engine -o jsonpath="{.data.ANCHORE_ADMIN_PASSWORD}" | base64 --decode; echo)
Using the service endpoint from within the cluster you can use:
ANCHORE_CLI_URL=http://anchore-anchore-engine-api.anchore.svc.cluster.local:8228/v1/
To verify the service is up and running, you can run container for the Anchore Engine CLI:
kubectl run -i --tty anchore-cli --restart=Always --image anchore/engine-cli --env ANCHORE_CLI_USER=admin --env ANCHORE_CLI_PASS=${ANCHORE_CLI_PASS} --env ANCHORE_CLI_URL=http://anchore-anchore-engine-api.anchore.svc.cluster.local:8228/v1/
from within the container you can use 'anchore-cli' commands.
* NOTE: On first startup of anchore-engine, it performs a CVE data sync which may take several minutes to complete. During this time the system status will report 'partially_down' and any images added for analysis will stay in the 'not_analyzed' state.
Once the sync is complete, any queued images will be analyzed and the system status will change to 'all_up'.
Initial setup time can be >120sec for postgresql setup and readiness checks to pass for the services as indicated by pod state. You can check with:
kubectl get pods -l app=anchore-anchore-engine,component=api
A quick primer on using the Anchore Engine CLI follows. For more info see: https://github.com/anchore/anchore-engine/wiki/Getting-Started
View system status:
anchore-cli system status
Add an image to be analyzed:
anchore-cli image add <imageref>
List images and see the analysis status (not_analyzed initially):
anchore-cli image list
Once the image is analyzed you'll see status change to 'analyzed'. This may take some time on first execution with a new database because
the system must first do a CVE data sync which can take several minutes. Once complete, the image will transition to 'analyzing' state.
When the image reaches 'analyzed' state, you can view policy evaluation output with:
anchore-cli evaluate check <imageref>
List CVEs found in the image with:
anchore-cli image vuln <imageref> os
List OS packages found in the image with:
anchore-cli image content <imageref> os
List files found in the image with:
anchore-cli image content <imageref> files
anchore 설치후 동작하는데 약 5분의 시간이 소요되었습니다.
anchore document에는 약3분정도 소요된다고 했는데 시스템에 따라 다를수 있으니 최소 3분이상 대기가 필요할것으로 보입니다.
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ k get po -n anchore
NAME READY STATUS RESTARTS AGE
anchore-anchore-engine-analyzer-8659dccb4b-sdfpd 1/1 Running 0 5m8s
anchore-anchore-engine-api-658ff56945-5jgxc 1/1 Running 0 5m8s
anchore-anchore-engine-catalog-5786dd8986-dkdjn 1/1 Running 0 5m8s
anchore-anchore-engine-policy-6fcb868764-v5n48 1/1 Running 0 5m8s
anchore-anchore-engine-simplequeue-7689ff844f-rbkrw 1/1 Running 0 5m8s
anchore-postgresql-7d8f988b7-kdc4z 1/1 Running 0 5m6s
위와 같은 anchore engine의 각 구성요소들이 정상적으로 동작하는지를 확인하여 설치를 완료합니다.
또한 실제 외부 IP를 확인하여 해당 IP로 anchore가 정상적으로 running 하는지 확인해봅니다.
(loadbalancer type으로 생성하여 진행하였습니다.)
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ k get svc -n anchore
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
anchore-anchore-engine-api LoadBalancer 10.233.33.72 192.168.197.140 8228:32182/TCP 6m59s
anchore-anchore-engine-catalog ClusterIP 10.233.61.226 <none> 8082/TCP 6m58s
anchore-anchore-engine-policy ClusterIP 10.233.13.102 <none> 8087/TCP 6m59s
anchore-anchore-engine-simplequeue ClusterIP 10.233.10.236 <none> 8083/TCP 7m1s
anchore-postgresql ClusterIP 10.233.39.237 <none> 5432/TCP 6m58s
아래와 같이 api 호출에 대한 json 결과를 확인할수 있는 페이지가 확인되어집니다.
참고로 docker-compose를 이용하여 설치도 가능하니 참고하면 좋을 것 같습니다.
WARNING
UI는 Enterprise 버전에서만 가능합니다.
물론 UI가 꼭 필요하지는 않지만 좀더 UI를 통해 정보를 확인하고자할 경우, enterprise 라이센스 구매에 대해서도 고민해볼 필요는 있을 것 같습니다.
API 정보 확인
swagger UI를 통해 api spec을 확인해볼수 있습니다.
접속 경로는 v1/swagger.json으로 접속하면 됩니다.
http://192.168.197.140:8228/v1/swagger.json
WARNING
실제 v1/ui로 안내되고 있는데 해당 정보는 업데이트가 아직안된것으로 보여집니다.
anchore-cli 설치
실제 anchore 를 사용하기 위해서는 anchore-cli를 설치해서 사용해야 합니다.
하여 다음 링크를 참고하여 anchore-cli를 설치합니다.
필자는 ubuntu 환경이어서 아래와 같이 설치를 진행했습니다.
jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ . venv/bin/activate
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ pip install anchorecli
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting anchorecli
Downloading anchorecli-0.6.1.tar.gz (36 kB)
Requirement already satisfied: certifi==2019.11.28 in ./venv/lib/python2.7/site-packages (from anchorecli) (2019.11.28)
Collecting Click==7.0
Downloading Click-7.0-py2.py3-none-any.whl (81 kB)
|████████████████████████████████| 81 kB 260 kB/s
Requirement already satisfied: prettytable==0.7.2 in ./venv/lib/python2.7/site-packages (from anchorecli) (0.7.2)
...
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli
Usage: anchore-cli [OPTIONS] COMMAND [ARGS]...
Options:
...
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ cat ~/.bash_profile
export ANCHORE_CLI_URL=http://192.168.197.140:8228/v1
export ANCHORE_CLI_USER=admin
export ANCHORE_CLI_PASS=password
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image list
위와 같이 image list 를 출력해보았을때 아무 결과가 나오지 않으면 설치 및 인증이 정상적으로 된것이라 보면 됩니다.
anchore-cli 사용법
이제부터 anchore-cli를 사용하여 이미지를 추가하고 분석하는 작업을 수행해보도록 하겠습니다.
기본 사용법
우선 anchore document에서 소개되고 있는 debian image를 가져와 분석하는 과정을 수행해보도록 하겠습니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image add docker.io/library/debian:latest
Image Digest: sha256:121dd2a723be1c8aa8b116684d66157c93c801f2f5107b60287937e88c13ab89
Parent Digest: sha256:a63d0b2ecbd723da612abf0a8bdb594ee78f18f691d7dc652ac305a490c9b71a
Analysis Status: not_analyzed
Image Type: docker
Analyzed At: None
Image ID: 971452c943760ab769134f22db8d3381b09ea000a6c459fbfa3603bb99115f62
Dockerfile Mode: None
Distro: None
Distro Version: None
Size: None
Architecture: None
Layer Count: None
Full Tag: docker.io/library/debian:latest
Tag Detected At: 2020-03-16T07:58:44Z
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image list
Full Tag Image Digest Analysis Status
docker.io/library/debian:latest sha256:121dd2a723be1c8aa8b116684d66157c93c801f2f5107b60287937e88c13ab89 analyzing
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image wait docker.io/library/debian:latest
Status: analyzing
Waiting 5.0 seconds for next retry.
Image Digest: sha256:121dd2a723be1c8aa8b116684d66157c93c801f2f5107b60287937e88c13ab89
Parent Digest: sha256:a63d0b2ecbd723da612abf0a8bdb594ee78f18f691d7dc652ac305a490c9b71a
Analysis Status: analyzed
Image Type: docker
Analyzed At: 2020-03-16T07:59:27Z
Image ID: 971452c943760ab769134f22db8d3381b09ea000a6c459fbfa3603bb99115f62
Dockerfile Mode: Guessed
Distro: debian
Distro Version: 10
Size: 126607360
Architecture: amd64
Layer Count: 1
Full Tag: docker.io/library/debian:latest
Tag Detected At: 2020-03-16T07:58:44Z
아래와 같이 api service를 통해 업로드된 image 정보를 확인할 수 있습니다.
policy hub 사용
사전에 정의된 anchore 정책 번들의 저장소라는 개념으로 policy hub가 사용되어집니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli policy hub list
Name Description
anchore_security_only Single policy, single whitelist bundle for performing
security checks, including example blacklist known malicious
packages by name.
anchore_default_bundle Default policy bundle that comes installed with vanilla
anchore-engine deployments. Mixture of light vulnerability
checks, dockerfiles checks, and warning triggers for common
best practices.
anchore_cis_1.13.0_base Docker CIS 1.13.0 image content checks, from section 4 and
5. NOTE: some parameters (generally are named 'example...')
must be modified as they require site-specific settings
### https://github.com/anchore/hub/tree/master/sources/bundles
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli policy hub install anchore_cis_1.13.0_base
Policy ID: anchore_cis_1.13.0_base
Active: False
Source: local
Created: 2020-03-16T08:28:33Z
Updated: 2020-03-16T08:28:33Z
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli policy activate anchore_cis_1.13.0_base
Success: anchore_cis_1.13.0_base activated
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli policy list
Policy ID Active Created Updated
anchore_cis_1.13.0_base True 2020-03-17T01:34:06Z 2020-03-17T01:34:20Z
2c53a13c-1765-11e8-82ef-23527761d060 False 2020-03-16T09:25:06Z 2020-03-17T01:34:20Z
개인 repository에 있는 이미지를 실제 upload 및 scan해보도록 하겠습니다.
anchore-cli를 통해 이미지를 가져오고 분석하여 평가하는 과정을 아래 명령어들을 통해 수행해볼수 있습니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image add dubaek/samplejavaweb:latest
Image Digest: sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e
Parent Digest: sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e
Analysis Status: not_analyzed
Image Type: docker
Analyzed At: None
Image ID: 5fcdc5f418ee9d480cd8dc6f3f74938277614e4ac7a1f7176cf0a29818cef132
Dockerfile Mode: None
Distro: None
Distro Version: None
Size: None
Architecture: None
Layer Count: None
Full Tag: docker.io/dubaek/samplejavaweb:latest
Tag Detected At: 2020-03-17T01:35:18Z
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image wait dubaek/samplejavaweb:latest
Status: analyzing
Waiting 5.0 seconds for next retry.
Status: analyzing
Waiting 5.0 seconds for next retry.
Image Digest: sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e
Parent Digest: sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e
Analysis Status: analyzed
Image Type: docker
Analyzed At: 2020-03-17T01:38:17Z
Image ID: 5fcdc5f418ee9d480cd8dc6f3f74938277614e4ac7a1f7176cf0a29818cef132
Dockerfile Mode: Guessed
Distro: debian
Distro Version: 9
Size: 549058560
Architecture: amd64
Layer Count: 12
Full Tag: docker.io/dubaek/samplejavaweb:latest
Tag Detected At: 2020-03-17T01:35:18Z
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli evaluate check docker.io/dubaek/samplejavaweb:latest --detail
Image Digest: sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e
Full Tag: docker.io/dubaek/samplejavaweb:latest
Image ID: 5fcdc5f418ee9d480cd8dc6f3f74938277614e4ac7a1f7176cf0a29818cef132
Status: fail
Last Eval: 2020-03-17T01:39:11Z
Policy ID: anchore_cis_1.13.0_base
Final Action: stop
Final Action Reason: policy_evaluation
Gate Trigger Detail Status
vulnerabilities stale_feed_data The vulnerability feed for this image distro is older than MAXAGE (2) days stop
vulnerabilities vulnerability_data_unavailable Feed data unavailable, cannot perform CVE scan for distro: debian:9 stop
dockerfile exposed_ports Dockerfile exposes port (8080) which is not in policy file ALLOWEDPORTS list stop
dockerfile instruction Dockerfile directive 'ADD' check 'exists' matched against '' for line 'file:fdf0128645db4c8b990073dc4fe3fabad50411032c9aa4f86538d46e0e8f158f in /' warn
dockerfile instruction Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check stop
dockerfile instruction Dockerfile directive 'FROM' check 'not_in' matched against 'example_trusted_base1,example_trusted_base2' for line 'scratch' stop
...
파일, 운영체제, 패키지, npm, gem 등 docker image의 모든 산출물에 대한 content를 분석하고 이에 대한 결과를 확인할 수 있습니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image content docker.io/dubaek/samplejavaweb:latest
os: available
files: available
npm: available
gem: available
python: available
java: available
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image content docker.io/dubaek/samplejavaweb:latest python
Package Version Location
Python 2.7.13 /usr/lib/python2.7/lib-dynload
argparse 1.2.1 /usr/lib/python2.7
bzr 2.8.0.dev1 /usr/lib/python2.7/dist-packages
configobj 5.0.6 /usr/lib/python2.7/dist-packages
mercurial 4.0 /usr/lib/python2.7/dist-packages
six 1.10.0 /usr/lib/python2.7/dist-packages
wsgiref 0.1.2 /usr/lib/python2.7
아래 명령을 이용하여 컨테이너 이미지의 발견된 취약점목록을 확인할 수 있습니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image vuln docker.io/library/debian:latest os
Vulnerability ID Package Severity Fix CVE Refs Vulnerability URL
CVE-2005-2541 tar-1.30+dfsg-6 Negligible None https://security-tracker.debian.org/tracker/CVE-2005-2541
CVE-2007-5686 login-1:4.5-1.1 Negligible None https://security-tracker.debian.org/tracker/CVE-2007-5686
CVE-2007-5686 passwd-1:4.5-1.1 Negligible None https://security-tracker.debian.org/tracker/CVE-2007-5686
CVE-2010-4051 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2010-4051
CVE-2010-4051 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2010-4051
CVE-2010-4052 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2010-4052
CVE-2010-4052 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2010-4052
CVE-2010-4756 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2010-4756
CVE-2010-4756 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2010-4756
CVE-2011-3374 apt-1.8.2 Negligible None https://security-tracker.debian.org/tracker/CVE-2011-3374
CVE-2011-3374 libapt-pkg5.0-1.8.2 Negligible None https://security-tracker.debian.org/tracker/CVE-2011-3374
CVE-2011-3389 libgnutls30-3.6.7-4+deb10u2 Negligible None https://security-tracker.debian.org/tracker/CVE-2011-3389
CVE-2011-4116 perl-base-5.28.1-6 Negligible None https://security-tracker.debian.org/tracker/CVE-2011-4116
CVE-2012-2663 libxtables12-1.8.2-4 Negligible None https://security-tracker.debian.org/tracker/CVE-2012-2663
CVE-2013-4235 login-1:4.5-1.1 Negligible None https://security-tracker.debian.org/tracker/CVE-2013-4235
CVE-2013-4235 passwd-1:4.5-1.1 Negligible None https://security-tracker.debian.org/tracker/CVE-2013-4235
CVE-2013-4392 libsystemd0-241-7~deb10u3 Negligible None https://security-tracker.debian.org/tracker/CVE-2013-4392
CVE-2013-4392 libudev1-241-7~deb10u3 Negligible None https://security-tracker.debian.org/tracker/CVE-2013-4392
CVE-2017-11164 libpcre3-2:8.39-12 Negligible None https://security-tracker.debian.org/tracker/CVE-2017-11164
CVE-2017-16231 libpcre3-2:8.39-12 Negligible None https://security-tracker.debian.org/tracker/CVE-2017-16231
CVE-2017-18018 coreutils-8.30-3 Negligible None https://security-tracker.debian.org/tracker/CVE-2017-18018
CVE-2017-7245 libpcre3-2:8.39-12 Negligible None https://security-tracker.debian.org/tracker/CVE-2017-7245
CVE-2017-7246 libpcre3-2:8.39-12 Negligible None https://security-tracker.debian.org/tracker/CVE-2017-7246
CVE-2018-1000654 libtasn1-6-4.13-3 Negligible None https://security-tracker.debian.org/tracker/CVE-2018-1000654
CVE-2018-20796 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2018-20796
CVE-2018-20796 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2018-20796
CVE-2018-6829 libgcrypt20-1.8.4-5 Negligible None https://security-tracker.debian.org/tracker/CVE-2018-6829
CVE-2019-1010022 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010022
CVE-2019-1010022 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010022
CVE-2019-1010023 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010023
CVE-2019-1010023 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010023
CVE-2019-1010024 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010024
CVE-2019-1010024 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010024
CVE-2019-1010025 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010025
CVE-2019-1010025 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-1010025
CVE-2019-11360 libxtables12-1.8.2-4 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-11360
CVE-2019-19882 login-1:4.5-1.1 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-19882
CVE-2019-19882 passwd-1:4.5-1.1 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-19882
CVE-2019-9192 libc-bin-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-9192
CVE-2019-9192 libc6-2.28-10 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-9192
CVE-2019-9893 libseccomp2-2.3.3-4 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-9893
CVE-2019-9923 tar-1.30+dfsg-6 Negligible None https://security-tracker.debian.org/tracker/CVE-2019-9923
CVE-2020-1712 libsystemd0-241-7~deb10u3 Unknown None https://security-tracker.debian.org/tracker/CVE-2020-1712
CVE-2020-1712 libudev1-241-7~deb10u3 Unknown None https://security-tracker.debian.org/tracker/CVE-2020-1712
WARNING
system feeds sync가 되어 있어야 취약점 결과가 출력될수 있습니다.
system feeds list에 출력결과가 없을 경우 sync를 수행한후 진행하는것을 권장합니다.
앞서 명령들은 컨테이너 이미지의 tag 하나하나를 직접 지정하여 사용하는 방식이었고
아래는 저장소의 특정 컨테이너 이미지의 모든 tag의 변화를 감지하는 방식입니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli repo add docker.io/dubaek/samplejavaweb
Repository Watched TagCount
docker.io/dubaek/samplejavaweb True 1
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image list
Full Tag Image Digest Analysis Status
192.168.197.130:5000/stlapp:1.0 sha256:5b307c4254ec86e8043a42037b254ffb3ff5cccab5f6c5002fceb885443579c8 analyzed
docker.io/dubaek/samplejavaweb:latest sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e analyzed
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ docker tag dubaek/samplejavaweb:latest dubaek/samplejavaweb:1.0
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ docker push dubaek/samplejavaweb:1.0
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image list
Full Tag Image Digest Analysis Status
192.168.197.130:5000/stlapp:1.0 sha256:5b307c4254ec86e8043a42037b254ffb3ff5cccab5f6c5002fceb885443579c8 analyzed
docker.io/dubaek/samplejavaweb:1.0 sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e analyzed
docker.io/dubaek/samplejavaweb:latest sha256:164b91f591beec2f6452f222024e825a1b845686f41796ab18f9ff653c91926e analyzed
실제로 특정 이미지(samplejavaweb)에 tag를 추가하여 push한 결과 cycle time(60초)에 기반하여
새로 push된 tag에 맞는 컨테이너 이미지를 가져옴을 확인할수 있습니다.
image 삭제
image 삭제는 관련된 subscription이 inactive 상태가 되어야 삭제가 가능합니다.
subscription active 상태가 true로 남아 있다면 다음과 같이 에러가 나게 됩니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image del docker.io/debian:latest
Error: cannot delete image that is the latest of its tags, and has active subscription
HTTP Code: 409
Detail: {u'error_codes': []}
하여 아래와 같이 관련된 subscription을 inactive 로 변경하여 삭제를 진행합니다.
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli subscription list
Tag Subscription Type Active
192.168.197.130:5000/stlapp:1.0 analysis_update True
192.168.197.130:5000/stlapp:1.0 policy_eval False
192.168.197.130:5000/stlapp:1.0 tag_update True
192.168.197.130:5000/stlapp:1.0 vuln_update False
docker.io/debian:latest analysis_update True
docker.io/debian:latest policy_eval False
docker.io/debian:latest tag_update True
docker.io/debian:latest vuln_update False
docker.io/library/debian:latest analysis_update True
docker.io/library/debian:latest policy_eval False
docker.io/library/debian:latest tag_update True
docker.io/library/debian:latest vuln_update False
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli subscription deactivate analysis_update docker.io/debian:latest
Success
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli subscription deactivate tag_update docker.io/debian:latest
Success
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli subscription list
Tag Subscription Type Active
192.168.197.130:5000/stlapp:1.0 analysis_update True
192.168.197.130:5000/stlapp:1.0 policy_eval False
192.168.197.130:5000/stlapp:1.0 tag_update True
192.168.197.130:5000/stlapp:1.0 vuln_update False
docker.io/debian:latest analysis_update False
docker.io/debian:latest policy_eval False
docker.io/debian:latest tag_update False
docker.io/debian:latest vuln_update False
docker.io/library/debian:latest analysis_update False
docker.io/library/debian:latest policy_eval False
docker.io/library/debian:latest tag_update False
docker.io/library/debian:latest vuln_update False
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image del docker.io/debian:latest
Success
## 혹은 --force option을 통한 강제 삭제
(venv) jacob@jacob-laptop:~/workspace/openlabs/openlabs-manifests/anchore-engine$ anchore-cli image del docker.io/library/debian:latest --force
Success
NOTE
참고로 anchore engine내부에서 사용되는 component로는 skopeo 입니다.
anchore-cli를 사용하는 jenkins plugin
이제부터는 jenkins를 통해 pipeline 상에서 자동으로 image scanning을 수행하고
그결과를 확인할 수 있는 방법에 대하여 알아보도록 하겠습니다.
workflow는 다음과 같습니다.
anchore를 jenkins에서 사용하기 위해서는 plugin을 설치해야 합니다.
설치될 plugin은 다음과 같습니다.
plugin설치가 완료된후 jenkins의 configuration system 메뉴에서 Anchore Container Image Scanner 설정을 추가합니다.
해당 정보는 앞서 anchore-cli에서 export 했던 정보를 그대로 입력하면 됩니다.
이후 kubernetes 환경에서 jenkins를 사용중이기에 scripted pipeline으로 작성을 진행합니다.
kubernetes 환경의 jenkins에서는 docker image를 사용할수 있고 anchore를 사용하기 위해서는
(Jenkins pipeline을 kubernetes에서 사용하는 방법은 https://tech.osci.kr/2019/11/21/86026733/ 블로그 참고)
다음 anchore-cli container image를 사용합니다.
- https://hub.docker.com/r/anchore/engine-cli 참고로 찾다보면 anchore/cli와 같은 이전 버전의 cli image가 있는데 이를 사용하면 안되고
API를 사용해 engine과 통신하여 scanning을 수행하는 방식으로 변경되었고 그에 맞는 이미지를 사용해야 합니다.
이제 jenkins pipeline을 작성해보도록 하겠습니다.
아래는 간단한 예제입니다.
stage('check security') {
// container('anchore-cli') {
// def imageLine = 'debian:latest'
// writeFile file: 'anchore_images', text: imageLine
// anchore name: 'anchore_images'
// }
container('anchore-cli') {
def imageLine = '192.168.197.130:5000/stlapp:1.0'
writeFile file: 'anchore_images', text: imageLine
anchore name: 'anchore_images'
}
}
NOTE
jenkins pipeline에 의해 실행된 anchore 결과 중 image 정보를 확인해볼수 있습니다.
또한 jenkinsfile example은 다음과 같습니다.
실제 jenkins pipeline에 의해 실행된 결과는 다음과 같이 출력됩니다.
Jenkins plugin을 통해 다음과 같은 파일들이 생성됨을 확인할 수 있으며 각 파일은 json 형태로 생성됩니다.
Anchore Policy에 기반한 평가 결과에 대해서도 Jenkins UI상에서 확인해볼수 있습니다.
Dockerfile의 HEALTHCHECK 지시어 사용에대한 권장안도 출력되었고 CVE를 기반으로 하기에 CVE의 취약점에 대한 경고도
함께 출력됨을 확인할 수 있습니다.