Skip to content

Commit edcb07a

Browse files
committed
Add MavenPasswordDecrypter
1 parent 3cc5ded commit edcb07a

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.sbm.project.parser;
17+
18+
import lombok.RequiredArgsConstructor;
19+
import org.apache.maven.settings.Server;
20+
import org.apache.maven.settings.crypto.*;
21+
import org.openrewrite.maven.MavenSettings;
22+
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
23+
import org.sonatype.plexus.components.cipher.PlexusCipherException;
24+
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
25+
import org.springframework.sbm.testhelper.ResourceUtil;
26+
import org.springframework.stereotype.Component;
27+
import org.springframework.util.ReflectionUtils;
28+
29+
import java.lang.reflect.Field;
30+
import java.nio.file.Path;
31+
import java.util.List;
32+
33+
/**
34+
* Decrypt Maven Server passwords.
35+
*
36+
* Requires access to Maven security settings file (~/.settings-security.xml) to decrypt the server passwords provided in
37+
* the server settings in Maven settings file (~/.m2/settings.xml) which are provided with {@link MavenSettings}.
38+
*
39+
* @author Fabian Krüger
40+
*/
41+
@Component
42+
@RequiredArgsConstructor
43+
// TODO: should be package private
44+
public class MavenPasswordDecrypter {
45+
private DefaultSecDispatcher securityDispatcher = new DefaultSecDispatcher();
46+
private final SettingsDecrypter settingsDecrypter = new DefaultSettingsDecrypter(securityDispatcher);
47+
48+
public void decryptMavenServerPasswords(MavenSettings mavenSettings, Path mavenSecuritySettingsFile) {
49+
try {
50+
// DefaultSecDispatcher reads file with security settings
51+
// hack, the cipher is required but can't be set from outside
52+
Field cipher1 = ReflectionUtils.findField(DefaultSecDispatcher.class, "_cipher");
53+
//Field cipher = ReflectionUtils.getField(cipher1, securityDispatcher);
54+
ReflectionUtils.makeAccessible(cipher1);
55+
ReflectionUtils.setField(cipher1, securityDispatcher, new DefaultPlexusCipher());
56+
// The file location is retrieved from env, default is ~/${user.home}/.settings-security.xml
57+
System.setProperty("settings.security", mavenSecuritySettingsFile.toString());
58+
decryptMavenServerPasswords(mavenSettings);
59+
} catch (PlexusCipherException e) {
60+
throw new RuntimeException(e);
61+
}
62+
}
63+
64+
65+
private void decryptMavenServerPasswords(MavenSettings mavenSettings) {
66+
if(mavenSettings.getServers() != null && mavenSettings.getServers().getServers() != null) {
67+
List<MavenSettings.Server> servers = mavenSettings.getServers().getServers();
68+
for(int i = 0; i< servers.size(); i++){
69+
MavenSettings.Server server = servers.get(i);
70+
if(server.getPassword() != null) {
71+
MavenSettings.Server serverWithDecodedPw = decryptPassword(server);
72+
servers.set(i, serverWithDecodedPw);
73+
}
74+
}
75+
}
76+
}
77+
78+
private MavenSettings.Server decryptPassword(MavenSettings.Server server) {
79+
Server mavenServer = new Server();
80+
mavenServer.setPassword(server.getPassword());
81+
SettingsDecryptionRequest decryptionRequest = new DefaultSettingsDecryptionRequest(mavenServer);
82+
SettingsDecryptionResult decryptionResult = settingsDecrypter.decrypt(decryptionRequest);
83+
String decryptedPassword = decryptionResult.getServer().getPassword();
84+
return server.withPassword(decryptedPassword);
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.springframework.sbm.project.parser;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.io.TempDir;
5+
import org.openrewrite.internal.lang.Nullable;
6+
import org.openrewrite.maven.MavenSettings;
7+
import org.springframework.sbm.project.parser.MavenPasswordDecrypter;
8+
9+
import java.io.IOException;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.util.ArrayList;
13+
14+
import static org.assertj.core.api.Assertions.assertThat;
15+
16+
/**
17+
* @author Fabian Krüger
18+
*/
19+
class MavenPasswordDecrypterTest {
20+
21+
@Test
22+
void decryptMavenServerPasswords(@TempDir Path tempDir) throws IOException {
23+
MavenPasswordDecrypter sut = new MavenPasswordDecrypter();
24+
25+
// create MavenSettings with Server using an encrypted password
26+
MavenSettings.@Nullable Servers serversWithPassword = new MavenSettings.Servers();
27+
String encryptedPassword = "{gY56I8DPBrwHu3dWkh+EGDqp+ppuTnBaWe9fNpdTPIw=}";
28+
MavenSettings.Server serverWithPassword = new MavenSettings.Server("id", "username", encryptedPassword);
29+
ArrayList servers = new ArrayList<>();
30+
servers.add(serverWithPassword);
31+
serversWithPassword.setServers(servers);
32+
MavenSettings mavenSettings = new MavenSettings(null, null, null, null, serversWithPassword);
33+
34+
// Write Maven security settings file to file system
35+
// Required because {@link DefaultSecDispatcher} uses SecUtil which reads the file from
36+
// provided location
37+
Path mavenSecurityFilePath = tempDir.resolve(".settings-security.xml");
38+
String mavenSecurityFileContent = """
39+
<settingsSecurity>
40+
<master>{H39p2LFBhRQHqKIsRiu0R/zhfke3/B4k0Wt+BZlC8mc=}</master>
41+
</settingsSecurity>
42+
""";
43+
Files.writeString(mavenSecurityFilePath, mavenSecurityFileContent);
44+
45+
// Server has encrypted password
46+
assertThat(mavenSettings.getServers().getServers().get(0).getPassword()).isEqualTo(encryptedPassword);
47+
// call system under test
48+
sut.decryptMavenServerPasswords(mavenSettings, mavenSecurityFilePath);
49+
// password has been decrypted
50+
assertThat(mavenSettings.getServers().getServers().get(0).getPassword()).isEqualTo("xxx");
51+
}
52+
}

0 commit comments

Comments
 (0)