Polish "Support authentication to private Docker registry"
See gh-22972
This commit is contained in:
@@ -59,6 +59,37 @@ On Linux and macOS, these environment variables can be set using the command `ev
|
||||
|
||||
|
||||
|
||||
[[build-image-docker-registry]]
|
||||
=== Docker Registry
|
||||
If the Docker images specified by the `builder` or `runImage` parameters are stored in a private Docker image registry that requires authentication, the authentication credentials can be provided using `docker.registry` parameters.
|
||||
Parameters are provided for user authentication or identity token authentication.
|
||||
Consult the documentation for the Docker registry being used to store builder or run images for further information on supported authentication methods.
|
||||
|
||||
The following table summarizes the available parameters:
|
||||
|
||||
|===
|
||||
| Parameter | Description
|
||||
|
||||
| `username`
|
||||
| Username for the Docker image registry user. Required for user authentication.
|
||||
|
||||
| `password`
|
||||
| Password for the Docker image registry user. Required for user authentication.
|
||||
|
||||
| `url`
|
||||
| Address of the Docker image registry. Optional for user authentication.
|
||||
|
||||
| `email`
|
||||
| E-mail address for the Docker image registry user. Optional for user authentication.
|
||||
|
||||
| `token`
|
||||
| Identity token for the Docker image registry user. Required for token authentication.
|
||||
|===
|
||||
|
||||
For more details, see also <<build-image-example-docker,examples>>.
|
||||
|
||||
|
||||
|
||||
[[build-image-customization]]
|
||||
=== Image Customizations
|
||||
The plugin invokes a {buildpacks-reference}/concepts/components/builder/[builder] to orchestrate the generation of an image.
|
||||
@@ -252,3 +283,57 @@ The image name can be specified on the command line as well, as shown in this ex
|
||||
$ mvn spring-boot:build-image -Dspring-boot.build-image.imageName=example.com/library/my-app:v1
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[build-image-example-docker]]
|
||||
==== Docker Configuration
|
||||
If the builder or run image are stored in a private Docker registry that supports user authentication, authentication details can be provided as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
<project>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>{gradle-project-version}</version>
|
||||
<configuration>
|
||||
<docker>
|
||||
<registry>
|
||||
<username>user</username>
|
||||
<password>secret</password>
|
||||
<url>https://docker.example.com/v1/</url>
|
||||
<email>user@example.com</email>
|
||||
</registry>
|
||||
</docker>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
----
|
||||
|
||||
If the builder or run image is stored in a private Docker registry that supports token authentication, the token value can be provided as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
<project>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>{gradle-project-version}</version>
|
||||
<configuration>
|
||||
<docker>
|
||||
<registry>
|
||||
<token>9cbaf023786cd7...</token>
|
||||
</registry>
|
||||
</docker>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
----
|
||||
|
||||
@@ -159,8 +159,8 @@ public class BuildImageMojo extends AbstractPackagerMojo {
|
||||
private void buildImage() throws MojoExecutionException {
|
||||
Libraries libraries = getLibraries(Collections.emptySet());
|
||||
try {
|
||||
DockerConfiguration dockerConfiguration = (this.docker != null) ? this.docker.getDockerConfiguration()
|
||||
: new DockerConfiguration();
|
||||
DockerConfiguration dockerConfiguration = (this.docker != null) ? this.docker.asDockerConfiguration()
|
||||
: null;
|
||||
Builder builder = new Builder(new MojoBuildLog(this::getLog), dockerConfiguration);
|
||||
BuildRequest request = getBuildRequest(libraries);
|
||||
builder.build(request);
|
||||
|
||||
@@ -17,37 +17,116 @@
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerConfiguration;
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerRegistryConfiguration;
|
||||
|
||||
/**
|
||||
* Docker configuration options.
|
||||
*
|
||||
* @author Wei Jiang
|
||||
* @author Scott Frederick
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public class Docker {
|
||||
|
||||
/**
|
||||
* The docker registry configuration.
|
||||
*/
|
||||
private DockerRegistry registry;
|
||||
|
||||
public DockerRegistry getRegistry() {
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link DockerRegistry} that configures registry authentication.
|
||||
* @param registry the registry configuration
|
||||
*/
|
||||
public void setRegistry(DockerRegistry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public DockerConfiguration getDockerConfiguration() {
|
||||
DockerRegistryConfiguration dockerRegistryConfiguration = null;
|
||||
|
||||
if (this.registry != null) {
|
||||
dockerRegistryConfiguration = this.registry.getDockerRegistryConfiguration();
|
||||
/**
|
||||
* Returns this configuration as a {@link DockerConfiguration} instance. This method
|
||||
* should only be called when the configuration is complete and will no longer be
|
||||
* changed.
|
||||
* @return the Docker configuration
|
||||
*/
|
||||
DockerConfiguration asDockerConfiguration() {
|
||||
if (this.registry == null || this.registry.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (this.registry.hasTokenAuth() && !this.registry.hasUserAuth()) {
|
||||
return DockerConfiguration.withRegistryTokenAuthentication(this.registry.getToken());
|
||||
}
|
||||
if (this.registry.hasUserAuth() && !this.registry.hasTokenAuth()) {
|
||||
return DockerConfiguration.withRegistryUserAuthentication(this.registry.getUsername(),
|
||||
this.registry.getPassword(), this.registry.getUrl(), this.registry.getEmail());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid Docker registry configuration, either token or username/password must be provided");
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates Docker registry authentication configuration options.
|
||||
*/
|
||||
public static class DockerRegistry {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String url;
|
||||
|
||||
private String email;
|
||||
|
||||
private String token;
|
||||
|
||||
String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
String getEmail() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return this.username == null && this.password == null && this.url == null && this.email == null
|
||||
&& this.token == null;
|
||||
}
|
||||
|
||||
boolean hasTokenAuth() {
|
||||
return this.token != null;
|
||||
}
|
||||
|
||||
boolean hasUserAuth() {
|
||||
return this.username != null && this.password != null;
|
||||
}
|
||||
|
||||
return new DockerConfiguration(dockerRegistryConfiguration);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerRegistryConfiguration;
|
||||
|
||||
/**
|
||||
* Docker registry configuration options.
|
||||
*
|
||||
* @author Wei Jiang
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public class DockerRegistry {
|
||||
|
||||
/**
|
||||
* Docker registry server address.
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* Docker registry authentication username.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Docker registry authentication password.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Docker registry authentication email.
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Docker registry authentication identity token.
|
||||
*/
|
||||
private String token;
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public DockerRegistryConfiguration getDockerRegistryConfiguration() {
|
||||
return new DockerRegistryConfiguration(this.url, this.username, this.password, this.email, this.token);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerRegistryConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link DockerRegistry}.
|
||||
*
|
||||
* @author Wei Jiang
|
||||
*/
|
||||
public class DockerRegistryTests {
|
||||
|
||||
@Test
|
||||
void getDockerRegistryConfiguration() {
|
||||
DockerRegistry dockerRegistry = new DockerRegistry();
|
||||
dockerRegistry.setUsername("username");
|
||||
dockerRegistry.setPassword("password");
|
||||
dockerRegistry.setEmail("mock@spring.com");
|
||||
dockerRegistry.setUrl("http://mock.docker.registry");
|
||||
DockerRegistryConfiguration dockerRegistryConfiguration = dockerRegistry.getDockerRegistryConfiguration();
|
||||
assertThat(dockerRegistryConfiguration).isNotNull();
|
||||
assertThat(dockerRegistryConfiguration.getUsername()).isEqualTo(dockerRegistry.getUsername());
|
||||
assertThat(dockerRegistryConfiguration.getPassword()).isEqualTo(dockerRegistry.getPassword());
|
||||
assertThat(dockerRegistryConfiguration.getEmail()).isEqualTo(dockerRegistry.getEmail());
|
||||
assertThat(dockerRegistryConfiguration.getUrl()).isEqualTo(dockerRegistry.getUrl());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerConfiguration;
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerRegistryAuthentication;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link Docker}.
|
||||
*
|
||||
* @author Wei Jiang
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
public class DockerTests {
|
||||
|
||||
@Test
|
||||
void asDockerConfigurationWithoutRegistry() {
|
||||
Docker docker = new Docker();
|
||||
assertThat(docker.asDockerConfiguration()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void asDockerConfigurationWithEmptyRegistry() {
|
||||
Docker.DockerRegistry dockerRegistry = new Docker.DockerRegistry();
|
||||
Docker docker = new Docker();
|
||||
docker.setRegistry(dockerRegistry);
|
||||
assertThat(docker.asDockerConfiguration()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void asDockerConfigurationWithUserAuth() {
|
||||
Docker.DockerRegistry dockerRegistry = new Docker.DockerRegistry();
|
||||
dockerRegistry.setUsername("user");
|
||||
dockerRegistry.setPassword("secret");
|
||||
dockerRegistry.setUrl("https://docker.example.com");
|
||||
dockerRegistry.setEmail("docker@example.com");
|
||||
Docker docker = new Docker();
|
||||
docker.setRegistry(dockerRegistry);
|
||||
DockerConfiguration dockerConfiguration = docker.asDockerConfiguration();
|
||||
DockerRegistryAuthentication registryAuthentication = dockerConfiguration.getRegistryAuthentication();
|
||||
assertThat(registryAuthentication).isNotNull();
|
||||
assertThat(new String(Base64Utils.decodeFromString(registryAuthentication.createAuthHeader())))
|
||||
.contains("\"username\" : \"user\"").contains("\"password\" : \"secret\"")
|
||||
.contains("\"email\" : \"docker@example.com\"")
|
||||
.contains("\"serveraddress\" : \"https://docker.example.com\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void asDockerConfigurationWithIncompleteUserAuthFails() {
|
||||
Docker.DockerRegistry dockerRegistry = new Docker.DockerRegistry();
|
||||
dockerRegistry.setUsername("user");
|
||||
dockerRegistry.setUrl("https://docker.example.com");
|
||||
dockerRegistry.setEmail("docker@example.com");
|
||||
Docker docker = new Docker();
|
||||
docker.setRegistry(dockerRegistry);
|
||||
assertThatIllegalArgumentException().isThrownBy(docker::asDockerConfiguration)
|
||||
.withMessageContaining("Invalid Docker registry configuration");
|
||||
}
|
||||
|
||||
@Test
|
||||
void asDockerConfigurationWithTokenAuth() {
|
||||
Docker.DockerRegistry dockerRegistry = new Docker.DockerRegistry();
|
||||
dockerRegistry.setToken("token");
|
||||
Docker docker = new Docker();
|
||||
docker.setRegistry(dockerRegistry);
|
||||
DockerConfiguration dockerConfiguration = docker.asDockerConfiguration();
|
||||
DockerRegistryAuthentication registryAuthentication = dockerConfiguration.getRegistryAuthentication();
|
||||
assertThat(registryAuthentication).isNotNull();
|
||||
assertThat(new String(Base64Utils.decodeFromString(registryAuthentication.createAuthHeader())))
|
||||
.contains("\"identitytoken\" : \"token\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void asDockerConfigurationWithUserAndTokenAuthFails() {
|
||||
Docker.DockerRegistry dockerRegistry = new Docker.DockerRegistry();
|
||||
dockerRegistry.setUsername("user");
|
||||
dockerRegistry.setPassword("secret");
|
||||
dockerRegistry.setToken("token");
|
||||
Docker docker = new Docker();
|
||||
docker.setRegistry(dockerRegistry);
|
||||
assertThatIllegalArgumentException().isThrownBy(docker::asDockerConfiguration)
|
||||
.withMessageContaining("Invalid Docker registry configuration");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user