mirror of https://github.com/apache/maven.git
[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:
parent
4b0dd4362a
commit
1614226c68
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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<>();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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>");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<settingsSecurity>
|
||||||
|
<master>{1wQaa6S/o8MH7FnaTNL53XmhT5O0SEGXQi3gC49o6OY=}</master>
|
||||||
|
</settingsSecurity>
|
|
@ -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>
|
2
pom.xml
2
pom.xml
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue