Browse Source

Improve null-safety of buildpack/spring-boot-buildpack-platform

See gh-46926
pull/46973/head
Moritz Halbritter 7 months ago
parent
commit
ca7e025dfd
  1. 8
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildOwner.java
  2. 6
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildpackCoordinates.java
  3. 8
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java
  4. 3
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListener.java
  5. 11
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java
  6. 8
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java
  7. 9
      buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageConfig.java
  8. 8
      core/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java

8
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildOwner.java

@ -18,6 +18,8 @@ package org.springframework.boot.buildpack.platform.build; @@ -18,6 +18,8 @@ package org.springframework.boot.buildpack.platform.build;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.buildpack.platform.io.Owner;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -38,7 +40,7 @@ class BuildOwner implements Owner { @@ -38,7 +40,7 @@ class BuildOwner implements Owner {
private final long gid;
BuildOwner(Map<String, String> env) {
BuildOwner(Map<String, @Nullable String> env) {
this.uid = getValue(env, USER_PROPERTY_NAME);
this.gid = getValue(env, GROUP_PROPERTY_NAME);
}
@ -48,7 +50,7 @@ class BuildOwner implements Owner { @@ -48,7 +50,7 @@ class BuildOwner implements Owner {
this.gid = gid;
}
private long getValue(Map<String, String> env, String name) {
private long getValue(Map<String, @Nullable String> env, String name) {
String value = env.get(name);
Assert.state(StringUtils.hasText(value),
() -> "Missing '" + name + "' value from the builder environment '" + env + "'");
@ -83,7 +85,7 @@ class BuildOwner implements Owner { @@ -83,7 +85,7 @@ class BuildOwner implements Owner {
* @return a {@link BuildOwner} instance extracted from the env
* @throws IllegalStateException if the env does not contain the correct CNB variables
*/
static BuildOwner fromEnv(Map<String, String> env) {
static BuildOwner fromEnv(Map<String, @Nullable String> env) {
Assert.notNull(env, "'env' must not be null");
return new BuildOwner(env);
}

6
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildpackCoordinates.java

@ -106,15 +106,15 @@ final class BuildpackCoordinates { @@ -106,15 +106,15 @@ final class BuildpackCoordinates {
private static BuildpackCoordinates fromToml(TomlParseResult toml, Path path) {
Assert.isTrue(!toml.isEmpty(),
() -> "Buildpack descriptor 'buildpack.toml' is required in buildpack '" + path + "'");
Assert.hasText(toml.getString("buildpack.id"),
() -> "Buildpack descriptor must contain ID in buildpack '" + path + "'");
String buildpackId = toml.getString("buildpack.id");
Assert.hasText(buildpackId, () -> "Buildpack descriptor must contain ID in buildpack '" + path + "'");
Assert.hasText(toml.getString("buildpack.version"),
() -> "Buildpack descriptor must contain version in buildpack '" + path + "'");
Assert.isTrue(toml.contains("stacks") || toml.contains("order"),
() -> "Buildpack descriptor must contain either 'stacks' or 'order' in buildpack '" + path + "'");
Assert.isTrue(!(toml.contains("stacks") && toml.contains("order")),
() -> "Buildpack descriptor must not contain both 'stacks' and 'order' in buildpack '" + path + "'");
return new BuildpackCoordinates(toml.getString("buildpack.id"), toml.getString("buildpack.version"));
return new BuildpackCoordinates(buildpackId, toml.getString("buildpack.version"));
}
/**

8
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java

@ -160,10 +160,12 @@ public class DockerApi { @@ -160,10 +160,12 @@ public class DockerApi {
}
private ApiVersion getApiVersion() {
if (this.apiVersion == null) {
this.apiVersion = this.system.getApiVersion();
ApiVersion apiVersion = this.apiVersion;
if (apiVersion == null) {
apiVersion = this.system.getApiVersion();
this.apiVersion = apiVersion;
}
return this.apiVersion;
return apiVersion;
}
/**

3
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListener.java

@ -105,6 +105,9 @@ public abstract class TotalProgressListener<E extends ImageProgressUpdateEvent> @@ -105,6 +105,9 @@ public abstract class TotalProgressListener<E extends ImageProgressUpdateEvent>
void update(ImageProgressUpdateEvent event) {
String status = event.getStatus();
if (status == null) {
return;
}
if (event.getProgressDetail() != null && this.progressByStatus.containsKey(status)) {
int current = this.progressByStatus.get(status);
this.progressByStatus.put(status, updateProgress(current, event.getProgressDetail()));

11
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java

@ -89,7 +89,7 @@ final class DockerConfigurationMetadata { @@ -89,7 +89,7 @@ final class DockerConfigurationMetadata {
return this.context;
}
DockerContext forContext(String context) {
DockerContext forContext(@Nullable String context) {
return createDockerContext(this.configLocation, context);
}
@ -129,8 +129,9 @@ final class DockerConfigurationMetadata { @@ -129,8 +129,9 @@ final class DockerConfigurationMetadata {
if (currentContext == null || DEFAULT_CONTEXT.equals(currentContext)) {
return DockerContext.empty();
}
Path metaPath = Path.of(configLocation, CONTEXTS_DIR, META_DIR, asHash(currentContext), CONTEXT_FILE_NAME);
Path tlsPath = Path.of(configLocation, CONTEXTS_DIR, TLS_DIR, asHash(currentContext), DOCKER_ENDPOINT);
String hash = asHash(currentContext);
Path metaPath = Path.of(configLocation, CONTEXTS_DIR, META_DIR, hash, CONTEXT_FILE_NAME);
Path tlsPath = Path.of(configLocation, CONTEXTS_DIR, TLS_DIR, hash, DOCKER_ENDPOINT);
if (!metaPath.toFile().exists()) {
throw new IllegalArgumentException("Docker context '" + currentContext + "' does not exist");
}
@ -146,14 +147,14 @@ final class DockerConfigurationMetadata { @@ -146,14 +147,14 @@ final class DockerConfigurationMetadata {
}
}
private static @Nullable String asHash(String currentContext) {
private static String asHash(String currentContext) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(currentContext.getBytes(StandardCharsets.UTF_8));
return HexFormat.of().formatHex(hash);
}
catch (NoSuchAlgorithmException ex) {
return null;
throw new IllegalStateException("SHA-256 is not available", ex);
}
}

8
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java

@ -115,11 +115,11 @@ final class PemPrivateKeyParser { @@ -115,11 +115,11 @@ final class PemPrivateKeyParser {
private PemPrivateKeyParser() {
}
private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, @Nullable String password) {
return createKeySpecForAlgorithm(bytes, RSA_ALGORITHM, null);
}
private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, @Nullable String password) {
DerElement ecPrivateKey = DerElement.of(bytes);
Assert.state(ecPrivateKey != null, "Unable to find private key");
Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE),
@ -164,7 +164,7 @@ final class PemPrivateKeyParser { @@ -164,7 +164,7 @@ final class PemPrivateKeyParser {
}
}
private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, @Nullable String password) {
DerElement ecPrivateKey = DerElement.of(bytes);
Assert.state(ecPrivateKey != null, "Unable to find private key");
Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE),
@ -182,7 +182,7 @@ final class PemPrivateKeyParser { @@ -182,7 +182,7 @@ final class PemPrivateKeyParser {
return (algorithmName != null) ? new PKCS8EncodedKeySpec(bytes, algorithmName) : new PKCS8EncodedKeySpec(bytes);
}
private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, @Nullable String password) {
return Pkcs8PrivateKeyDecryptor.decrypt(bytes, password);
}

9
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageConfig.java

@ -24,6 +24,7 @@ import java.util.function.Consumer; @@ -24,6 +24,7 @@ import java.util.function.Consumer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.buildpack.platform.json.MappedObject;
@ -38,7 +39,7 @@ public class ImageConfig extends MappedObject { @@ -38,7 +39,7 @@ public class ImageConfig extends MappedObject {
private final Map<String, String> labels;
private final Map<String, String> configEnv;
private final Map<String, @Nullable String> configEnv;
ImageConfig(JsonNode node) {
super(node, MethodHandles.lookup());
@ -55,12 +56,12 @@ public class ImageConfig extends MappedObject { @@ -55,12 +56,12 @@ public class ImageConfig extends MappedObject {
return labels;
}
private Map<String, String> parseConfigEnv() {
private Map<String, @Nullable String> parseConfigEnv() {
String[] entries = valueAt("/Env", String[].class);
if (entries == null) {
return Collections.emptyMap();
}
Map<String, String> env = new LinkedHashMap<>();
Map<String, @Nullable String> env = new LinkedHashMap<>();
for (String entry : entries) {
int i = entry.indexOf('=');
String name = (i != -1) ? entry.substring(0, i) : entry;
@ -88,7 +89,7 @@ public class ImageConfig extends MappedObject { @@ -88,7 +89,7 @@ public class ImageConfig extends MappedObject {
* an empty {@code Map} is returned.
* @return the env, never {@code null}
*/
public Map<String, String> getEnv() {
public Map<String, @Nullable String> getEnv() {
return this.configEnv;
}

8
core/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java

@ -115,11 +115,11 @@ final class PemPrivateKeyParser { @@ -115,11 +115,11 @@ final class PemPrivateKeyParser {
private PemPrivateKeyParser() {
}
private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, @Nullable String password) {
return createKeySpecForAlgorithm(bytes, RSA_ALGORITHM, null);
}
private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, @Nullable String password) {
DerElement ecPrivateKey = DerElement.of(bytes);
Assert.state(ecPrivateKey != null, "Unable to find private key");
Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE),
@ -164,7 +164,7 @@ final class PemPrivateKeyParser { @@ -164,7 +164,7 @@ final class PemPrivateKeyParser {
}
}
private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, @Nullable String password) {
DerElement ecPrivateKey = DerElement.of(bytes);
Assert.state(ecPrivateKey != null, "Unable to find private key");
Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE),
@ -182,7 +182,7 @@ final class PemPrivateKeyParser { @@ -182,7 +182,7 @@ final class PemPrivateKeyParser {
return (algorithmName != null) ? new PKCS8EncodedKeySpec(bytes, algorithmName) : new PKCS8EncodedKeySpec(bytes);
}
private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, String password) {
private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, @Nullable String password) {
return Pkcs8PrivateKeyDecryptor.decrypt(bytes, password);
}

Loading…
Cancel
Save