Перейти к содержанию

Интеграция с Jenkins

Jenkins Master Node

Используется сборка Jenkins от Blue Ocean, которая запускается в rootless контейнере docker.

Установлены следующие плагины.

Нажмите, чтобы просмотреть список плагинов.
ace-editor:latest
ant:latest
antisamy-markup-formatter:latest
apache-httpcomponents-client-4-api:latest
authentication-tokens:latest
bitbucket:latest
blueocean:latest
blueocean-autofavorite:latest
blueocean-bitbucket-pipeline:latest
blueocean-commons:latest
blueocean-config:latest
blueocean-core-js:latest
blueocean-dashboard:latest
blueocean-display-url:latest
blueocean-events:latest
blueocean-github-pipeline:latest
blueocean-git-pipeline:latest
blueocean-i18n:latest
blueocean-jira:latest
blueocean-jwt:latest
blueocean-personalization:latest
blueocean-pipeline-api-impl:latest
blueocean-pipeline-editor:latest
blueocean-pipeline-scm-api:latest
blueocean-rest:latest
blueocean-rest-impl:latest
blueocean-web:latest
bouncycastle-api:latest
branch-api:latest
build-pipeline-plugin:latest
build-timeout:latest
build-token-root:latest
build-token-trigger:latest
checkmarx:latest
cloudbees-bitbucket-branch-source:latest
cloudbees-folder:latest
command-launcher:latest
conditional-buildstep:latest
configuration-as-code:latest
copy-data-to-workspace-plugin:latest
credentials:latest
credentials-binding:latest
dependency-check-jenkins-plugin:latest
dependency-track:latest
display-url-api:latest
docker-commons:latest
docker-workflow:latest
durable-task:latest
email-ext:latest
external-monitor-job:latest
favorite:latest
generic-webhook-trigger:latest
git:latest
git-client:latest
github:latest
github-api:latest
github-branch-source:latest
gitlab-plugin:latest
git-server:latest
gradle:latest
handlebars:latest
handy-uri-templates-2-api:latest
htmlpublisher:latest
jackson2-api:latest
javadoc:latest
jdk-tool:latest
jenkins-design-language:latest
jira:latest
job-fan-in:latest
jquery:latest
jquery-detached:latest
jsch:latest
junit:latest
ldap:latest
lockable-resources:latest
mailer:latest
mapdb-api:latest
matrix-auth:latest
matrix-project:latest
maven-plugin:latest
mercurial:latest
metrics:latest
momentjs:latest
nested-view:latest
nexus-jenkins-plugin:latest
nuget:latest
pam-auth:latest
parameterized-trigger:latest
permissive-script-security:latest
pipeline-build-step:latest
pipeline-graph-analysis:latest
pipeline-input-step:latest
pipeline-milestone-step:latest
pipeline-model-api:latest
pipeline-model-declarative-agent:latest
pipeline-model-definition:latest
pipeline-model-extensions:latest
pipeline-rest-api:latest
pipeline-stage-step:latest
pipeline-stage-tags-metadata:latest
pipeline-stage-view:latest
plain-credentials:latest
pubsub-light:latest
resource-disposer:latest
run-condition:latest
scm-api:latest
script-security:latest
sloccount:latest
sse-gateway:latest
ssh-agent:latest
ssh-credentials:latest
ssh-slaves:latest
stash-pullrequest-builder:latest
structs:latest
subversion:latest
text-finder:latest
timestamper:latest
token-macro:latest
trilead-api:latest
variant:latest
view-job-filters:latest
windows-slaves:latest
workflow-aggregator:latest
workflow-api:latest
workflow-basic-steps:latest
workflow-cps:latest
workflow-cps-global-lib:latest
workflow-durable-task-step:latest
workflow-job:latest
workflow-multibranch:latest
workflow-scm-step:latest
workflow-step-api:latest
workflow-support:latest
ws-cleanup:latest

При запуске выполняются первоначальные настройки, позволяющие:

  • определить пользователя с ролью Администратор и установить пароль для его учетной записи;
  • указать базовый URL Jenkins;
  • выполнить импорт в систему всех SSL-сертификатов в качестве доверенных;
  • определить некоторые переменные окружения до запуска инсталляции Jenkins.

Jenkins Slave Node

Используется базовый образ Ubuntu, который запускается в rootless контейнере. Дополнительно установлены утилиты и сборщики, необходимые для проведения сканирований. Возможна работа со следующими утилитами: mono, cdxgen, nuget, npm, java, maven и gradel. При подключении ноды к Jenkins необходимо указать следующие метки: all super jenkins-slave-node-all maven mono npm nodejs docker java python pypi cdxgen.

