Использование программного компонента#
Оглавление#
Сборка составного дистрибутива#
Использование составных дистрибутивов рекомендуется с целью:
Ускорения сборки в случае изменения конфигураций;
Уменьшения расхода места в Хранилище дистрибутивов;
Возможности использовать для разных сегментов одну кодовую базу с разными конфигурациями.
Артефакты составного дистрибутива#
Бинарные файлы - собранные приложения для дистрибутива.
Конфигурации - конфигурация дистрибутива. В данном артефакте прописана зависимость на бинарные (исполняемые) файлы.
Архивация в ZIP конечного дистрибутива производится через указание маски включаемых папок/файлов в стиле Ant. По умолчанию, в дистрибутив попадает только содержимое папки
package
Сборка исполняемого файла#
Для того чтобы собрать исполняемый файл, необходимо:
Создать отдельный файл pipeline.yml (отдельный файл или отдельный репозиторий с этим файлом);
В нем включить расширение std5Binaries:
extensions: - std5BinariesЗапустить Jenkins job сборки, указав с помощью параметров расположение файла конфигурации (
CONFIG_REPO/CONFIG_FILE/CONFIG_BRANCH/CONFIG_DIR);Отметить версию, с которой был выложен исполняемый файл, она потребуется для сборки конфигураций;
Сборка конфигураций#
Аналогично пункту 1 раздела «Сборка исполняемого файла».
В файле pipeline.yml добавить зависимость (дистрибутив, собранный согласно разделу «Сборка исполняемого файла») в профиле binaries:
profiles: binaries: - groupId: my.group.id # groupId из сборки binaries artifactId: my-artifact-bin # artifactId из сборки binaries version: D-01.004.03-453 # В данном случае использована версия дистрибутива, указанная в шаге 4 сборки binary type: zip classifier: distribВ файле pipeline.yml добавить расширение std5Configuration
extensions:
- std5Configuration
аналогично пункту 3 раздела «Сборка исполняемого файла».
В одном из начальных этапов сборки будет скачана зависимость из профиля
binaries.В pom.xml дистрибутива появятся все профили со всеми зависимостями, описанные в разделе
profiles
Ограничения#
При сборке исполняемых файлов из дистрибутива исключаются все конфигурации.
При сборке конфигураций из дистрибутива исключаются все исполняемые файлы (pl, bh и пр.).
Загрузка логических моделей данных (LDM) при сборке дистрибутива#
Для того чтобы при сборке дистрибутива выполнялась отправка логических моделей данных в сервис META, необходимо:
Разработать логические модели данных, содержащие ПДн, БТ, ДПК в формате JSON в соответствии с требованиями Разработки логических моделей данных АС;
Разместить модели в директории dataModel репозитория конфигурации проекта;
Зарегистрировать ТУЗ с правами загрузки моделей в META;
Выяснить код компонента используемого приложения в ARIS;
Добавить настройки для работы с сервисом МЕТА в файл pipeline.yml.
При размещении моделей в директории dataModel необходимо соблюдать правила именования:
model-pd.json - имя файла для модели ПДн;
model-bs.json - имя файла для модели БТ;
model-pcidss.json - имя файла для модели ДПК.
При разработке логических моделей данных необходимо соблюдать уникальность имени и кода модели.
Рекомендации по заполнению полей code и name (замените CI00000000 на КЭ вашего приложения):
"name": "CI00000000 Логическая модель данных PD",
"code": "CI00000000_LDM_PD",
"name": "CI00000000 Логическая модель данных BS",
"code": "CI00000000_LDM_BS",
"name": "CI00000000 Логическая модель данных PCI_DSS",
"code": "CI00000000_LDM_PCI_DSS",
Настройка динамических параметров#
Для получения необходимых параметров сборки при установке в OpenShift предусмотрены placeholders вида ${build: <parameter>}, значения которых будут проставлены в процессе выполнения Pipeline:
jenkins_env.fp_artifact_version - версия текущей сборки. Пример шаблона:
${build: jenkins_env.fp_artifact_version }jenkins_env.
<image-name>.fp_image_hash - хэш сумма, получившегося при сборке образа приложения, где<image-name>- название deployment unit. Пример шаблона:image:https://nexus3.<...>.ru/efs/ci00428440_efs/ci01947988_integration_routing/ufs-routing@${build: jenkins_env.deployment_unit_folder.fp_image_hash }
При использовании данного функционала необходимо исключить символ -
.- в названии deployment unit директории (<image-name>)
Использование sha-суммы обусловлено требованиями безопасности и новым стандартом формирования дистрибутива ОСЕ.
Обратите внимание, что в отличие от версии, sha-сумма отделяется от имени образа не двоеточием
:, а символом@. Таким образом поле image имеет формат:https://registry_host/image_url@${build: jenkins_env.fp_image_hash }
Данный placeholder необходимо использовать только в поле image, которое соответствует ВАШЕМУ образу. В sidecar и остальных полях файла менять ничего не нужно!
Значения следующих placeholders вида ${build: <parameter>} проставляются из вашего pipeline.yml:
fp.groupId, fp.artifactId, fp.version - groupId, artifactId, version - координаты дистрибутива в Nexus. Пример шаблона:
${build: fp.version}profiles.binaries.groupId, profiles.binaries.artifactId, profiles.binaries.version - аналогично - координаты бинарного артефакта, если текущий является конфигурацией. Пример шаблона:
${build: profiles.binaries.groupId}
Для определения значений переменных окружения среды необходимо в шаблонах использовать placeholders вида ${build: lookup('env', '<env_key>') }. Пример шаблона: ${build: lookup('env', 'BINARIES_VERSION') }, ${build: lookup('env', 'VERSION', default='1.0.0') }
Обратите внимание, переопределены placeholders для блока -
${build block: <block>}
Обратите внимание, что замена placeholders производится во всех текстовых (не бинарных) файлах рекурсивно относительно директории
package/conf
Для работы функционала необходимо определить переменную окружения ANSIBLE_TEMPLATING_TOOL. Значением должна выступать метка инструмента ansible (подробнее можно прочитать в разделе Поиск инструментов сборки).
Также доступна Ansible-шаблонизация pipeline.yml посредством ${build: } и ${build block:}, при этом используется Jinja2-синтаксис. Предварительно необходимо задать ANSIBLE_TEMPLATING_TOOL (метка инструмента Ansible). Подробнее о настройке можно узнать в разделе Поиск инструментов сборки.
Пример шаблона:
${build block: if not lookup('env', 'BINARIES_VERSION') and lookup('env', 'TEST_SPEC') == 'bin'}
fp:
groupId: "<PROD_1>"
artifactId: "<DEVOPS_PIPELINE_1>"
version: "D-01.000.02"
${build block: elif lookup('env', 'BINARIES_VERSION') and lookup('env', 'TEST_SPEC') == 'conf'}
fp:
groupId: "<PROD_2>"
artifactId: "<DEVOPS_PIPELINE_2>"
version: "P100"
${build block: endif}
Для использования lookup плагина „file“ рекомендуется применять следующую конструкцию:
${build: lookup('file', source_folder + '<relative_path>' ) }
Где:
source_folder - параметр пути до «package/conf» (менять этот параметр нельзя);
relative_path - относительный путь от «package/conf».
Также можно использовать и относительный путь от workspace (где вызывается шаблонизация):
${build: lookup('file', '<relative_path>' ) }
Сборка скриптов БД#
Скрипты БД, лежащие в дистрибутиве, должны быть сконфигурированы таким образом, чтобы при сборке получался архив следующей структуры:
db_archive.zip/
├─ <jdbc-driver>.jar
├─ <liquibase>.jar
├─ 0001_changelog.xml
├─ <папки и файлы, на которые ссылается 0001_changelog.xml>
Файла такой структуры можно добиться, например, с помощью добавления в файл pom.xml зависимостей postgres вызова assembly plugin с соответствующим дескриптором:
<dependencies>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.6.2</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.4.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-db-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>db_archive</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>db-assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Важно: помимо скриптов текущего релиза в архив должны попасть liquibase-скрипты БД всех предыдущих. В данном примере все скрипты накопительным итогом хранятся в resources, и resources целиком попадает в дистрибутив.
и содержимое дескриптора db-assembly.xml (все файлы, которые нужно добавить, расположены в src/main/resources):
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0">
<id>make-liquibase-archive</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<dependencySet>
<includes>
<include>org.postgresql:postgresql</include>
<include>org.liquibase:liquibase-core</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main/resources/</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
</fileSets>
Сборка bh-артефактов#
Репозиторий bh - это обычный maven-проект. Для сборки используется maven, который
настроен в соответствующем разделе в файле pipeline.yml.
При этом к cmd добавляются следующие параметры (профили включаются, если не выключен сонар):
mvn <параметры из настройки args> -U -Dmaven.repo.local=<workspace>/.m2 -DFP_VERSION=<версия дистрибутива> -DDB_BRANCH_NAME=<ветка репозитория> -Pnexus-alpha,sonar,sonar-coverage
Далее, если не включен параметр sonarSkip, запускается SonarQube сканирование. Для запуска сканирования используется следующая команда:
если настроен параметр
sonar_cmd- просто выполняется то, что в нем указано (при этом в начало команды добавляются параметры изargs)иначе - выполняется команда
sonar:sonarс параметрами (параметры указываются с префиксом -D - как стандартные свойства Java):sonar.projectKey - указывается, если не включена опция
sonarPomConfiguredи если в pom.xml нет свойстваsonar.projectKey. Равен этот параметр свойствуnameрепозитория (в pipeline.yml).sonar.branch.name - текущая ветка репозитория. Если она равна опции
sonar.mainBranch- то параметр вообще не указывается.sonar.branch.longLivedBranches.regex - берется из опции
sonar.longLivingBranchesPattern, по умолчанию равен(<текущая ветка>|branch|release|develop).*sonar.login - в качестве значения используется переменная окружения
SONAR_TOKEN
Описание параметров конфигурации в файле pipeline.yml представлено в соответствующем разделе
Сборка Frontend#
Репозиторий pl - это nodejs-проект. Для сборки используется npm, который настроен в соответствующем разделе pipeline.yml.
При этом перед запуском непосредственно команды, которая прописана в cmd, будет выполнена подгрузка зависимостей с помощью команды
npm set strict-ssl false && env && npm ci -timeout=9999999.
Важно!
В корне репозитория должен располагаться файл package-lock.json
package-lock.json предназначен для блокировки зависимостей от определенного номера версии. В package-lock.json файле перечислены зависимости вашего приложения и зависимости всех его составляющих.
Генерация package-lock.json производится в процессе исполнения команды
npm install [library]. При установке библиотек необходимо указывать версию (например,npm i express@4.18.2). Указание флагов –save-dev/–save-prod при установке зависимостей обязательно.
Рекомендуется сохранять именно подобное поведение, т.е. скачивание зависимостей с помощью команды npm ci, т.к. если использовать npm install,
можно получить ситуацию, когда сборка внезапно начинает падать без каких-либо изменений - из-за того, что вышла новая версия какой-либо из зависимостей.
Параметры конфигурации в pipeline.yml описаны в соответствующем разделе.
Собственная реализация сборки#
Предоставляемая Jenkins библиотека программного компонента позволяет реализовывать собственные решения по сборке приложений для дистрибутива. Данный способ необходим в случае отсутствия той или иной сборочной функциональности внутри библиотеки и является рекомендуемой практикой, так как позволяет разработчикам собирать дистрибутивы удобными способами без привязки к pipeline. Как это сделать:
В корне репозитория в собираемой ветке создается Jenkinsfile.
В данный файл копируется обертка:
groovy def onDistrib(app, distr) { } return wrapJenkinsfile(this)Далее, при, например, сборке через maven, может быть добавлен wrapper:
def onDistrib(app, distr) { withMaven(jdk: 'JDK_1.8_121_Linux', maven: 'Maven 3.6.1', mavenSettingsConfig: 'test.app.settings') { } } return wrapJenkinsfile(this)Параметр
mavenSettingsConfigбудет описан в соответствующем разделе Настройка конфигурационных файлов в Jenkins файла settings.xml.После этого осталось написать команду сборки вашего приложения (или любую другую).
Важное замечание!Внутри обертки onDistrib можно указывать что угодно:можно загружать файлы и копировать их в папки;
можно вызывать несколько команд maven и т.д. Для добавления артефактов в дистрибутив необходимо вызывать соответствующие методы объекта Distrib. Полный список методов описан ниже.
Добавить dockerfile или, например, entrypoint-скрипт можно с помощью функции
distr.addDockerItems('my-deployment-unit', 'Dockerfile')илиdistr.addDockerItems('my-deployment-unit', 'entrypoint.sh').После создания Jenkinsfile в репозитории, его нужно настроить в pipeline.yml в соответствии с разделом Заполнение раздела Jenkinsfiles.
Пример сборки maven-проекта#
def onDistrib(app, distr) {
withMaven(jdk: 'JDK_1.8_121_Linux', maven: 'Maven 3.6.1', mavenSettingsConfig: 'test.app.settings') {
sh "mvn clean package -Ddistrib.version=${distr.getVersion()}"
sh 'mvn sonar:sonar'
}
distr.addBH ("target/*.war") // добавляем в дистрибутив артефакт типа bh
}
return wrapJenkinsfile(this)
Пример сборки gradle-проекта#
def onDistrib(app, distr) {
withEnv(["GRADLE_HOME=${tool name: 'gradle-6.5', type: 'gradle'}"]) {
withCredentials([usernamePassword(credentialsId: 'my-credentials', usernameVariable: 'maven.user.name', passwordVariable: 'maven.user.password')]) {
stage('Build with gradle') { // допустим, вызов SonarQube встроен в build
sh "$GRADLE_HOME/bin/gradle :my-app:build -Pversion=$distr.version"
}
}
}
distr.addBH("./my-app/build/libs/my-app-*.jar") // добавляем в дистрибутив артефакт типа bh
}
return wrapJenkinsfile(this)
Пример сборки npm-проекта#
def onDistrib(app, distr) {
nodejs(configId: 'test.app.npmrc', nodeJSInstallationName: 'v7.5.0-linux-x64') {
sh 'npm ci'
sh 'npm pack'
}
distr.addPL("*.tgz") // добавляем в дистрибутив артефакт типа pl
}
return wrapJenkinsfile(this)
На этапах построения приложения происходит скачивание open-source библиотек и компонент из внешних репозиториев. Данная процедура производится с использованием инструмента, который проверяет соответствие установленных библиотек и компонентов требованиям кибербезопасности.
API дистрибутива#
У объекта Distrib существуют методы для добавления артефактов в дистрибутив:
Аргумент filePath во всех приведенных ниже методах - это путь к файлу, который необходимо добавить в дистрибутив. Допускается использование маски в bash-стиле.
// Добавить в дистрибутив артефакт типа bh
// Если задан аргумент bhName, то артефакт будет добавлен в папку bh/$bhName
def addBH(filePath, bhName = "")
// Добавить в дистрибутив артефакт типа pl
def addPL(filePath)
// Добавить в дистрибутив артефакт типа pl_mobile
def addPLMobile(filePath)
// Добавить в дистрибутив артефакт типа db
def addDB(filePath)
// Добавить в дистрибутив артефакт типа data
def addData(filePath)
// Добавить файл(ы) документации в дистрибутив
def addDocs(filePath)
// Добавить файлы конфигурации в дистрибутив
def addConf(filePath)
// Добавить Dockerfile (Dockerfile, entrypoint.sh, etc) в дистрибутив
def addDockerItems(deploymentUnit, filePath)
Расшифровка для типов артефактов приведена в разделе Термины и сокращения.
Методы объекта Distrib для добавления своих библиотек в дистрибутив (для пользования другими командами):
// Добавляет в дистрибутив Node.js-библиотеку
// coordinates - координаты библиотеки в npm-формате (имя библиотеки и ее версия)
def addSdkNpm(filePath, coordinates) // пример - distr.addSdkNpm('some-path/output.tgz', [name: 'some-lib', version: '1.2.3'])
// Добавляет в дистрибутив JAR-библиотеку (Java)
// pomPath - путь к файлу pom.xml библиотеки
def addSdkMvn(filePath, pomPath)
Чтобы получить версию дистрибутива, следует использовать метод getVersion:
def getVersion()
Сборка Pull Request#
Для того чтобы собрать Pull Request в том же окружении, в котором он будет собираться
при подготовке дистрибутива (что дает некоторые гарантии того, что PR не сломает
сборку дистрибутива), рекомендуется использовать предоставляемую библиотеку. Кроме того,
данный подход позволяет версионировать логику сборки приложения вместе с кодом
самого приложения.
Для этого необходимо добавить Jenkinsfile в корень репозитория и настроить автоматический запуск сборки. Ниже описаны требования к содержанию Jenkinsfile
Требования к Jenkinsfile#
Jenkinsfile – это стандартный pipeline-скрипт Jenkins.
В данном файле должны быть реализованы методы:
onPR(prInfo)- для обработки событий PR. prInfo - словарь с ключами:id (Pull Request id),
url (ссылка на PR),
from (из какой ветки PR),
to (в какую ветку PR).
onCommit(commitInfo)- для обработки commit-хуков, например, после слияния ветки вdevelop,masterилиrelease/*.
commitInfo содержит ключ branch с наименованием ветки, в которую был выполнен commit (или merge).
В скрипт должна быть подключена библиотека ufs-pipeline, на уровне папки, либо через динамическую загрузку.
Скрипт должен заканчиваться строчкой
return wrapJenkinsfile(this, context), где context - это необязательный параметр-map, содержащий ключи:NODE - наименование slave или label (по умолчанию
Linux_Default), на котором следует выполнять сборку,COLOR_MAP - параметр для степа ansiColor (по умолчанию
xterm).
Использование node в скрипте Jenkinsfile не требуется и не рекомендуется.
Использование stage - рекомендуется в onPR и не рекомендуется в onDistrib.
Отправлять нотификации в Bitbucket не требуется и не рекомендуется.
Данный функционал присоединяется вызовом wrapJenkinsfile.
Автоматический запуск сборки#
Существуют следующие варианты настройки автоматического запуска сборки:
С помощью stash-плагина Pull Request Notifier :
Организовать первичный запуск Jenkins job.
Настроить выгрузку репозитория.
Добавить загрузку Jenkinsfile и вызов метода, соответствующего целям сборки (onPR или onCommit):
load('Jenkinsfile').onPR().Можно использовать пример ниже – Job с подгрузкой Jenkinsfile.
С помощью jenkins-плагина Multibranch Pipeline. В этом случае в настройках multibranch pipeline необходимо подключить библиотеку ufs-pipeline c load implicity.
Для корректной работы функциональности notifyBitbucket, которая автоматически вызывается при сборке, рекомендуется добавить в Jenkins job следующие переменные окружения:
USERPASS_CREDS - ID credentials в Jenkins, у которых есть доступ в Bitbucket;
STASH_BASE_URL - ссылка на Bitbucket.
Примечания#
Решение проблем первой сборки pipeline с использованием Pull Request Notifier#
У многих команд имеются сложности с тем, что pipeline-job сборки Pull Request не запускается через hook Bitbucket.
Для запуска, необходимо хотя бы одно успешное выполнение checkout этой Jenkins job.
Для этого рекомендуется выполнить следующие действия:
Создать в репозитории ветку
pull-requests/test.Запустить Jenkins job с отмеченной опцией Poll SCM и следующим кодом pipeline:
def creds = <credentials id>
def repo = <ссылка на репозиторий>
node('Linux_Default') {
checkout([$class: 'GitSCM', branches: [[name: 'pull-requests/**']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: creds, url: repo]]])
}
После этого hook репозиториев должен заработать, и Jenkins job можно наполнять полезным функционалом.
Ветку pull-requests/test можно удалить.
Примеры Jenkinsfile#
Пример Jenkinsfile со сборкой maven#
mySonarUrl = 'https://sonar.<...>/sonar/dashboard?id=some-project'
def onPR(prInfo) {
stage('Build') {
build()
}
report()
}
def onCommit(commitInfo) {
stage('Build') {
build()
}
report()
}
def build() {
withCredentials([usernamePassword(credentialsId: 'tech-creds', passwordVariable: 'TECH_PASSWORD', usernameVariable: 'TECH_USERNAME')]) {
withMaven(jdk: 'jdk_installation', maven: 'maven_installation', mavenSettingsConfig: 'settings') {
mvnBuild()
if (!app.sonarSkip?.toBoolean()) {
sonarScan()
}
}
distributeArtifacts()
}
}
def mvnBuild() {
sh """
mvn clean install -U -P build-config,spring
touch test-db.zip
touch pom-test.xml sdk-test.txt
"""
}
def sonarScan() {
withSonarQubeEnv(credentialsId: 'your_cred', installationName: 'your_sonar_installation') {
def sonarProjectKey = 'test.app.backend'
sh """
mvn sonar:sonar \
-Dsonar.projectKey=${sonarProjectKey} \
-Dsonar.host.url=${SONAR_HOST_URL} \
-Dsonar.login=${SONAR_AUTH_TOKEN} \
-Dsonar.branch.name=${SONAR_BRANCH} \
--errors
mv target/sonar ./
"""
}
}
def report() {
stage('Report') {
junit '**/target/surefire-reports/*.xml'
addBadge icon: '/plugin/sonar/images/waves_16x16.png', link: "$mySonarUrl&branch=$commitInfo.branch", text: 'Analyzed by SonarQube'
}
}
def distributeArtifacts() {
distr.addSdkMvn('pom-test.xml', 'sdk-test.txt')
distr.addDB('test-db.zip')
distr.addBH('target/*.war')
distr.addBH('mod/module_test/*')
distr.addConf('target/conf/*')
}
return wrapJenkinsfile(this)
Пример Jenkinsfile со сборкой gradle#
mySonarUrl = 'https://sonar.<...>/sonar/dashboard?id=some-project'
def onPR(prInfo) {
withCredentials([usernamePassword(
credentialsId: 'tech-creds',
passwordVariable: 'TECH_PASSWORD',
usernameVariable: 'TECH_USERNAME'
)]) {
stage('Build') {
sh './gradlew build'
}
stage('Sonar') {
sh """./gradlew \
-Dsonar.login=$env.TECH_USERNAME \
-Dsonar.password=$env.TECH_PASSWORD \
-Dsonar.stash.login=$env.TECH_USERNAME \
-Dsonar.stash.password=$env.TECH_PASSWORD \
-Dsonar.pullrequest.key=$prInfo.id \
-Dsonar.pullrequest.branch=$prInfo.from \
-Dsonar.pullrequest.base=$prInfo.to \
sonar """
}
}
stage('Report') {
junit '**/target/surefire-reports/*.xml'
addBadge icon: '/plugin/sonar/images/waves_16x16.png',
link: "$mySonarUrl&pullRequest=$prInfo.id",
text: 'Analyzed by SonarQube'
}
}
def onCommit(commitInfo) {
withCredentials([usernamePassword(
credentialsId: 'tech-creds',
passwordVariable: 'TECH_PASSWORD',
usernameVariable: 'TECH_USERNAME'
)]) {
stage('Build') {
sh './gradlew build'
}
stage('Sonar') {
sh """./gradlew sonar \
-Dsonar.login=$TECH_USERNAME \
-Dsonar.password=$TECH_PASSWORD \
-Dsonar.branch.name=$commitInfo.branch
"""
}
}
stage('Report') {
junit '**/target/surefire-reports/*.xml'
addBadge icon: '/plugin/sonar/images/waves_16x16.png',
link: "$mySonarUrl&branch=$commitInfo.branch",
text: 'Analyzed by SonarQube'
}
}
return wrapJenkinsfile(this)
Jenkins job Pull Requests с подгрузкой Jenkinsfile#
def creds = 'git-creds'
def branch = 'master'
def repo = 'SSH ССЫЛКА НА РЕПОЗИТОРИЙ БИТБАКЕТ С ВАШИМ JENKINSFILE'
def merge(map, remoteConfig) {
def branchFrom = map.from ?: 'origin/pull-requests/**'
def branchTo = map.to
return checkout([
$class: 'GitSCM',
branches: [[name: branchFrom]],
extensions: [[$class: 'PreBuildMerge', options: [mergeRemote: 'origin', mergeTarget: branchTo]]],
userRemoteConfigs: [remoteConfig]
])
}
library identifier: "ufs-pipeline@$branch", retriever: legacySCM([
$class: 'GitSCM',
branches: [[name: branch]],
userRemoteConfigs: [[
credentialsId: creds,
url: 'SSH ССЫЛКА НА РЕПОЗИТОРИЙ БИТБАКЕТ С UFS-PIPELINE'
]]
])
node('Linux_Default') {
ansiColor('xterm') {
stage('Checkout') {
merge (
[to: env.PULL_REQUEST_TO_BRANCH],
[
credentialsId: creds,
url: repo
]
)
}
if( fileExists('Jenkinsfile') ) {
load('Jenkinsfile').onPR()
} else {
echo "Jenkinsfile not found" // На время переходного периода, когда PR с Jenkinsfile уже есть
manager.buildAborted() // А в основных ветках его еще нет
}
}
}
Сборка и доставка Docker образов#
В случае, если необходимо выполнить установку в OpenShift, необходимо создать следующую иерархию в репозитории с конфигурациями:
test.app.config/
├─ k8s/base/
│ ├─ test.app.backend/
│ │ ├─ Dockerfile
│ │ ├─ dc.yaml
│ ├─ test.app.frontend/
│ │ ├─ Dockerfile
│ │ ├─ dc.yaml
├─ pipeline.yml
При наличии данной структуры, созданный pipeline найдет необходимые Dockerfile и запустит их сборку, после чего выложит образы в registry. Помимо этого он вставит hash образов в соответствующие конфигурационные файлы.
Обратите внимание, что в приведенной иерархии имя Docker образа будет соответствовать имени директории в которой расположен Dockerfile (в конкретном случае это
test.app.backend,test.app.frontend), а тег это версия дистрибутива.
В Dockerfile, вместо указания
tag, можно использовать placeholder BASE_IMAGE_VERSION, который будет доставать последнюю доступную версию базового образа на текущий момент, например:
FROM registry.host/path/to/my/image:BASE_IMAGE_VERSION
В Dockerfile необходимо указать параметр BASE_IMAGE, как показано в примере:
ARG BASE_IMAGE=registry.host/path/to/my/image:tag
FROM ${BASE_IMAGE}
Настройка Docker в файле конфигурации pipeline.yml описана в разделе Заполнение раздела docker.
Результат выкладки в registry отображается в логах Jenkins job (ссылка на docker-image), который можно дополнительно проверить, зайдя по адресу web-интерфейса docker-репозиториев
https://registry.<...>.ru/docker/под общим ТУЗом. В web-интерфейсе необходимо перейти по указанному пути в image_path (как пример - browse - efs/ci00428440_efs/ci00749857_efs_authorization) и/имя сервиса/tags.
Сборка приложений в Docker#
Декларативная сборка#
Декларативный подход к решению предполагает использование раздела with_docker в секции build. Данный раздел направлен на непосредственную работу с Dockerfile, в котором разработчик описывает последовательность инструкций по сборке приложений. Существует следующее соглашение, обязательное при использовании данной функциональности:
В корневой директории (
/) финального Docker-образа должна располагаться папка с названиемoutputs;В папке
outputsдолжны располагаться директории, названия которых полностью соответствуют типу добавляемого артефакта (bh, pl, ...)
Для добавления Dockerfile (Dockerfile, entrypoint.sh, etc) в дистрибутив необходимо в
outputs/dockerопределить директории с наименованием соответствующего deployment-unit, которые содержат соответствующие Dockerfile-артефакты.
Раздел with_docker используется для подключения сборки приложения в Docker. Каждый элемент списка в данном разделе должен содержать следующие обязательные параметры:
name - название элемента (рекомендуется использовать уникальные значения всех name во всех блоках);
repo (<…>/helloword.git) - репозиторий, из которого нужно взять собираемый Dockerfile;
branch (master) - ветка, из которой нужно взять расширение.
context - директория сборки Docker-образов;
dockerfile_path - путь до Docker-файла относительно директории сборки;
Также раздел может включать следующие необязательные параметры:
secrets - подраздел, отвечающий за передачу секретов (файлов, переменных) в Docker-сборку:
files - расширение для добавления конфигурационных файлов (данная опция включает список
<config file id>);
prod_branch - это ветка, из которой был собран предыдущий релиз (можно также указать тег);
sonarSkip - если
true, пропустить SonarQube-сканирование;create_tag - значение типа boolean, по умолчанию
false(если значение параметра выставлено вtrue, то создается аннотированный тег с версией, декларированной разделом fp);parallel - опция использования параллельной сборки (если для двух приложений будет указано одинаковое значение
parallel, то они будут запускаться в общем потоке);outputs - список артефактов, которые необходимо скопировать в директорию относительно
workspace;source - путь до артефакта (может быть указана маска). Значение по умолчанию -
outputs/*;dest - директория назначения выбранного артефакта. Значение по умолчанию -
package;
skip - если установить в
true, сборка данного Dockerfile будет пропущена.use_cache - при значении
falseпозволяет производить сборку with_docker не используя cache. Значение по умолчанию -true;
Для использования данного раздела требуется заполнение секции docker (подробнее об этом можно прочитать в разделе Заполнение раздела docker).
build:
with_docker:
- name: "docker-app-1"
repo: "project/dockerfile-repo.git"
branch: "release/1.0.0"
prod_branch: "master"
dockerfile_path: Dockerfile
context: ./
parallel: "A"
secrets:
files:
- <config file id>
outputs:
- source: "outputs/bh/*"
dest: "package/bh"
Монтирование секретных файлов производится через флаг
--mount=type=secret,id=maven_secret_id,dst=/project/settings.xmlв инструкцииRUNв вашем Dockerfile. Заданный параметрtype(тип монтируемого файла) должен иметь значениеsecret; значение параметраidдолжно совпадать с, определенным в filesв подразделеsecretsвашего pipeline.yml; значение параметраdstопределяет расположение конфигурационного файла (требуется указать полный путь и имя файла).
Добавленные через инструкцию
filesв подразделеsecretsконфигурационные файлы по умолчанию (без указания параметраdstв инструкцииRUN) располагаются в директории/run/secrets/запущенногоDocker- образа. Имена добавленных конфигурационных файлов соответствуют указанному<config file id>в списке, определеннымfiles.
syntax- определяет расположение образа синтаксиса Dockerfile, используемого для сборки пользовательского Dockerfile. В данном контексте определение образа синтаксиса необходимо для использования инструкцииRUNс флагом--mount=type=secret,id=maven_secret_id(пример официального образа интерфейсаDockerfile-docker/dockerfile:1.2).
Важно отметить, что сборка c кешированием в удаленный registry производится только при наличии установленного
buildxплагина илиbuildctlконтроллера BuildKit и заполненного подразделаcacheсекцииdocker.
Для указания ссылки на собственный BuildKit демон, переопределите переменную окружения BUILDKITD_HOST.
Пример Dockerfile:#
# syntax = registry.host/path/to/my/dockerfile/syntax/image:tag
FROM registry.host/path/to/my/maven/image:tag AS <target>
WORKDIR project/
COPY . .
RUN --mount=type=secret,id=<config file id>,dst=/project/settings.xml mvn clean package
FROM scratch
COPY --from=<target> /project/target/*.war /outputs/bh/
Сборка приложения с кешированием слоев:#
Кеширование слоев необходимо для увеличения скорости сборки проекта. Сборка проекта может быть разделена на несколько этапов, например - загрузка зависимостей и сборка приложения. Каждый этап может быть записан в отдельной инструкции в Dockerfile при сборке Docker-образа. Тогда для каждой инструкции создается новый слой образа, который сохраняется в кеше. В случае отсутствия изменений в исходных файлах проекта для отдельной инструкции, пересборка проекта или повторная загрузка зависимостей не осуществляется. Ниже приведены примеры сборок проектов в Dockerfile:
Пример сборки maven-проекта в Dockerfile#
Для настройки кеширования промежуточных слоев в удаленный репозиторий необходимо прописать название scratch:
# syntax = registry.host/path/to/my/dockerfile/syntax/image:tag
FROM registry.host/path/to/my/maven/image:tag AS <target>
WORKDIR project/
# Копируем из исходного репозитория конфигурационные файлы проекта
COPY ./pom.xml ./
# Производим полную загрузку зависимотей
RUN --mount=type=secret,id=maven_secret_id mvn package -s /run/secrets/maven_secret_id
# Копируем проект целиком (pom.xml файл перезапишется)
COPY . .
# Производим сборку проекта
RUN --mount=type=secret,id=maven_secret_id mvn package -s /run/secrets/maven_secret_id
FROM scratch
COPY --from=<target> /project/target/*.war /outputs/bh/
При работе с кешированием необходимо убедиться, что каталоги/файлы, которые не участвуют в сборке проекта (например, .git, .idea, …), исключены из сборки Dockerfile. Инструментом для уточнения контекста сборки является файл
.dockerignore
Пропуск кеширования отдельных инструкций#
Для пропуска кеширования отдельных инструкций рекомендуется использовать произвольный параметр внутри dockerfile, который во время сборки будет изменен, к примеру:
ARG CACHEBUST
RUN echo "$CACHEBUST" && mvn --settings /run/secrets/maven_secret_id package
Вместе с тем необходимо будет этот же параметр добавить в build_args секции docker:
docker:
build_args:
CACHEBUST: "$(date +%s)"
Экспорт переменных окружения Jenkins Job#
Для доступа к переменным окружения Jenkins Job нужно смонтировать секретный файл с ID envParams. Экспорт переменных в процесс сборки производится следующей инструкцией в Dockerfile - RUN --mount=type=secret,id=envParams,dst=/project/envParams . ./envParams || source ./envParams
# syntax = registry.host/path/to/my/dockerfile/syntax/image:tag
FROM registry.host/path/to/my/maven/image:tag
WORKDIR project/
COPY . .
RUN mvn package -s settings.xml
# Монтируем секретный файл и экспортируем переменные окружения
RUN --mount=type=secret,id=envParams,dst=/project/envParams \
. ./envParams && \
printenv
Передача секретных параметров#
Создайте конфигурационный файл с типом Custom file в Jenkins:
export EXAMPLE_KEY=$SECRET_TOKEN_ID
export ...
Смонтируйте секретный файл и произведите экспорт переменных, например - RUN --mount=type=secret,id=<custom file id>,dst=/project/<custom file name> . ./<custom file name> || source ./<custom file name>.
# syntax = registry.host/path/to/my/dockerfile/syntax/image:tag
FROM registry.host/path/to/my/maven/image:tag
WORKDIR project/
# Экспортируем переменные в окружение среды
RUN --mount=type=secret,id=envParams,dst=/envs \
--mount=type=secret,id=custom_envs,dst=/custom_envs \
. ./custom_envs && . ./envs && \
printenv
Настройка SonarQube#
Для настройки сканирования приложений необходимо использовать переменные доступа к инструменту SonarQube, которые могут быть доступны в Dockerfile через инструкцию - RUN --mount=type=secret,id=envParams,dst=/project/envParams.
Существует следующее соглашение, обязательное для использования данного функционала:
В корневой директории (
/) финального Docker-образа должна располагаться папка с названиемsonar;В директории
sonarдолжны располагаться отчеты о сканировании вашего приложения. Например, SonarScanner плагин сборщика Maven после анализа приложения загружает отчеты о сканировании в директориюtarget/sonarотносительно корня репозитория
Использование SonarQube при сборке Docker#
Для интеграции SonarQube в процессе сборки Docker, при условии заполненного раздела sonar в pipeline.yml, в контекст сборки передаются следующие переменные окружения, чтобы обеспечить корректное взаимодействие с сервером SonarQube:
SONAR_HOST_URL - URL сервера SonarQube.
SONAR_AUTH_TOKEN - токен для аутентификации.
После завершения сканирования SonarQube создаёт файл report-task.txt, содержащий информацию о задаче сканирования. Этот файл следует поместить в папку outputs/sonar внутри финального Docker-образа, чтобы обеспечить возможность дальнейшей обработки результатов. Более подробно про использование SonarQube при сборке Docker можно прочитать в документации SonarQube.
Пример сканирования maven-приложения в Docker#
# syntax = registry.host/path/to/my/dockerfile/syntax/image:tag
FROM registry.host/path/to/my/maven/image:tag as <target>
WORKDIR project/
COPY . .
RUN mvn package -s settings.xml
# Экспортируем переменные в окружение среды и производим сканирование
RUN --mount=type=secret,id=envParams,dst=/project/envParams \
. ./envParams && \
mvn sonar:sonar -s settings.xml
FROM scratch
COPY --from=<target> /project/target/*.war /outputs/bh/
COPY --from=<target> /project/target/sonar/* /sonar/
Существующие точки расширений#
analyzeDependencies#
Данное расширение подключается автоматически и выполняет анализ зависимостей включенных в дистрибутив образов.
Для того чтобы отменить автоматическое подключение расширения, нужно создать переменную окружения ANALYZE_DEP = false.
Также это расширение использует сервис поиска образов по hash, который предоставляет Nexus.
Запрос к сервису генерируется следующим образом: <registry_root>/<registry_search_api><hash>,
где registry_root - это параметр docker.registry_address из pipeline.yml,
а registry_search_api - путь сервиса поиска, по умолчанию docker/service/rest/v1/search?docker.contentDigest=sha256:,
hash - хэш искомого образа
Запрос к сервису можно переопределить с помощью переменной окружения REGISTRY_SEARCH_API, причем, если она будет начинаться с https://,
ссылка на сервис будет генерироваться так: <registry_search_api><hash> (т.е. без registry_root).
Узнать адрес сервиса поиска образов можно у владельца инсталляции Nexus
Если требуется использовать какую-либо специальную версию SYFT, можно ее указать с помощью переменной окружения ]]SYFT_TOOLING - но она должна быть подключена в Jenkins.
sequrityChecks#
Данное расширение подключается автоматически и выполняет запуск проверок SAST/OSS. Результирующие флаги проверок будут загружены в qgm средствами сервиса SAST/OSS. Запуск проверок можно регулировать выключением/включением сценариев в PLAYBOOKS sast-run и oss-run.
Для использования конкретных метрик проверки необходимо указать опцию sast_check_keysв секции securityChecks файла pipeline.yml. Внутри этой опции определяются флаги и ожидаемые результаты. Например:
SAST_PASS - для проверки на дефекты средней степени критичности.
no_critical_defects - для проверки на отсутствие дефектов высокой критичности.
Вы можете указать любые требуемые флаги, поддерживаемые SAST.
Пример заполнения:
- name: securityChecks
devsec_repo: some_devsec_repo
run_sast: true
run_oss: true
sast_check_keys:
SAST_PASS: true
no_critical_defects: true
makeReleaseNotes#
Данное расширение подключается автоматически, готовит ReleaseNotes и выкладывает его в QGM.
Настройка данного расширения осуществляется через Заполнение раздела qgm qgm в файле pipeline.yml.
Формирование Release Notes для каждого из используемых репозиториев управляется следующими параметрами:
Релизная ветка или tag (
prod_branch, между этой веткой будет браться diff. Если указываетсяtag, то в форматеrefs/tags/tagID).Регулярное выражение для определения списка задач из JIRA (
issue_pattern). Например:### Ссылки на сборочные Jenkins-файлы ### jenkinsfiles: - name: "test.app.backend" # любое repo: "ufs_ci/test.app.backend.git" # url без хоста branch: "develop" # ветка сборки prod_branch: 'master', issue_pattern: '[A-Za-z][A-Za-z0-9]+-[0-9]+' # регулярное выражение по которому определяется идентификатор запроса в JIRA из commit.
updateVersionConf#
Данное расширение подключается автоматически и выполняет копирование файла version.conf в дистрибутив из репозитория version.conf.git того же проекта, из которого запускался ufs-pipeline.
Ветка репозитория определяется по следующим правилам:
если релиз платформы
!R19.5, то используетсяApp19.5если релиз платформы
!R20.1, то используетсяApp20.1иначе используется ветка
master
Кроме того, в случае наличия соответствующих переменных окружения PLATFORM_RELEASE и/или AT_BRANCH в файл version.conf добавятся параметры atBranch и platformRelease.
Также, если в подготавливаемом дистрибутиве уже содержится файл version.conf (был в репозитории конфигураций или добавлен из Jenkinsfile), то все параметры в нем будут сохранены.
В случае, когда данный репозиторий
version.conf.gitуже есть в разделе downloads, расширение не выполняет копирование, но выводит предупреждение, если выбрана неверная ветка. При этом остальная логика (выставление параметровatBranchиplatformRelease, сохранение уже существующих параметров) также не будет выполнена – будет скопирован тот файл, который указан в downloads.
AddDescription#
Данное расширение подключается автоматически и добавляет в описание сборки таблицу с координатами дистрибутива, а также ссылками, по которым он (и его pom.xml) был загружен в хранилище.
Если в вашей инфраструктуре используется какие-либо механизмы по «перекладыванию» дистрибутивов, ссылки могут быть устаревшими.
generateSWIDtagFiles#
Данная точка расширения выполняет генерацию файла SWIDTAG-файла.
Для работы точки необходима следующая структура pipeline.yml:
info:
version: D-01.00.00 # версия компонента (если не заполнено, используется то же значение, что и для fp.version)
code: wxyz # код компонента
title: "Component title" # название собираемого компонента в учетной системе
creator:
name: "<NAME>" # название организации создателя тега
regid: "<...>" # идентификатор организации создателя тега
product:
title: "Product title" # название продукта в учетной системе
code: XYZ # код продукта в учетной системе, к которому относится собираемый компонент
version: 1.0.0 # версия продукта в учетной системе, к которому относится собираемый компонент
dependencies: # необязательный параметр, список зависимостей продукта на другие продукты
- { unique_id: <unique_id> , tag_creator_regid: <tag_creator_regid> }
- unique_id: cije-1.9.0
tag_creator_regid: <...>
extensions:
- name: generateSWIDtagFiles
Так же отдельные/все параметры можно определить в настройках Jenkins job с помощью String Parameter:
info.version;info.code;info.title;info.creator.name;info.creator.regid;info.product.code;info.product.version;info.dependencies.
Данные определения будут иметь высший приоритет и перезаписывать значения из pipeline.yml.
Для передачи параметра info.dependencies в значении следует указать JSON-массив, например:
[] или [{ unique_id: "test fp dependency1 unique_id env" , tag_creator_regid: "<REG_ID>" }, { unique_id: "test fp dependency2 unique_id env" , tag_creator_regid: "<REG_ID>" }]
Генерация SWIDTAG-файла производится с помощью Ansible посредством модуля template.
Также есть возможность использовать шаблон, который уже находится в workspace сборки. Для этого необходимо прописать в pipeline.yml:
extensions:
- name: generateSWIDtagFiles
template: <template> # путь до файла с шаблоном
transformDistrib#
Данное расширение позволяет трансформировать получившийся дистрибутив в какой-либо другой формат.
Для этого необходимо указать правила трансформации в параметре directories в виде <директория>: <файлы, которые надо в нее скопировать>
Пример:
extensions:
- name: transformDistrib
directories:
modules: "package/bh/*"
other/seap-lib/lib: "package/sdk/mvn/*"
config: "package/conf/application.properties"
install: "package/conf/deployment_pg.xml"
db: "package/db/*"
./:
- "package/ReleaseNotes.json"
- "package/conf/pipeline.yml"
CheckDistrib#
Расширение для проверки состава получившегося дистрибутива. Настройка проверок осуществляется с помощью следующих параметров:
exists список регулярных выражений, по которым требуется проверять наличие файлов
not_exists список регулярных выражений, по которым требуется проверять отсутствие файлов
check_rn - необязательный параметр, по-умолчанию: false. Значение true указывается для запуска проверки ReleaseNotes.
checked_flags - список QGM флагов. Указанные QGM флаги проходят проверку (ОК статус) для выпущенного дистрибутива.
Пример (проверка дистрибутива бинарных файлов):
extensions:
- name: CheckDistrib
exists:
- package/conf/data/sup2/.*
- package/docker/test.app.backend/.sha256
not_exists:
- documentation/.*
- package/conf/openshift/test.app.backend/.sha256
- package/conf/openshift/test.app.backend/Dockerfile
- package/bh/.*
- package/sdk/.*
- package/db/.*
- package/pl/.*
- package/conf/data/analyze_dep/.*
generateJenkinsFile#
Данная точка расширения предназначена для упрощения разработки jenkinsfile для своих сборок.
При ее выполнении в bh-, pl- и db-репозиториях будет создана ветка feature/conf/SUFSCI-126, в которой будет добавлен Jenkinsfile,
реализующий сборку артефактов дистрибутива в соответствии с требованиями данной библиотеки сборки.
Какой-либо настройки расширения не требуется, достаточно просто его подключить.
gettingConfigXml#
Данная точка расширения копирует файл config.xml Jenkins job сборки в дистрибутив.
По умолчанию расширение скачивает config.xml под Credentials, указанными в USERPASS_CREDS.
Также доступна настройка через свойство расширения creds, например:
extensions:
- name : gettingConfigXml
creds: some_jenkins_token_cred
MoveDockerfile#
Расширение переносит dockerfiles из package/conf/k8s/base/<deployment_unit> в package/docker/<deployment_unit> для выполнения требований стандарта STD-5.
В большинстве случаев настройка расширения не требуется, достаточно только подключение:
extensions:
- MoveDockerfile
Но если требуется помимо Dockerfile переместить еще какие-либо файлы, можно указать соотвутствующую маску в параметре mask:
extensions:
- name: MoveDockerfile
mask: *.sh
Если нужно указать несколько масок, следует указать их списком:
extensions:
- name: MoveDockerfile
mask:
- *.sh
- *.py
std5Configuration#
Расширение для сборки дистрибутива конфигураций. Детали работы описаны в соответствующем разделе
std5Binaries#
Расширение для сборки дистрибутива бинарных файлов. Детали работы описаны в соответствующем разделе.
Обратите внимание: при использовании данной точки расширения этап шаблонизации (templating) по умолчанию будет пропущен.
std19Sdk#
Расширение для сборки дистрибутива sdk. Данное расширение исключает все файлы/папки из дистрибутива, кроме /sdk.
shell#
Расширение для выполнения shell команд.
Доступные инструменты сборки: maven, node (если настроен раздел npm).
Данная точка расширения поддерживает следующие опции:
commands - список команд, которые будут выполнены
env - список переменных, которые будут доступны
Список экспортируемых переменных окружения:
CONFIGS_DIR - конфигурационными файлами
ARCHIVE_SOURCE_DIR - директория, из которой собирается архив дистрибутива
ARCHIVE_PATH - путь до архива, если он уже собран(расширение должно быть запущено после стадии pack)
Пример (скачивание зависимости maven и клонирование репозитория):
extensions:
- name: shell
env:
collection-version: 4.4
commands:
- mvn --version
- |
mvn dependency:get -DgroupId=org.apache.commons -DartifactId=commons-collections4 -Dversion=$collection-version -Dpackaging=pom -Ddest=commons-collections4.pom
cp commons-collections4.pom $ARCHIVE_SOURCE_DIR/package/bh
- git clone <...>
generateSBOMCyclonedx#
Расширение для анализа зависимостей сборочных проектов инструментом cdxgen.
Данная точка расширения поддерживает следующие опции:
tools - список инструментов окружения для анализа зависимостей сборочных проектов
cdxgen - версия cdxgen (версия по умолчанию - 8.6.2)
cdxgen_path - путь до бинарного файла
cdxgen(путь по умолчанию -cdxgen-linux-x64)cyclonedx_cli - версия cyclonedx (версия по умолчанию - 0.27.1)
cyclonedx_cli_path - путь до бинарного файла
cyclonedx_cli(путь по умолчанию -cyclonedx-linux-x64)args - список дополнительных пользовательских параметров при исполнении команды
cdxgenclassifier - maven classifier (значение по умолчанию -
cyclonedx-distrib)env - позволяет получать и перезаписывать environment в параметрах Jenkins job из pipeline.yml
Пример:
- name: generateSBOMCyclonedx
tools:
- '<метка инструмента Jenkins>'
env:
MVN_ARGS: "install -U -P build-config,spring"
SOME_ENV: "somevalue"
При сканировании сборок инструментом
maven, библиотека определяет следующие переменные окружения:
CDX_MAVEN_INCLUDE_TEST_SCOPE- отвечает за включение зависимостей тестовой области в сканирование, по умолчанию выставлена вfalse.
MVN_ARGS- отвечает за определение дополнительных аргументов в команде сканирования, по умолчанию выставлена вincludeProvidedScope=falseПри переопределении данных переменных окружения необходимо самостоятельно добавить настройку.
Если в корне репозитория с исходным кодом присутствует
sbom.jsonфайл, то его содержимое будет использовано при формировании результирующегоSBOMфайла и сканирование данного репозитория текущей точкой расширения исполняться не будет.
При подключении расширения у вас могут возникнуть проблемы с настройкой. Пожалуйста, обратитесь к разделу - часто встречающиеся проблемы и пути их устранения.
generateSBOMTrivy#
Расширение для анализа зависимостей сборочных проектов инструментом trivy.
Данная точка расширения поддерживает следующие опции:
trivy - версия
trivy(версия по умолчанию - 0.52.0)trivy_path - путь до бинарного файла
trivy(путь по умолчанию -trivy)cyclonedx_cli - версия cyclonedx (версия по умолчанию - 0.27.1)
cyclonedx_cli_path - путь до бинарного файла
cyclonedx_cli(путь по умолчанию -cyclonedx-linux-x64)args - список дополнительных пользовательских параметров при исполнении команды
trivyclassifier - maven classifier (значение по умолчанию -
cyclonedx-distrib)sbom_path - список путей к SBOM файлам. Путь указывается относительно корня репозитория. По умолчанию - sbom.json из корневой директории репозитория.
Пример:
extensions:
- name: generateSBOMTrivy
sbom_path:
- "sbom.json"
- "target/*-sbom.json"
Если ни один SBOM файл не найден, в лог точки расширения выводится сообщение уровня INFO о том, что в репозитории не найден SBOM файл и он будет сгенерирован
Если найден ровно один SBOM файл, то в лог точки расширения выводится сообщение уровня INFO о том, что в репозитории найден SBOM файл и он будет использован вместо генерации SBOM компонента
Если в репозитории по массиву
sbom_pathнайдено несколько SBOM файлов, в лог точки расширения выводится сообщение уровня WARN о том, что в репозитории найдено несколько файлов, SBOM файл будет сгенерирован
generateSWIDtagAnnotations#
Опциональное расширение для добавления аннотаций к Docker-образам, собранным при использовании BuildKit.
Аннотации формируются из данных SWIDTAG, что означает, что точка расширения может быть включена в сборку только если generateSWIDtagFiles исполнилась ранее, а также должна быть исполнена до stage docker.
Данная точка расширения поддерживает следующие опции:
level - уровень, на котором будут созданы аннотации. Может содержать единственное значение или список из допустимых:
manifest,manifest-descriptor,index,index-descriptor. По умолчаниюmanifest.
Пример:
extensions:
- name: generateSWIDtagFiles
- name: generateSWIDtagAnnotations
level: manifest
Разработка собственной точки расширения#
В предоставляемом pipeline для каждого этапа имеется поддержка точек расширения через контракт в Jenkinsfile.
Как и в случае onDistrib() необходимо написать groovy скрипт, реализовав в нем следующую обертку:
def run(extension, extensionAPI) {
}
return this
Объект из списка extensions это Map extension в функции run, то есть все поля этого объекта доступны вам внутри. Т.е. если расширение подключено так:
extensions:
- name: SomeExtension
param1: one
param2: 2
В таком случае расширение может использовать объект extension следующим образом:
def run(extension, extensionAPI) {
assert extension.name == 'SomeExtension'
assert extension.branch == 'master' // Поскольку значение по умолчанию добавляется
assert extension.param1 == 'one'
assert extension.param2 == 2
}
return this
Объект extensionAPI можно использовать для получения данных из pipeline, доступные функции:
package ru.<...>.devops
class ExtensionAPI {
def getPipelineConfig() // прочитанный в объект pipeline.yml
def getDistrib() // объект distrib, такой же, как и в onDistrib
}
В точке расширения есть возможность подгрузить файлы, находящиеся рядом с ней в том же репозитории. Загрузка файлов осуществляется при загрузке самой точки расширения.
Как использовать:
Объявить переменные вне методов без ключевого слова
def. В них подгружаем необходимые файлы.Далее эти переменные можем использовать в методах точки расширения. Пример реализации простой точки расширения, которая читает контент файла textfile и подгружает объект файла
test.groovy, а далее в своих методах имеет доступ к содержимому textfile и методамtest.groovy:// начало файла примера точки расширения fileContents = readFile("textfile") // загружаем файл в точке расширения, но вне ее методов без ключевого слова def testFile = load("test.groovy") // загружаем еще файл, путь к файлу указываем относительно пути где находится эта точка расширения def run(extension, extensionAPI) { testFile.call() // в методе точки расширения вызываем метод загруженного файла println fileContents // а также можем смотреть контент загруженного файла } // конец файла примера точки расширения
При создании новой точки расширения можно указать конфигурацию по умолчанию, чтобы не указывать ряд полей в файле pipeline.yml. Для этого надо создать новый метод getDefaultConfig, например:
def getDefaultConfig() {
return [
stage: 'upload',
phase: 'before',
description: 'Проверка состава дистрибутива'
]
}
Поля name, repo, branch и script_path возвращать в getDefaultConfig() не нужно, т.к. они используются до загрузки расширения.
Пример точки расширения, привязанной к finally stage:
def run(extension, extensionAPI) {
println ("${currentBuild.number}") // Номер сборки в виде целого числа
println ("${currentBuild.result}") // Результат выполнения
println ("${currentBuild.absoluteUrl}") // URL-адрес индексной страницы сборки
}
def getDefaultConfig() {
return [
stage: 'finally',
phase: 'after',
description: 'Финальное расширение'
]
}
return this
Детали подключения расширения описаны в разделе Подключение и настройка расширений.
Настройка SAST/OSS#
В библиотеке ufs-pipeline существует возможность настроить анализ всех git-репозиториев на сканирование SAST и OSS. Для этого необходимо в pipeline.yml добавить настройки соответствующих инструментов:
### Настройки DevSecOps ###
### Общая информация о командах ###
team:
- # Код команды в МУС
# Если не сработает код команды в МУС, то можно попробовать прописать логин ТУЗа, который используется для сканирования
mus_code: "command_code"
# Название команды в МУС
mus_name: "command_name"
# Почтовый адрес Product Owner в МУС для уведомлений с результатами сканирования
# !!! Почта должна быть валидной для текущего домена, чтобы корректно определить пользователя, которому впоследствии предоставятся права на доступ к АС в SALM !!!
# !!! Возможно указание нескольких почт через знаки ";" или "," внутри одной строки !!!
# Пример: "user1@mycompany.com; user2@mycompany.com, user3@mycompany.com"
mus_po_mail: "user1@mycompany.com; user2@mycompany.com, user3@mycompany.com"
# Возможно добавление нескольких команд
# !!! Вторую и последующие команды необходимо добавить по формату, аналогичному первой !!!
# - mus_code: "00040018"
# mus_name: "Web"
# mus_po_mail: "user3@mycompany.com"
### Общая информация о приложении ###
app:
# Конфигурационный элемент (КЭ) приложения / модуля ПО в Service Manager.
# !!! КЭ должен быть строкой, состоящей исключительно из цифр без лидирующих нулей !!!
sm_id: "number_id"
# Название КЭ приложения / модуля ПО в Service Manager
sm_name: "app_name"
### Настройки SAST ###
sast_cx:
# Credentials ID в Jenkins для учетной записи одной команды, под которой будет проводиться сканирование
creds_id: "creds"
# Проектная область в JIRA для заведения и синхронизации дефектов
jira_area: "area"
# Маски файлов и директорий для включения (**/*) в скан и исключения (!**/*) из скана.
# Пример: "!**/utils/**/*.xml" - исключение всех xml файлов в папке utils
masks: ""
# ID профиля сканирования, по умолчанию 36. 14 - для мобильного приложения. 100003 - Smoke
preset_id: "36"
# Максимальное время ожидания статуса QG в минутах
wait_qg: "2"
### Настройки OSS
oss:
# Маски файлов и директорий для исключения из сканирования
# Пример: "**/utils/**/*.xml" - исключение всех xml файлов во всех папках utils
# !!! Перечисление нескольких масок возможно через знаки "," или ";" внутри одной строки, например, "**/*test*/**; **/*.txt, .git/**" !!!
# !!! Пропуски в каждой маске справа и слева автоматически удалятся (trim) !!!
excludes: ""
Также существует возможность исключить какой-либо из подключенных репозиториев из сканирования, добавив при этом опцию sast_skip: true.
Например (в данном случае сканирование не будет выполнено ни для одного из подключенных репозиториев):
jenkinsfiles:
- name: bh-jf
repo: cije/test.app.backend.git
branch: develop
sast_skip: true
pl:
- name: my-pl
repo: cije/test.app.frontend.git
branch: develop
cmd: 'npm pack'
sast_skip: true
downloads:
- source: git
type: conf
repo: cije/test.app.backend.git
branch: develop
files: pom.xml
sast_skip: true
Более подробную информацию по настройке параметров sast/oss можно запросить у подразделения кибербезопасности компании.
Непосредственно запуск проверок осуществляется включением сценариев run-sast, run-oss.