[MNG-8379] Decrypt all of settings on building it (#1913)

The decryption should happen transparently, also, resolver should not decrypt for itself only, whole maven should have access to all.

This PR also disables Maven 3.0 IT MNG-4459 as Maven4 stops with this "security through obscurity" (keep encrypted pw in memory kinda for "security reasons" but in reality any mojo or extension can decrypt anything they want).

---

https://issues.apache.org/jira/browse/MNG-8379
This commit is contained in:
Tamas Cservenak 2024-11-16 14:55:43 +01:00 committed by GitHub
parent 4b0dd4362a
commit 1614226c68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 355 additions and 49 deletions

View File

@ -46,7 +46,7 @@ public class DefaultSettingsDecrypter implements SettingsDecrypter {
private final SecDispatcher securityDispatcher; private final SecDispatcher securityDispatcher;
@Inject @Inject
public DefaultSettingsDecrypter(SecDispatcher securityDispatcher) { public DefaultSettingsDecrypter(MavenSecDispatcher securityDispatcher) {
this.securityDispatcher = securityDispatcher; this.securityDispatcher = securityDispatcher;
} }

View File

@ -18,14 +18,13 @@
*/ */
package org.apache.maven.cling.invoker.mvnenc; package org.apache.maven.cling.invoker.mvnenc;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.Prompter; import org.apache.maven.api.services.Prompter;
import org.apache.maven.api.services.PrompterException; import org.apache.maven.api.services.PrompterException;
import org.codehaus.plexus.components.secdispatcher.MasterSource; import org.codehaus.plexus.components.secdispatcher.MasterSource;

View File

@ -47,10 +47,6 @@ import org.apache.maven.rtinfo.RuntimeInformation;
import org.apache.maven.settings.Mirror; import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Proxy; import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server; import org.apache.maven.settings.Server;
import org.apache.maven.settings.building.SettingsProblem;
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.ConfigurationProperties;
import org.eclipse.aether.RepositoryListener; import org.eclipse.aether.RepositoryListener;
@ -123,8 +119,6 @@ public class DefaultRepositorySystemSessionFactory implements RepositorySystemSe
private final RepositorySystem repoSystem; private final RepositorySystem repoSystem;
private final SettingsDecrypter settingsDecrypter;
private final EventSpyDispatcher eventSpyDispatcher; private final EventSpyDispatcher eventSpyDispatcher;
private final RuntimeInformation runtimeInformation; private final RuntimeInformation runtimeInformation;
@ -141,7 +135,6 @@ public class DefaultRepositorySystemSessionFactory implements RepositorySystemSe
@Inject @Inject
DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory(
RepositorySystem repoSystem, RepositorySystem repoSystem,
SettingsDecrypter settingsDecrypter,
EventSpyDispatcher eventSpyDispatcher, EventSpyDispatcher eventSpyDispatcher,
RuntimeInformation runtimeInformation, RuntimeInformation runtimeInformation,
TypeRegistry typeRegistry, TypeRegistry typeRegistry,
@ -149,7 +142,6 @@ public class DefaultRepositorySystemSessionFactory implements RepositorySystemSe
Map<String, MavenExecutionRequestExtender> requestExtenders, Map<String, MavenExecutionRequestExtender> requestExtenders,
Map<String, RepositorySystemSessionExtender> sessionExtenders) { Map<String, RepositorySystemSessionExtender> sessionExtenders) {
this.repoSystem = repoSystem; this.repoSystem = repoSystem;
this.settingsDecrypter = settingsDecrypter;
this.eventSpyDispatcher = eventSpyDispatcher; this.eventSpyDispatcher = eventSpyDispatcher;
this.runtimeInformation = runtimeInformation; this.runtimeInformation = runtimeInformation;
this.typeRegistry = typeRegistry; this.typeRegistry = typeRegistry;
@ -211,22 +203,6 @@ public class DefaultRepositorySystemSessionFactory implements RepositorySystemSe
sessionBuilder.setVersionFilter(versionFilter); sessionBuilder.setVersionFilter(versionFilter);
} }
DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
decrypt.setProxies(request.getProxies());
decrypt.setServers(request.getServers());
SettingsDecryptionResult decrypted = settingsDecrypter.decrypt(decrypt);
for (SettingsProblem problem : decrypted.getProblems()) {
if (problem.getSeverity() == SettingsProblem.Severity.WARNING) {
logger.warn(problem.getMessage());
} else if (problem.getSeverity() == SettingsProblem.Severity.ERROR) {
logger.error(
problem.getMessage(),
request.isShowErrors()
? problem.getException()
: problem.getException().getMessage());
}
}
DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector(); DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
for (Mirror mirror : request.getMirrors()) { for (Mirror mirror : request.getMirrors()) {
mirrorSelector.add( mirrorSelector.add(
@ -241,7 +217,7 @@ public class DefaultRepositorySystemSessionFactory implements RepositorySystemSe
sessionBuilder.setMirrorSelector(mirrorSelector); sessionBuilder.setMirrorSelector(mirrorSelector);
DefaultProxySelector proxySelector = new DefaultProxySelector(); DefaultProxySelector proxySelector = new DefaultProxySelector();
for (Proxy proxy : decrypted.getProxies()) { for (Proxy proxy : request.getProxies()) {
AuthenticationBuilder authBuilder = new AuthenticationBuilder(); AuthenticationBuilder authBuilder = new AuthenticationBuilder();
authBuilder.addUsername(proxy.getUsername()).addPassword(proxy.getPassword()); authBuilder.addUsername(proxy.getUsername()).addPassword(proxy.getPassword());
proxySelector.add( proxySelector.add(
@ -254,7 +230,7 @@ public class DefaultRepositorySystemSessionFactory implements RepositorySystemSe
// Note: we do NOT use WagonTransportConfigurationKeys here as Maven Core does NOT depend on Wagon Transport // Note: we do NOT use WagonTransportConfigurationKeys here as Maven Core does NOT depend on Wagon Transport
// and this is okay and "good thing". // and this is okay and "good thing".
DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector(); DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
for (Server server : decrypted.getServers()) { for (Server server : request.getServers()) {
AuthenticationBuilder authBuilder = new AuthenticationBuilder(); AuthenticationBuilder authBuilder = new AuthenticationBuilder();
authBuilder.addUsername(server.getUsername()).addPassword(server.getPassword()); authBuilder.addUsername(server.getUsername()).addPassword(server.getPassword());
authBuilder.addPrivateKey(server.getPrivateKey(), server.getPassphrase()); authBuilder.addPrivateKey(server.getPrivateKey(), server.getPassphrase());

View File

@ -36,7 +36,6 @@ import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.internal.impl.DefaultTypeRegistry; import org.apache.maven.internal.impl.DefaultTypeRegistry;
import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.rtinfo.RuntimeInformation;
import org.apache.maven.settings.Server; import org.apache.maven.settings.Server;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.testing.PlexusTest; import org.codehaus.plexus.testing.PlexusTest;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
@ -69,9 +68,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
@Inject @Inject
protected EventSpyDispatcher eventSpyDispatcher; protected EventSpyDispatcher eventSpyDispatcher;
@Inject
protected SettingsDecrypter settingsDecrypter;
@Inject @Inject
protected org.eclipse.aether.RepositorySystem aetherRepositorySystem; protected org.eclipse.aether.RepositorySystem aetherRepositorySystem;
@ -88,7 +84,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
void isNoSnapshotUpdatesTest() throws InvalidRepositoryException { void isNoSnapshotUpdatesTest() throws InvalidRepositoryException {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -112,7 +107,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
void isSnapshotUpdatesTest() throws InvalidRepositoryException { void isSnapshotUpdatesTest() throws InvalidRepositoryException {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -148,7 +142,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -192,7 +185,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -230,7 +222,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -272,7 +263,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -308,7 +298,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -350,7 +339,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -369,7 +357,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
void transportConfigurationTest() throws InvalidRepositoryException { void transportConfigurationTest() throws InvalidRepositoryException {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,
@ -416,7 +403,6 @@ public class DefaultRepositorySystemSessionFactoryTest {
void versionFilteringTest() throws InvalidRepositoryException { void versionFilteringTest() throws InvalidRepositoryException {
DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory( DefaultRepositorySystemSessionFactory systemSessionFactory = new DefaultRepositorySystemSessionFactory(
aetherRepositorySystem, aetherRepositorySystem,
settingsDecrypter,
eventSpyDispatcher, eventSpyDispatcher,
information, information,
defaultTypeRegistry, defaultTypeRegistry,

View File

@ -109,6 +109,10 @@ under the License.
<groupId>org.apache.maven.resolver</groupId> <groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId> <artifactId>maven-resolver-impl</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-sec-dispatcher</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>

View File

@ -51,6 +51,7 @@ import org.apache.maven.api.settings.Settings;
import org.apache.maven.internal.impl.model.DefaultInterpolator; import org.apache.maven.internal.impl.model.DefaultInterpolator;
import org.apache.maven.settings.v4.SettingsMerger; import org.apache.maven.settings.v4.SettingsMerger;
import org.apache.maven.settings.v4.SettingsTransformer; import org.apache.maven.settings.v4.SettingsTransformer;
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
/** /**
* Builds the effective settings from a user settings file and/or a global settings file. * Builds the effective settings from a user settings file and/or a global settings file.
@ -65,13 +66,23 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
private final Interpolator interpolator; private final Interpolator interpolator;
private final SecDispatcher secDispatcher;
/**
* This ctor is used in legacy components, and when in legacy, {@link SecDispatcher} is {@code null} and
* Maven3 exposes decryption with other means.
*/
public DefaultSettingsBuilder() { public DefaultSettingsBuilder() {
this(new DefaultInterpolator()); this(new DefaultInterpolator(), null);
} }
/**
* In Maven4 the {@link SecDispatcher} is injected and build settings are fully decrypted as well.
*/
@Inject @Inject
public DefaultSettingsBuilder(Interpolator interpolator) { public DefaultSettingsBuilder(Interpolator interpolator, SecDispatcher secDispatcher) {
this.interpolator = interpolator; this.interpolator = interpolator;
this.secDispatcher = secDispatcher;
} }
@Override @Override
@ -198,6 +209,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
} }
settings = interpolate(settings, request, problems); settings = interpolate(settings, request, problems);
settings = decrypt(settingsSource, settings, request, problems);
settingsValidator.validate(settings, isProjectSettings, problems); settingsValidator.validate(settings, isProjectSettings, problems);
@ -237,6 +249,41 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
.visit(settings); .visit(settings);
} }
private Settings decrypt(
Source settingsSource, Settings settings, SettingsBuilderRequest request, List<BuilderProblem> problems) {
if (secDispatcher == null) {
return settings;
}
Function<String, String> decryptFunction = str -> {
if (secDispatcher.isAnyEncryptedString(str)) {
if (secDispatcher.isLegacyEncryptedString(str)) {
// add a problem
problems.add(new DefaultBuilderProblem(
settingsSource.getLocation(),
-1,
-1,
null,
"Pre-Maven 4 legacy encrypted password detected "
+ " - configure password encryption with the help of mvnenc to be compatible with Maven 4.",
BuilderProblem.Severity.WARNING));
}
try {
return secDispatcher.decrypt(str);
} catch (Exception e) {
problems.add(new DefaultBuilderProblem(
settingsSource.getLocation(),
-1,
-1,
e,
"Could not decrypt password (fix the corrupted password or remove it, if unused) " + str,
BuilderProblem.Severity.ERROR));
}
}
return str;
};
return new SettingsTransformer(decryptFunction).visit(settings);
}
@Override @Override
public List<BuilderProblem> validate(Settings settings, boolean isProjectSettings) { public List<BuilderProblem> validate(Settings settings, boolean isProjectSettings) {
ArrayList<BuilderProblem> problems = new ArrayList<>(); ArrayList<BuilderProblem> problems = new ArrayList<>();

View File

@ -0,0 +1,106 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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.apache.maven.internal.impl.secdispatcher;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import org.apache.maven.api.Constants;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Provides;
import org.codehaus.plexus.components.secdispatcher.Cipher;
import org.codehaus.plexus.components.secdispatcher.Dispatcher;
import org.codehaus.plexus.components.secdispatcher.MasterSource;
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
import org.codehaus.plexus.components.secdispatcher.internal.DefaultSecDispatcher;
import org.codehaus.plexus.components.secdispatcher.internal.cipher.AESGCMNoPadding;
import org.codehaus.plexus.components.secdispatcher.internal.dispatchers.LegacyDispatcher;
import org.codehaus.plexus.components.secdispatcher.internal.dispatchers.MasterDispatcher;
import org.codehaus.plexus.components.secdispatcher.internal.sources.EnvMasterSource;
import org.codehaus.plexus.components.secdispatcher.internal.sources.GpgAgentMasterSource;
import org.codehaus.plexus.components.secdispatcher.internal.sources.PinEntryMasterSource;
import org.codehaus.plexus.components.secdispatcher.internal.sources.SystemPropertyMasterSource;
/**
* Delegate that offers just the minimal surface needed to decrypt settings.
*/
@SuppressWarnings("unused")
@Named
public class SecDispatcherProvider {
private static final String FILE_NAME = "settings-security4.xml";
@Provides
public static SecDispatcher secDispatcher(Map<String, Dispatcher> dispatchers) {
return new DefaultSecDispatcher(dispatchers, configurationFile());
}
@Provides
@Named(LegacyDispatcher.NAME)
public static Dispatcher legacyDispatcher() {
return new LegacyDispatcher();
}
@Provides
@Named(MasterDispatcher.NAME)
public static Dispatcher masterDispatcher(
Map<String, Cipher> masterCiphers, Map<String, MasterSource> masterSources) {
return new MasterDispatcher(masterCiphers, masterSources);
}
@Provides
@Named(AESGCMNoPadding.CIPHER_ALG)
public static Cipher aesGcmNoPaddingCipher() {
return new AESGCMNoPadding();
}
@Provides
@Named(EnvMasterSource.NAME)
public static MasterSource envMasterSource() {
return new EnvMasterSource();
}
@Provides
@Named(GpgAgentMasterSource.NAME)
public static MasterSource gpgAgentMasterSource() {
return new GpgAgentMasterSource();
}
@Provides
@Named(PinEntryMasterSource.NAME)
public static MasterSource pinEntryMasterSource() {
return new PinEntryMasterSource();
}
@Provides
@Named(SystemPropertyMasterSource.NAME)
public static MasterSource systemPropertyMasterSource() {
return new SystemPropertyMasterSource();
}
private static Path configurationFile() {
String mavenUserConf = System.getProperty(Constants.MAVEN_USER_CONF);
if (mavenUserConf != null) {
return Paths.get(mavenUserConf, FILE_NAME);
}
// this means we are in UT or alike
return Paths.get(System.getProperty("user.home"), ".m2", FILE_NAME);
}
}

View File

@ -34,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class MavenITmng4459InMemorySettingsKeptEncryptedTest extends AbstractMavenIntegrationTestCase { public class MavenITmng4459InMemorySettingsKeptEncryptedTest extends AbstractMavenIntegrationTestCase {
public MavenITmng4459InMemorySettingsKeptEncryptedTest() { public MavenITmng4459InMemorySettingsKeptEncryptedTest() {
super("[2.1.0,3.0-alpha-1),[3.0-alpha-5,)"); super("[2.1.0,3.0-alpha-1),[3.0-alpha-5,4.0.0-beta-6)");
} }
/** /**

View File

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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.apache.maven.it;
import java.io.File;
import org.apache.maven.shared.verifier.util.ResourceExtractor;
import org.junit.jupiter.api.Test;
/**
* This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-8379">MNG-8379</a>.
*/
class MavenITmng8379SettingsDecryptTest extends AbstractMavenIntegrationTestCase {
MavenITmng8379SettingsDecryptTest() {
super("[4.0.0-beta-6,)");
}
/**
* Verify that all settings are decrypted
*/
@Test
void testLegacy() throws Exception {
File testDir = ResourceExtractor.simpleExtractResources(getClass(), "/mng-8379-decrypt-settings");
Verifier verifier = newVerifier(testDir.getAbsolutePath());
verifier.setLogFileName("log-legacy.txt");
verifier.setForkJvm(true);
ItUtils.setUserHome(verifier, new File(testDir, "legacyhome"));
verifier.addCliArgument("org.apache.maven.plugins:maven-help-plugin:3.3.0:effective-settings");
verifier.addCliArgument("-DshowPasswords");
verifier.execute();
verifier.verifyErrorFreeLog();
// there is a warning and all fields decrypted
verifier.verifyTextInLog("[WARNING] Pre-Maven 4 legacy encrypted password detected");
verifier.verifyTextInLog("<password>testtest</password>");
verifier.verifyTextInLog("<value>testtest</value>");
}
/**
* Verify that all settings are decrypted
*/
@Test
void testModern() throws Exception {
File testDir = ResourceExtractor.simpleExtractResources(getClass(), "/mng-8379-decrypt-settings");
Verifier verifier = newVerifier(testDir.getAbsolutePath());
verifier.setLogFileName("log-modern.txt");
verifier.setForkJvm(true);
verifier.setEnvironmentVariable("MAVEN_MASTER_PASSWORD", "master");
ItUtils.setUserHome(verifier, new File(testDir, "home"));
verifier.addCliArgument("org.apache.maven.plugins:maven-help-plugin:3.3.0:effective-settings");
verifier.addCliArgument("-DshowPasswords");
verifier.execute();
verifier.verifyErrorFreeLog();
// there is no warning and all fields decrypted
verifier.verifyTextInLog("<password>testtest</password>");
verifier.verifyTextInLog("<value>secretHeader</value>");
}
}

View File

@ -100,6 +100,7 @@ public class TestSuiteOrdering implements ClassOrderer {
* the tests are to finishing. Newer tests are also more likely to fail, so this is * the tests are to finishing. Newer tests are also more likely to fail, so this is
* a fail fast technique as well. * a fail fast technique as well.
*/ */
suite.addTestSuite(MavenITmng8379SettingsDecryptTest.class);
suite.addTestSuite(MavenITmng8336UnknownPackagingTest.class); suite.addTestSuite(MavenITmng8336UnknownPackagingTest.class);
suite.addTestSuite(MavenITmng8340GeneratedPomInTargetTest.class); suite.addTestSuite(MavenITmng8340GeneratedPomInTargetTest.class);
suite.addTestSuite(MavenITmng8360SubprojectProfileActivationTest.class); suite.addTestSuite(MavenITmng8360SubprojectProfileActivationTest.class);

View File

@ -0,0 +1,9 @@
# MNG-8379 IT Settings Decryption
## legacyhome:
master pw: unsure what (copied from MNG-0553)
server "test": testuser/testtest and secret-header "testest"
## home
master pw: master
server "test": testuser/testtest and secret-header "secretHeader"

View File

@ -0,0 +1,20 @@
<?xml version='1.0' encoding='UTF-8'?>
<settingsSecurity xmlns="http://codehaus-plexus.github.io/plexus-sec-dispatcher/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://codehaus-plexus.github.io/plexus-sec-dispatcher/4.0.0 https://codehaus-plexus.github.io/xsd/plexus-sec-dispatcher-4.0.0.xsd">
<modelVersion>4.0</modelVersion>
<defaultDispatcher>master</defaultDispatcher>
<configurations>
<configuration>
<name>master</name>
<properties>
<property>
<name>source</name>
<value>env:MAVEN_MASTER_PASSWORD</value>
</property>
<property>
<name>cipher</name>
<value>AES/GCM/NoPadding</value>
</property>
</properties>
</configuration>
</configurations>
</settingsSecurity>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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
http://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.
-->
<settings>
<servers>
<server>
<id>test</id>
<username>testuser</username>
<password>{[name=master,cipher=AES/GCM/NoPadding,version=4.0]w+C6vJwryWolUYkLtAMCkMGCWfB09haER/AiingAH4NEDr37euLdwMYYLvxaSQe/97OJ+A==}</password>
<configuration>
<httpHeaders>
<property>
<name>secret-header</name>
<value>{[name=master,cipher=AES/GCM/NoPadding,version=4.0]/EbAnkmLQnYmz75KTY+5+A4iG/N9AAE8o/SvaWy/E/gOIcyDBuJ5DDFeNj0SI4rtVGPnDbFOHis=}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<settingsSecurity>
<master>{1wQaa6S/o8MH7FnaTNL53XmhT5O0SEGXQi3gC49o6OY=}</master>
</settingsSecurity>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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
http://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.
-->
<settings>
<servers>
<server>
<id>testserver</id>
<username>testuser</username>
<password>{BteqUEnqHecHM7MZfnj9FwLcYbdInWxou1C929Txa0A=}</password>
<configuration>
<httpHeaders>
<property>
<name>secret-header</name>
<value>{BteqUEnqHecHM7MZfnj9FwLcYbdInWxou1C929Txa0A=}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>

View File

@ -163,7 +163,7 @@ under the License.
<plexusTestingVersion>1.4.0</plexusTestingVersion> <plexusTestingVersion>1.4.0</plexusTestingVersion>
<plexusXmlVersion>4.0.4</plexusXmlVersion> <plexusXmlVersion>4.0.4</plexusXmlVersion>
<resolverVersion>2.0.3</resolverVersion> <resolverVersion>2.0.3</resolverVersion>
<securityDispatcherVersion>4.0.1</securityDispatcherVersion> <securityDispatcherVersion>4.0.2</securityDispatcherVersion>
<sisuVersion>0.9.0.M3</sisuVersion> <sisuVersion>0.9.0.M3</sisuVersion>
<slf4jVersion>2.0.16</slf4jVersion> <slf4jVersion>2.0.16</slf4jVersion>
<stax2ApiVersion>4.2.2</stax2ApiVersion> <stax2ApiVersion>4.2.2</stax2ApiVersion>