Настройка

  1. Для запуска используйте следующий docker-compose.yaml.

    version: '3.2'
    
    services:
      jenkins:
        image: docker.swordfishsecurity.com/sfs-jenkins:${jenkins_version}
        container_name: jenkins
        user: 1000:1000
        ports:
          - 8080:8080
        environment:
          - JENKINS_URL=http://jenkins.company.com
          - JENKINS_ADMIN_USER=admin
          - JENKINS_ADMIN_PASSWORD=<some-password>
          - DOCKER_HOST=tcp://docker-in-docker:2375
          - gradle_dependency_task=dependencies
          - fetch_license=true
          - maven_home=/opt/maven
          - gradle_home=/opt/gradle
          - github_token=
          - gradle_args=
          - mvn_args=
          - cdxgen_npm_url=https://registry.npmjs.org/
          - cdxgen_maven_central_url=https://repo1.maven.org/maven2/
          - cdxgen_android_maven=https://maven.google.com/
          - cdxgen_pypi_url=https://pypi.org/pypi/
          - cdxgen_go_url=https://pkg.go.dev/
          - cdxgen_nuget_url=https://api.nuget.org/v3/registration3/
        networks:
          - network
        volumes:
          - ./jenkins_home:/var/jenkins_home:z
          - ./fortify/projects:/fortify/projects
          - /etc/localtime:/etc/localtime
          - /etc/timezone:/etc/timezone
          - ./certs:/tmp/certs
        cap_add:
          - SYS_ADMIN
        pids_limit: 100
        security_opt:
          - no-new-privileges
        restart: on-failure:5
        cpu_shares: 1024
        deploy:
          resources:
            limits:
              memory: 2048M
    
      node-all:
        image: docker.swordfishsecurity.com/sfs-jenkins-slave-all:${slave_all_version}
        container_name: node-all
        networks:
          - network
        user: 2000:2000
        environment:
          - LANG=en_US.utf-8
          - DOCKER_HOST=tcp://docker-in-docker:2375
        volumes:
          - /sys/fs/cgroup:/sys/fs/cgroup:ro
          - ./ssh-pub-keys-all:/home/ubuntu/.ssh
          - ./jenkins-slave-all:/home/ubuntu/jenkins-slave
          - /etc/localtime:/etc/localtime
          - /etc/timezone:/etc/timezone
          - ./certs:/tmp/certs
        restart: on-failure:5
        cpu_shares: 2048
        deploy:
          resources:
            limits:
              memory: 3072M
    
      docker-in-docker:
        image: docker:19.03.3-dind
        container_name: docker-in-docker
        privileged: true
        volumes:
          - ./docker-certs:/etc/docker/certs.d
        environment:
          - DOCKER_TLS_CERTDIR=
        networks:
          - network
        pids_limit: 100
        security_opt:
          - no-new-privileges
        restart: on-failure:5
        cpu_shares: 512
        deploy:
          resources:
            limits:
              memory: 512M
    
    networks:
      network:
        driver: "bridge"
        driver_opts:
          com.docker.network.driver.mtu: 1450
    

    Примечание

    Для корректной работы отдельных утилит и инструментов, например cdxgen, могут потребоваться переменные окружения, которые указываются в файле docker-compose.yaml, см. строки 22–27 выше. Более подробная информация о переменных окружения приведена здесь.

    Примечание

    Для автоматического конфигурирования URL Jenkins и учетных данных Администратора используются переменные окружения: JENKINS_URL, JENKINS_ADMIN_USER, JENKINS_PASSADMIN_PASSWORD. При запуске Jenkins соответствующие параметры берутся из перечисленных переменных. Если после запуска необходимо скрыть учетные данные Администратора, следует убрать переменные JENKINS_ADMIN_USER и JENKINS_ADMIN_PASSPASSWORD из docker-compose.yaml — текущие username/password будут сохранены в Jenkins и, используя их, можно войти в систему.

    Список используемых переменных окружения

    Переменная Описание
    JENKINS_URL URL Jenkins master ноды
    JENKINS_ADMIN_USER Имя Администратора в Jenkins
    JENKINS_ADMIN_PASSWORD Пароль Администратора в Jenkins
    DOCKER_HOST URL демона Docker
    gradle_dependency_task Имя задачи по умолчанию для скачивания пакетов для утилиты cdxgen
    fetch_license Скачивание информации о лицензии из репозиториев для cdxgen (только для npm и golang) (необязательный параметр, в случае ненадобности — удалить)
    maven_home Домашняя папка maven
    gradle_home Домашняя папка gradle
    github_token Токен Github (необязательный параметр, в случае ненадобности — удалить)
    gradle_args Аргументы запуска утилиты gradle (необязательный параметр, в случае ненадобности — удалить)
    mvn_args Аргументы запуска утилиты mvn (необязательный параметр, в случае ненадобности — удалить)
    cdxgen_npm_url URL репозитория npm для утилиты cdxgen
    cdxgen_maven_central_url URL репозитория maven для утилиты cdxgen
    cdxgen_android_maven URL репозитория Android для утилиты cdxgen
    cdxgen_pypi_url URL репозитория PyPi для утилиты cdxgen
    cdxgen_go_url URL репозитория Go для утилиты cdxgen
    cdxgen_nuget_url URL репозитория nuget для утилиты cdxgen
  2. В директории, где расположен файл docker-compose.yaml, создайте файл .env.

    touch .env
    

    И укажите в нем версии для Jenkins и slave-all образов.

    jenkins_version=2.0
    slave_all_version=2.0
    
  3. Для подключения к slave ноде по SSH создайте директорию ssh-pub-keys-all и сохраните в ней файл authorized_keys, содержащий публичный ключ. Приватный ключ добавляется в Jenkins, см. раздел «Подключение нод в Jenkins».

  4. Большинство утилит считают самоподписанные сертификаты невалидными — можно столкнуться с проблемами при работе по протоколу HTTPS. Чтобы избежать этого, необходимо добавить сертификаты как доверенные. Перенесите все файлы с расширением .crt в папку certs и после запуска они будут автоматически добавлены в систему как доверенные. Если файлов с расширением .crt нет, но есть сертификаты другого типа от того же домена, их можно сконвертировать следующим образом.

    openssl x509 -inform DER -in certificate.cer -out certificate.crt
    
    # Если возникает ошибка, необходимо выполнить следующую команду.
    
    openssl x509 -inform PEM -in certificate.cer -out certificate.crt
    
    openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.crt
    
    # Потребуется ввод пароля, с использованием которого был зашифрован сертификат.
    

    Если есть необходимость добавить доверенный сертификат для docker, необходимо создать в папке с файлом docker-compose.yaml директорию docker-certs/<repo>, где <repo> — container registry, который указывается при логине, например, если необходимо выполнить вход с помощью команды docker login gitlab.example.com, то необходмио создать директорию docker-certs/gitlab.example.com и сохранить .crt сертификат в ней.

  5. Под инсталляцию рекомендуется выделять отдельную директорию, например /opt/jenkins. При необходимости использования Fortify в Jenkins как slave ноду нужно добавить в docker-compose.yaml следующий код. Предварительно необходимо создать файл с лицензией для Fortify по пути license/fortify.license.

    fortify-node:
      image: docker.swordfishsecurity.com/sfs-jenkins-slave-fortify:latest
      container_name: node-fortify
      user: 2000:2000
      networks:
        - network
      restart: always
      environment:
        - LANG=en_US.utf-8
        - "JAVA_OPTS=-DLANG=en_US.UTF-8"
      volumes:
        - ./ssh-pub-keys-all:/home/ubuntu/.ssh
        - ./jenkins-slave-fortify:/home/ubuntu/jenkins-slave
        - ./fortify/projects_fortify:/fortify/projects
        - ./license/fortify.license:/opt/Fortify/Fortify_SCA_and_Apps_21.1.1/fortify.license
    
  6. При необходимости использования reverse proxy для настройки защищённого SSL-соединения необходимо добавить в docker-compose.yaml следующие строки.

    nginx:
      image: docker.swordfishsecurity.com/sfs-nginx:latest
      container_name: nginx
      networks:
        - net-hub
      volumes:
        - ./nginx:/etc/nginx/conf.d:ro
        - ./ssl:/etc/ssl/certs/ssl-cert:ro
      restart: always
      ports:
        - 80:80/tcp
        - 443:443/tcp
    

    Далее необходимо создать директории nginx и ssl (команду выполнять из папки, где установлен Jenkins).

    mkdir nginx
    mkdir ssl
    

    В директории nginx необходимо создать файл web.conf со следующим содержимым.

    server {
        listen 80;
        server_name localhost;
        ignore_invalid_headers off;
        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;
        client_max_body_size       100m;
    
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
    
            proxy_pass http://jenkins:8080;
    
        }
        listen 443 ssl;
            ssl_certificate /etc/ssl/certs/ssl-cert/fullchain1.pem;
            ssl_certificate_key /etc/ssl/certs/ssl-cert/privkey1.pem;
    
            if ($scheme != "https") {
                return 301 https://$host$request_uri;
            }
    
    }
    

    В директории ssl необходимо создать 2 файла fullchain1.pem и privkey1.pem с сертификатом и приватным ключом соответственно.

  7. Поскольку контейнеры запускаются от имени непривилегированного пользователя, необходимо до запуска назначить необходимые права владельца и группу на директории, которые импортируются в контейнеры.

    Создайте папки в директории с файлом docker-compose.yaml.

    mkdir jenkins_home
    mkdir jenkins-slave-all
    mkdir ssh-pub-keys-all
    mkdir certs
    mkdir docker-certs
    mkdir fortify
    

    Назначьте группу и владельца для них.

    sudo chown 1000:1000 -R jenkins_home
    sudo chown 2000:2000 -R fortify
    sudo chown 2000:2000 -R jenkins-slave-all
    sudo chmod 600 ssh-pub-keys-all/authorized_keys # команду выполнять после того как был сохранён файл authorized_keys с содержанием публичного ключа
    sudo chown 2000:2000 -R ssh-pub-keys-all
    sudo chmod 755 -R certs
    sudo chmod 440 -R certs/* # команду выполнять после того как были импортированы все сертификаты в директорию
    sudo chown 1000:2000 -R certs/* # команду выполнять после того как были импортированы все сертификаты в директорию
    

Запуск

Запуск осуществляется с помощью следующей команды (из директории с файлом docker-compose.yaml).

docker login docker.swordfishsecurity.com -u <user> -p <password>
docker-compose up -d

После запуска Jenkins будет доступен на порту 8080.

Подключение нод в Jenkins

  1. Перед добавлением slave ноды необходимо добавить приватный SSH-ключ в хранилище секретов Jenkins Manage Jenkins Manage Credentials.

    Перейдите в Jenkins (поле Store) Global credentials Add Credentials и добавьте приватный ключ.

  2. Добавьте новый узел Manage Jenkins Manage Nodes and Clouds New Node, укажите название ноды и нажмите OK.

  3. В меню настроек укажите следующие параметры и нажмите Save.

    Параметр Значение
    Remote root directory /home/ubuntu/jenkins-slave
    Labels all super jenkins-slave-node-all maven mono npm nodejs docker java python pypi cdxgen
    Host node-all
  4. Укажите для slave ноды порт 2022 (Advanced Port).

  5. Укажите переменные окружения.

    Переменная Значение
    LANG en_US.UTF-8
    PATH ${PATH}:/opt/gradle/gradle-6.4.1/bin

При успешном добавлении статус ноды изменится на In Sync.

Важно!

При интеграции AppSec.Hub и Jenkins некоторые сканирования могут заканчиваться неуспешно, если не дать разрешение на исполнение Groovy-скриптам, которые появляются в Jenkins (Manage Jenkins In-process Script Approval).

Обновление Jenkins до версии 2.0

  1. Остановите Jenkins (команда выполняется из директории, где располагается файл docker-compose.yaml).

    docker-compose down
    
  2. В этой же директории в файле .env укажите следующие переменные (если такой файл отсутствует, его необходимо создать).

    jenkins_version=2.0
    slave_all_version=2.0
    
  3. Замените файл docker-compose.yaml приведенным в разделе «Настройка».

  4. Создайте директории, которые передаются в контейнеры, и задайте пользователя и группу.

    mkdir jenkins_home
    mkdir jenkins-slave-all
    mkdir ssh-pub-keys-all
    mkdir certs
    mkdir docker-certs
    mkdir fortify
    
    sudo chown 1000:1000 -R jenkins_home
    sudo chown 2000:2000 -R fortify
    sudo chown 2000:2000 -R jenkins-slave-all
    sudo chmod 600 ssh-pub-keys-all/authorized_keys # команду выполнять после того как был сохранён файл authorized_keys с содержанием публичного ключа
    sudo chown 2000:2000 -R ssh-pub-keys-all
    sudo chmod 755 -R certs
    sudo chmod 440 -R certs/* # команду выполнять после того как были импортированы все сертификаты в директорию
    sudo chown 1000:2000 -R certs/* # команду выполнять после того как были импортированы все сертификаты в директорию
    

    Примечание

    После обновления Jenkins до актуальной версии могут появиться ошибки зависимостей плагинов.

    Для их устранения необходимо из директории jenkins_home удалить папку plugins.

    rm -rf jenkins_home/plugins
    

    После удаления в контейнере будет создана новая директория с плагинами, совместимыми с актуальной версией Jenkins.

  5. Запустите Jenkins.

    docker-compose up -d
    

Важно

После полной инициализации Jenkins возникнет ожидаемая ошибка подключения Jenkins master к slave ноде. Связано это с тем, что был изменён порт SSH-сервера на slave ноде, пользователь и корневая директория для Jenkins. Для решения проблемы необходимо указать параметры из раздела «Подключение нод в Jenkins» в настройках подключения slave-all ноды и после переподключения нода станет доступна.

К началу