Featured image of post Установка Harbor в docker-compose

Установка Harbor в docker-compose

Установка оффлайн Harbor в закрытый контур

Harbor - это бесплатный реестр для хранения Docker образов. Умеет сканировать образы на уязвимости. Проект запущен в 2016 году командой VMware. В 2018 Harbor перешел под контроль организации CNCF и с тех пор активно развивается, поэтому новые релизы выходят несколько раз в месяц.

Зачем он нужен?
Хранить образы контейнеров в Docker Hub конечно удобно, но 99% компаний хранят их приватно на своих серверах.
Но хранить на своих серверах это половина, другое дело делать это в закрытом контуре компании, где нет интернета.
Этот гайд именно про такую установку. Основные отличия установки: переменные закрывающие обновление сканеру уязвимостей Trivy и ручное обогащение баз. В остальном всё тоже самое.

Собираю единомышленников в телеграм канале - Присоединяйся Telegram

Шаг 1. Установка Harbor

Шаг 1.1 Ставим docker

Ставим docker и compose:

1
2
3
4
apt update && \
apt install containerd docker.io docker-compose -y`
systemctl enable docker --now && \
sudo usermod -aG docker $USER

Шаг 1.2 Скачиваем Harbor и готовим конфиги

Клонируем репозиторий. Обернул в переменные, чтобы версия файла была всегда актуальна:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
LATEST=$(curl -s https://api.github.com/repos/goharbor/harbor/releases/latest \
  | grep browser_download_url \
  | grep offline-installer \
  | cut -d '"' -f 4)

FILE=$(basename "$LATEST")

wget "$LATEST" && \
tar xvzf "$FILE" && \
rm "$FILE" && \
cd harbor

Создаём файл .env:

1
sudo nano .env

Прописываем в переменных пароль Админа и БД:

1
2
HARBOR_ADMIN_PASSWORD=super_admin_pazzword
DB_PASSWORD=super_db_mazafaka

Изменяем права:

1
sudo chmod 600 .env

Далее работаем с файлом harbor.yml
Создаём резервную копию файла:

1
sudo cp harbor.yml.copy harbor.yml

Чтобы хосты доверяли этому репозиторию нужно создать серты в Центре Сертификатов (CA).

1
2
3
4
5
Создайте сертификаты в вашем ЦА с именами:
harbor.example.local.key
harbor.example.local.crt
где harbor.example.local доменное имя вашего будущего репозитория.
Или перейдите на Шаг 3, затем вернитесь сюда.

Открываем на редактирование:

1
sudo nano /opt/harbor/harbor.yml

Удаляем содержимое файла и вставляем параметры:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
hostname: harbor.example.local
http:
  port: 80
https:
  port: 443
  certificate: /opt/harbor/harbor.example.local.crt
  private_key: /opt/harbor/harbor.example.local.key
harbor_admin_password: ${HARBOR_ADMIN_PASSWORD}
database:
  password: ${DB_PASSWORD}
  max_idle_conns: 200
  max_open_conns: 100
  conn_max_lifetime: 5m
  conn_max_idle_time: 5m
data_volume: /data
trivy:
  ignore_unfixed: false       
  skip_update: true           #Если есть инет, то ставь false
  skip_java_db_update: true   #Если есть инет, то ставь false
  offline_scan: true          #Если есть инет, то ставь false
  security_check: vuln
  insecure: false
  timeout: 5m0s
jobservice:
  max_job_workers: 10
  max_job_duration_hours: 24
  job_loggers:
    - STD_OUTPUT
    - FILE
  logger_sweeper_duration: 1 #days
notification:
  webhook_job_max_retry: 3
  webhook_job_http_client_timeout: 3 #seconds
log:
  level: info
  local:
    rotate_count: 50
    rotate_size: 200M
    location: /var/log/harbor
_version: 2.14.0
proxy:
  http_proxy:
  https_proxy:
  no_proxy:
  components:
    - core
    - jobservice
    - trivy
upload_purging:
  enabled: true
  age: 168h
  interval: 24h
  dryrun: false
cache:
  enabled: false
  expire_hours: 24

Мой Harbor работает в закрытом контуре (без доступа к интернету). Что это значит?
Это значит что базы сканера уязвимостей Trivy встроенного в него не будут обновляться напрямую, а только вручную (Шаг 4). Настройки конфигурации я делал исходи из этого требования.

Шаг 2. Запуск установки

Без дополнительных параметров (–with) компонент не установится:

1
sudo ./install.sh --with-trivy

Шаг 2.1 Вход в UI

После установки мы можем войти по адресу, который вы указали. В моём случае https://harbor.example.local Логин и пароль мы задавали в .env файле

Шаг 3. Создание ЦА и подписание сертификата

Создаём директорию:

1
2
sudo mkdir -p ~/harbor/certs
sudo cd ~/harbor/certs

Создаём серты ЦА:

1
2
3
4
5
6
7
# Root CA key
openssl genrsa -out root-ca.key 4096

# Root CA cert (10 лет, можно меньше)
openssl req -x509 -new -nodes -sha256 -days 3650 \
  -key root-ca.key -out root-ca.crt \
  -subj "/C=RU/ST=Moscow/L=Moscow/O=HomeLab/OU=ITZM/CN=My-Root-CA"

Изменить значение перменных на своё имя и IP Harbor сервера:

1
2
export HARBOR_HOST=harbor.example.local
export MyIP=2.2.2.2

Выполнить команды:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# server key
openssl genrsa -out ${HARBOR_HOST}.key 4096

# csr config with SAN
cat > ${HARBOR_HOST}.csr.cnf <<EOF
[req]
default_bits       = 4096
prompt             = no
default_md         = sha256
distinguished_name = dn
req_extensions     = req_ext

[dn]
C=RU
ST=Moscow
L=Moscow
O=HomeLab
OU=ITZM
CN=${HARBOR_HOST}

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = ${HARBOR_HOST}
IP.1  = ${MyIP}
EOF

# create CSR
openssl req -new -key ${HARBOR_HOST}.key -out ${HARBOR_HOST}.csr -config ${HARBOR_HOST}.csr.cnf

# sign server cert by our CA
openssl x509 -req -in ${HARBOR_HOST}.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial \
  -out ${HARBOR_HOST}.crt -days 825 -sha256 \
  -extensions req_ext -extfile ${HARBOR_HOST}.csr.cnf

На выходе: root-ca.crt - корневой сертификат, который надо раздать всем клиентам/нодам.
${HARBOR_HOST}.crt и ${HARBOR_HOST}.key - серверные для Harbor

Корневой скопировать на все хосты:
Ubuntu

1
2
3
/usr/local/share/ca-certificates/
# Применить:
sudo update-ca-certificates

CentOS

1
2
3
/etc/pki/ca-trust/source/anchors/
# Применить:
sudo update-ca-trust extract

Перезапустить докер на хостах:

1
systemctl restart docker.service

Шаг 4. Оффлайн обновление Trivy

Сканер уязвимостей Trivy требует регулярных обновлений.
В данном примере мы выкачаем базу уязвимостей, а затем перенесем на закрытый контур.
Дальше можно автоматизировать обновления скриптом и т.д. на вашу фантазию.
Есть например вариант, поднять Harbor в контуре с инетом и в контуре без него и настроить репликацию между ними.

На компе с инетом ставим докер и качаем обновления:

1
2
3
4
apt update && \
apt install docker.io -y`
systemctl enable docker --now && \
sudo usermod -aG docker $USER

