Как отключить доступ к central

Варианты отключения доступа к репозиторию Maven Central в отдельном проекте.

Предисловие

Работа на крупных проектах часто связана с необходимостью соблюдать различные требования, в том числе мириться с ограничениями от службы информационной безопасности. Одним из таких ограничений в последнее время стал запрет на свободное использование артефактов с центрального maven репозитория. При этом часто происходит переход от автоматического проксирования на “ручной” процесс загрузки отдельных артефактов, в том числе с привлечением выделенной группы, которая рассматривает специальные заявки.

В итоге появляется необходимость исключить расхождение между сборкой проекта локально и на CI в закрытом контуре.

Варианты решения проблемы

Все варианты основываются на создании отдельного конфигурационного файла maven. Альтернативы из серии “заблокировать адрес на уровне hosts или маршрутов сети” в большинстве случаев не подходят, так как ограничение надо реализовать только для отдельного проекта.

По запросу Disable Maven central чаще всего обсуждают два варианта:

  1. переопределение адреса
  2. указание зеркала

Сперва их и рассмотрим.

Переопределение адреса репозитория central

Необходимо указать адрес внутреннего репозитория, куда происходит загрузка внешних артефактов.

settings-disable-central.xml v1
 1<?xml version="1.0" encoding="UTF-8"?>
 2<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
 5
 6    <profiles>
 7        <profile>
 8            <repositories>
 9                <repository>
10                    <id>central</id>
11                    <name>Private Nexus Common Repository</name>
12                    <url>https://akorolev.dev/repository/common/</url>
13                </repository>
14             </repositories>
15            <pluginRepositories>
16                <pluginRepository>
17                    <id>central</id>
18                    <name>Private Nexus Common Plugin Repository</name>
19                    <url>https://akorolev.dev/repository/common/</url>
20                </pluginRepository>
21            </pluginRepositories>
22            <activation>
23                <activeByDefault>true</activeByDefault>
24            </activation>
25        </profile>
26    </profiles>
27    <localRepository>D:/.m2/local_repository</localRepository>
28</settings>

На первый взгляд данное решение выглядит подходящим, но надо учитывать один важный момент. В локальном репозитории создаются файлы _remote.repositories, в которые записывается идентификатор источника загрузки.

При сборках maven проверяет, что источник ранее сохраненного артефакта присутствует в текущем контексте. Если в изолированных проектах переопределить central с разными адресами, но при этом использовать одно локальное хранилище, то можно подключить зависимость из “другого проекта”.

Использование зеркала для репозитория central

Можно заменить переопределение репозиториев на добавление зеркала.

settings-disable-central.xml v2
 1<?xml version="1.0" encoding="UTF-8"?>
 2<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
 5
 6    <mirrors>
 7        <mirror>
 8            <id>private-nexus-mock-external</id>
 9            <mirrorOf>central</mirrorOf>
10            <name>Repository to mock external</name>
11            <url>https://akorolev.dev/repository/common/</url>
12        </mirror>
13    </mirrors>
14
15    <localRepository>D:/.m2/local_repository</localRepository>
16</settings>

В метаинформацию по источнику загрузки артефакта будет добавляться уже не идентификатор репозитория, а идентификатор зеркала: private-nexus-mock-external. Это устранит возможность возникновения проблемы с некорректным определением доступности в текущем контексте сборки, если избегать создание зеркал с одинаковым именем, но разными адресами.

Блокировка репозитория central

В целом, предыдущий вариант решает необходимую задачу и можно воспользоваться им.

Есть только “концептуальный” момент, что https://akorolev.dev/repository/common/ — это не зеркало внешних репозиториев, а внутреннее хранилище организации. В первую очередь пространство предназначено для корпоративных библиотек общего назначения, в которое дополнительно загружаются отдельные внешние зависимости по мере потребностей.

Если используется Maven версии 3.8.1 и выше, то можно попробовать альтернативный вариант. В данном релизе была обновлена xml-модель файла настроек и элемент mirror обзавелся вложенным blocked.

settings-disable-central.xml v3
 1<?xml version="1.0" encoding="UTF-8"?>
 2<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
 5
 6    <mirrors>
 7        <mirror>
 8            <id>maven-central-blocker</id>
 9            <mirrorOf>central</mirrorOf>
10            <name>Pseudo repository to block the central repository</name>
11            <url>http://0.0.0.0/</url>
12            <blocked>true</blocked>
13        </mirror>
14    </mirrors>
15    <profiles>
16        <profile>
17            <repositories>
18                <repository>
19                    <id>private-nexus-common</id>
20                    <name>Private Nexus Common Repository</name>
21                    <url>https://akorolev.dev/repository/common/</url>
22                </repository>
23            </repositories>
24            <pluginRepositories>
25                <pluginRepository>
26                    <id>private-nexus-common</id>
27                    <name>Private Nexus Common Plugin Repository</name>
28                    <url>https://akorolev.dev/repository/common/</url>
29                </pluginRepository>
30            </pluginRepositories>
31            <activation>
32                <activeByDefault>true</activeByDefault>
33            </activation>
34        </profile>
35    </profiles>
36    <localRepository>D:/.m2/local_repository</localRepository>
37</settings>
Если при такой конфигурации сборщик будет доходить до обращения к central репозиторию, то в логи будут выводиться соответствующие предупреждения Blocked mirror for repositories: [central (https://repo.maven.apache.org/maven2, default, releases)], а сборка будет падать в ошибку.

Но на данном варианте тоже была замечена проблема при использовании достаточно старых версий плагинов. Например, flatten-maven-plugin версии 1.1.0 (21 декабря 2018 г.) стабильно пытался проверить доступность через заблокированное зеркало, так как ошибочно считал, что ранее закешированный артефакт загружен с недоступного в текущем контексте репозитория. Хотя его банальное обновление до следующей версии 1.2.1 (18 января 2020 г.) устранило данную проблему и проект начинал собираться корректно.