Maven
Configure Maven and Gradle to resolve dependencies through your firewall. Mirror setup, authentication, CI, publishing, and troubleshooting.
A Maven firewall implements the Maven repository layout. Maven and Gradle both resolve and publish through it.
The examples use <namespace-id> and <firewall-id> placeholders. Replace them with IDs, not with namespace or firewall names. XML examples use NAMESPACE_ID and FIREWALL_ID so the files stay valid XML before you replace them. The firewall's Setup tab shows a ready-to-copy Maven snippet with both values already filled in. This page also covers Gradle, whose configuration is not generated in the dashboard.
Repository endpoint
https://eu-sov-1.bytesafecloud.eu/v1/<namespace-id>/maven/<firewall-id>/The namespace ID and firewall ID are part of the URL. Authentication is a bearer token header for resolution; publishing also accepts HTTP basic auth with the token as the password.
Configure the project
Mirror everything through the firewall in ~/.m2/settings.xml (or a checked-in settings file passed with -s). Maven sends credentials from the <server> whose ID matches the mirror:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
<mirrors>
<mirror>
<id>firewall</id>
<name>Bytesafe Dependency Firewall</name>
<url>https://eu-sov-1.bytesafecloud.eu/v1/NAMESPACE_ID/maven/FIREWALL_ID/</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>firewall</id>
<configuration>
<httpHeaders>
<property>
<name>Authorization</name>
<value>Bearer ${env.BYTESAFE_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>mirrorOf: * routes every repository, including plugin repositories, through the firewall.
Replace the repository block in build.gradle (or settings.gradle under dependencyResolutionManagement):
repositories {
maven {
url = uri('https://eu-sov-1.bytesafecloud.eu/v1/<namespace-id>/maven/<firewall-id>/')
credentials(HttpHeaderCredentials) {
name = 'Authorization'
value = "Bearer ${System.getenv('BYTESAFE_TOKEN')}"
}
authentication {
header(HttpHeaderAuthentication)
}
}
}Remove mavenCentral() and other repository entries. Gradle tries repositories in order, and any direct entry is a firewall bypass.
Each developer exports a personal access token:
export BYTESAFE_TOKEN=<your token>Verify
mvn dependency:resolvegradle dependenciesA successful resolution confirms the firewall is serving the artifacts, and every request through that repository is evaluated against your rules.
Do not expect a log entry from this. A request is logged only when it matches a
rule with log: true or a logging exception, so a build that breaks no rule
leaves no trace. An empty log is not evidence that the build bypassed the
firewall. To see the requests while verifying setup, add a log-only rule that
matches all packages. See What is logged when.
CI
Use a Service Access Token (SAT) instead of a PAT. Set it as a secret in your CI system and export it as BYTESAFE_TOKEN before build steps.
To correlate all requests from one pipeline run, append an interaction ID to the token:
export BYTESAFE_TOKEN="${BYTESAFE_TOKEN}::${CI_PIPELINE_ID}"The ID shows up on every log entry from that run.
Publishing
A firewall can receive mvn deploy and gradle publish. First set a publish target: the upstream that should receive published artifacts. Without one the firewall is install-only and rejects publishes. Then publish with the firewall as the repository. Upload rules run against the publish before it is forwarded.
<distributionManagement>
<repository>
<id>firewall</id>
<url>https://eu-sov-1.bytesafecloud.eu/v1/NAMESPACE_ID/maven/FIREWALL_ID/</url>
</repository>
</distributionManagement>With basic-auth credentials on the matching server. The token goes in the password field; the username is not checked, so deploy here is only a label:
<server>
<id>firewall</id>
<username>deploy</username>
<password>${env.BYTESAFE_TOKEN}</password>
</server>publishing {
repositories {
maven {
url = uri('https://eu-sov-1.bytesafecloud.eu/v1/<namespace-id>/maven/<firewall-id>/')
credentials {
username = 'deploy'
password = System.getenv('BYTESAFE_TOKEN')
}
}
}
}A blocked publish fails with:
com.acme:app@1.0.0 upload blocked. Check firewall log entries for request <request-id> for detailsWhat a blocked install looks like
Rules on the versions phase filter versions out of maven-metadata.xml. Maven and Gradle dependencies are usually exact versions, so the practical effects are:
- Version ranges and
LATEST/RELEASEstyle resolution pick the newest version that passed the rules. - An exact dependency on a filtered version fails as not found (
Could not find artifactin Maven,Could not resolvein Gradle).
Rules on the download phase block the artifact fetch. The firewall returns a 404 with:
com.acme:app@1.0.0 is blocked. Check firewall log entries for request <request-id> for detailsTake the request ID to the logs to see which rule fired. See Investigate a blocked install.
Maven Central caching
Responses from Maven Central (repo1.maven.org, repo.maven.apache.org) are always cached by the firewall, regardless of the upstream's cache setting. Maven Central rate-limits heavy traffic with 429 Too Many Requests; the always-on cache keeps repeat resolutions from counting against that limit. Cache misses are fetched with automatic failover, so a throttling or failing Central does not break the resolution. This is automatic; there is nothing to configure. Other upstreams are cached when the upstream has caching enabled, which applies to internal upstreams. See Upstreams and caching.
Troubleshooting
BYTESAFE_TOKEN is unset, expired, or revoked, or the <server> ID does not match the mirror ID, in which case Maven never attaches the header at all. Confirm the variable is set in the shell that runs the build, that both IDs are identical, and that the token is still listed and unexpired in the dashboard.
A 429 in your build output means the build is talking to Maven Central directly, not through the firewall; Central throttles heavy or unauthenticated traffic. Fix the bypass (see below) and the problem disappears: the firewall always caches Maven Central responses, so repeat resolutions are served from cache instead of hitting Central, and cache misses are fetched with automatic failover when Central throttles.
Most likely a versions rule filtered it. Because Maven dependencies are exact versions, a filtered version fails the build instead of resolving to an older one. Check the firewall logs before assuming an upstream problem.
No log entry does not by itself mean the build bypassed the firewall. Approved
packages that match no logging rule pass through without an entry. First test
with a log-only rule matching the package or all packages. If that rule still
does not produce an entry, check for <repositories> in POMs (a mirrorOf: *
mirror catches these, a narrower one may not) and extra repositories blocks
in Gradle builds, including settings.gradle plugin management.
Plugin repositories go through the firewall too. With Maven, mirrorOf: * covers them. With Gradle, add the firewall repository to pluginManagement.repositories in settings.gradle as well.