Далее выкачиваем образы:

1
2
docker pull ghcr.io/aquasecurity/trivy-db:2
docker pull ghcr.io/aquasecurity/trivy-java-db:1

После чего упаковываем:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# DB
cid=$(docker create ghcr.io/aquasecurity/trivy-db:2)
docker cp $cid:/db db
docker rm $cid

# Java DB
cid=$(docker create ghcr.io/aquasecurity/trivy-java-db:1)
docker cp $cid:/java-db java-db
docker rm $cid

tar czf trivy-db.tgz db
tar czf trivy-java-db.tgz java-db

Переносим на Harbor-хост, где нет инета и распаковать в контейнер trivy-adapter:

1
2
3
4
5
6
sudo mkdir -p /data/trivy-adapter/trivy/db
sudo mkdir -p /data/trivy-adapter/trivy/java-db
sudo tar -xzf trivy-db.tgz -C /data/trivy-adapter/trivy/db
sudo tar -xzf trivy-java-db.tgz -C /data/trivy-adapter/trivy/java-db
sudo chown -R 10000:10000 /data/trivy-adapter/trivy 2>/dev/null || true
docker restart trivy-adapter

Сканирование работает.

Информацию можно использовать в свободном доступе, с указанием ссылки на сайт
Telegram GitHub YouTube