Fixed PEM Keys issue

This commit is contained in:
2026-08-01 09:51:36 +05:30
parent f264f90f3b
commit dcb6850306
15 changed files with 217 additions and 150 deletions

View File

@@ -30,6 +30,7 @@ public class DeploymentWriter {
try {
Path normalizedOutput = output.toAbsolutePath().normalize();
Path config = normalizedOutput.resolve("config");
protectCloudConfiguration(config, profile);
Path keyDirectory = config.resolve("keys");
Files.createDirectories(keyDirectory);
@@ -82,6 +83,23 @@ public class DeploymentWriter {
}
}
private void protectCloudConfiguration(Path deploymentConfig, ProductProfile profile) {
if (isInside(deploymentConfig, profile.assertionEncryptionPublicKey())
|| isInside(deploymentConfig, profile.loginEncryptionPublicKey())) {
throw new IllegalArgumentException(
"Refusing to write deployment files over the cloud-service "
+ "configuration directory");
}
}
private boolean isInside(Path directory, Path file) {
if (file == null) {
return false;
}
return file.toAbsolutePath().normalize().startsWith(
directory.toAbsolutePath().normalize());
}
private String installationConfiguration(
UUID installationUuid,
String installationCode,

View File

@@ -156,6 +156,7 @@ public class InstallationService {
if (request.outputDirectory() == null) {
throw new IllegalArgumentException("Output directory is required");
}
validateOutputIsolation(request.outputDirectory());
RuntimeConfiguration runtime = request.runtimeConfiguration();
if (runtime == null) {
throw new IllegalArgumentException("Runtime configuration is required");
@@ -204,6 +205,27 @@ public class InstallationService {
}
}
private void validateOutputIsolation(Path outputDirectory) {
Path deploymentConfig = outputDirectory
.toAbsolutePath()
.normalize()
.resolve("config");
if (isInside(deploymentConfig, profile.assertionEncryptionPublicKey())
|| isInside(deploymentConfig, profile.loginEncryptionPublicKey())) {
throw new IllegalArgumentException(
"Output directory would overwrite the cloud-service config folder. "
+ "Select a dedicated deployment directory, such as "
+ "'matrix-installation'.");
}
}
private boolean isInside(Path directory, Path file) {
if (file == null) {
return false;
}
return file.toAbsolutePath().normalize().startsWith(directory);
}
private String normalizedCloudServiceUrl(String value) {
String normalized = value.trim();
return normalized.endsWith("/")

View File

@@ -1,6 +1,7 @@
package com.cygnus.installer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.net.URI;
import java.nio.file.Files;
@@ -121,4 +122,84 @@ class DeploymentWriterTest {
assertThat(output.resolve("config/keys/client-signing-private.pem"))
.isRegularFile();
}
@Test
void refusesToOverwriteCloudServiceConfiguration() throws Exception {
Path cloudConfig = temporaryDirectory.resolve("config");
Path cloudKeys = cloudConfig.resolve("keys");
Files.createDirectories(cloudKeys);
Path assertionPublic = cloudKeys.resolve("assertion-decryption-public.pem");
Path loginPublic = cloudKeys.resolve("login-public.pem");
Files.writeString(assertionPublic, "assertion-public-key");
Files.writeString(loginPublic, "login-public-key");
var profile = new ProductProfile(
"matrix",
"Matrix",
"matrix-onprem",
"MATRIX_IMAGE",
"matrix",
"installation.yml",
"MATRIX_INSTALLATION_CONFIG",
"/srv/matrix/config/installation.yml",
"8080:8080",
"/matrix/",
"/oauth2/token",
assertionPublic,
loginPublic,
"cygnus-login-2026-01",
List.of());
assertThatThrownBy(() -> new DeploymentWriter().write(
temporaryDirectory,
UUID.randomUUID(),
"primary",
"matrix-client",
new ActivationDtos.ValidationResponse(
"activation-token",
OffsetDateTime.now().plusMinutes(5),
UUID.randomUUID(),
"matrix-client",
"FULL",
2),
new ActivationDtos.RegistrationResponse(
UUID.randomUUID(),
UUID.randomUUID(),
UUID.randomUUID(),
null,
"primary",
1,
"ACTIVE"),
new InstallationKeyService().generate(),
"assertion",
new InstallerSettings(
"matrix",
URI.create("https://cloud.example.com"),
URI.create("https://cloud.example.com"),
"/api/v1/installations",
"production",
temporaryDirectory,
temporaryDirectory,
"1",
new IniDocument(Map.of())),
profile,
"registry.example.com/matrix:1.0.0",
Map.of(),
new RuntimeConfiguration(
"https://cloud.example.com",
"jdbc:postgresql://db/matrix",
"postgres",
"secret",
"redis",
"7901",
"secret",
false,
"PT10S",
"PT30S")))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("cloud-service configuration");
assertThat(assertionPublic).hasContent("assertion-public-key");
assertThat(loginPublic).hasContent("login-public-key");
}
}