“앤코어”라고 불리우는 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 공식 문서들로 위 내용들을 좀더 상세히 알아볼수 있습니다.

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의 취약점에 대한 경고도
함께 출력됨을 확인할 수 있습니다.

참고사이트

오픈소스컨설팅의 마스코트, 열린이입니다! :)

Leave a Reply

Your email address will not be published. Required fields are marked *