Skip to content

Commit 0f7a316

Browse files
committed
Don't require config for the forwarding dispatcher
Allow to use arbitrary master sources in a mix & match fashion Some refactoring
1 parent 5f0a83b commit 0f7a316

File tree

4 files changed

+178
-156
lines changed

4 files changed

+178
-156
lines changed

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/dispatchers/ForwardingDispatcher.java

Lines changed: 0 additions & 143 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (c) 2008 Sonatype, Inc. All rights reserved.
3+
*
4+
* This program is licensed to you under the Apache License Version 2.0,
5+
* and you may not use this file except in compliance with the Apache License Version 2.0.
6+
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7+
*
8+
* Unless required by applicable law or agreed to in writing,
9+
* software distributed under the Apache License Version 2.0 is distributed on an
10+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12+
*/
13+
14+
package org.codehaus.plexus.components.secdispatcher.internal.dispatchers;
15+
16+
import javax.inject.Inject;
17+
import javax.inject.Named;
18+
import javax.inject.Singleton;
19+
20+
import java.util.ArrayList;
21+
import java.util.Collection;
22+
import java.util.Collections;
23+
import java.util.HashMap;
24+
import java.util.List;
25+
import java.util.Map;
26+
import java.util.Objects;
27+
import java.util.Optional;
28+
29+
import org.codehaus.plexus.components.secdispatcher.Dispatcher;
30+
import org.codehaus.plexus.components.secdispatcher.DispatcherMeta;
31+
import org.codehaus.plexus.components.secdispatcher.MasterSource;
32+
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
33+
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
34+
35+
/**
36+
* This dispatcher does not actually do any crypto operations, but just forwards the string to be decrypted
37+
* to a {@link MasterSource}. The given string is supposed to contain a valid source reference which is resolvable
38+
* by one of the bound {@link MasterSource} implementations (and not actually an encrypted value).
39+
* This dispatcher doesn't support encrypting but just returns a given master source
40+
*/
41+
@Singleton
42+
@Named(MasterSourceLookupDispatcher.NAME)
43+
public class MasterSourceLookupDispatcher implements Dispatcher, DispatcherMeta {
44+
public static final String NAME = "masterSourceLookup";
45+
46+
protected final Collection<MasterSource> sources;
47+
48+
@Inject
49+
public MasterSourceLookupDispatcher(Collection<MasterSource> sources) {
50+
this.sources = sources;
51+
}
52+
53+
@Override
54+
public String name() {
55+
return NAME;
56+
}
57+
58+
@Override
59+
public String displayName() {
60+
return "Master Source Lookup Dispatcher";
61+
}
62+
63+
@Override
64+
public Collection<Field> fields() {
65+
return Collections.emptyList();
66+
}
67+
68+
@Override
69+
public EncryptPayload encrypt(String str, Map<String, String> attributes, Map<String, String> config)
70+
throws SecDispatcherException {
71+
// just make sure the given string is a valid reference!
72+
decrypt(str, attributes, config);
73+
return new EncryptPayload(attributes, str);
74+
}
75+
76+
@Override
77+
public String decrypt(String str, Map<String, String> attributes, Map<String, String> config)
78+
throws SecDispatcherException {
79+
Optional<String> plain = sources.stream()
80+
.map(source -> source.handle(str))
81+
.filter(Objects::nonNull)
82+
.findFirst();
83+
if (plain.isPresent()) {
84+
return plain.get();
85+
} else {
86+
throw new SecDispatcherException("No master source found for : " + str);
87+
}
88+
}
89+
90+
@Override
91+
public SecDispatcher.ValidationResponse validateConfiguration(Map<String, String> config) {
92+
// there is nothing really to validate without having a master reference at hand (which is outside the config)
93+
HashMap<SecDispatcher.ValidationResponse.Level, List<String>> report = new HashMap<>();
94+
ArrayList<SecDispatcher.ValidationResponse> subsystems = new ArrayList<>();
95+
report.computeIfAbsent(SecDispatcher.ValidationResponse.Level.INFO, k -> new ArrayList<>())
96+
.add("Configured Source configuration valid");
97+
return new SecDispatcher.ValidationResponse(getClass().getSimpleName(), true, report, subsystems);
98+
}
99+
}

src/test/java/org/codehaus/plexus/components/secdispatcher/internal/DefaultSecDispatcherTest.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
import java.nio.file.Files;
1919
import java.nio.file.Path;
2020
import java.nio.file.Paths;
21+
import java.util.Collections;
22+
import java.util.List;
2123
import java.util.Map;
2224

2325
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
2426
import org.codehaus.plexus.components.secdispatcher.internal.cipher.AESGCMNoPadding;
25-
import org.codehaus.plexus.components.secdispatcher.internal.dispatchers.ForwardingDispatcher;
2627
import org.codehaus.plexus.components.secdispatcher.internal.dispatchers.LegacyDispatcher;
2728
import org.codehaus.plexus.components.secdispatcher.internal.dispatchers.MasterDispatcher;
29+
import org.codehaus.plexus.components.secdispatcher.internal.dispatchers.MasterSourceLookupDispatcher;
2830
import org.codehaus.plexus.components.secdispatcher.internal.sources.EnvMasterSource;
2931
import org.codehaus.plexus.components.secdispatcher.internal.sources.GpgAgentMasterSource;
3032
import org.codehaus.plexus.components.secdispatcher.internal.sources.SystemPropertyMasterSource;
@@ -83,14 +85,14 @@ void masterWithSystemPropertyRoundTrip() throws Exception {
8385

8486
@Test
8587
void forwardingWithEnvDecrypt() throws Exception {
86-
saveSec("forwarding", Map.of("source", "env"));
87-
decryptForwarding("{[name=forwarding,version=something]env:MASTER_PASSWORD}", "masterPw");
88+
saveSec("masterSourceLookup", Collections.emptyMap());
89+
decryptForwarding("{[name=masterSourceLookup,version=something]env:MASTER_PASSWORD}", "masterPw");
8890
}
8991

9092
@Test
9193
void forwardingWithSystemPropertyDecrypt() throws Exception {
92-
saveSec("forwarding", Map.of("source", "system-property"));
93-
decryptForwarding("{[name=forwarding,version=something]system-property:masterPassword}", "masterPw");
94+
saveSec("masterSourceLookup", Collections.emptyMap());
95+
decryptForwarding("{[name=masterSourceLookup,version=something]system-property:masterPassword}", "masterPw");
9496
}
9597

9698
@Test
@@ -206,14 +208,9 @@ protected DefaultSecDispatcher construct() {
206208
new GpgAgentMasterSource())),
207209
"legacy",
208210
new LegacyDispatcher(),
209-
"forwarding",
210-
new ForwardingDispatcher(Map.of(
211-
EnvMasterSource.NAME,
212-
new EnvMasterSource(),
213-
SystemPropertyMasterSource.NAME,
214-
new SystemPropertyMasterSource(),
215-
GpgAgentMasterSource.NAME,
216-
new GpgAgentMasterSource()))),
211+
"masterSourceLookup",
212+
new MasterSourceLookupDispatcher(List.of(
213+
new EnvMasterSource(), new SystemPropertyMasterSource(), new GpgAgentMasterSource()))),
217214
CONFIG_PATH);
218215
}
219216

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* This program is licensed to you under the Apache License Version 2.0,
3+
* and you may not use this file except in compliance with the Apache License Version 2.0.
4+
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
5+
*
6+
* Unless required by applicable law or agreed to in writing,
7+
* software distributed under the Apache License Version 2.0 is distributed on an
8+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
10+
*/
11+
12+
package org.codehaus.plexus.components.secdispatcher.internal.dispatchers;
13+
14+
import java.util.Collections;
15+
import java.util.Map;
16+
17+
import org.codehaus.plexus.components.secdispatcher.Dispatcher.EncryptPayload;
18+
import org.codehaus.plexus.components.secdispatcher.SecDispatcher.ValidationResponse;
19+
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
20+
import org.codehaus.plexus.components.secdispatcher.internal.sources.EnvMasterSource;
21+
import org.codehaus.plexus.components.secdispatcher.internal.sources.SystemPropertyMasterSource;
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.junit.jupiter.api.Assertions.assertEquals;
25+
import static org.junit.jupiter.api.Assertions.assertThrows;
26+
import static org.junit.jupiter.api.Assertions.assertTrue;
27+
28+
public class MasterSourceLookupDispatcherTest {
29+
30+
@Test
31+
void testUnknownPrefix() {
32+
MasterSourceLookupDispatcher masterSourceLookupDispatcher =
33+
new MasterSourceLookupDispatcher(Collections.singleton(new EnvMasterSource()));
34+
assertThrows(
35+
SecDispatcherException.class,
36+
() -> masterSourceLookupDispatcher.decrypt("unknown-prefix:test", Map.of(), Map.of()));
37+
assertThrows(
38+
SecDispatcherException.class,
39+
() -> masterSourceLookupDispatcher.encrypt("unknown-prefix:test", Map.of(), Map.of()));
40+
}
41+
42+
@Test
43+
void testSystemPropertyMasterSourceDecrypt() {
44+
System.setProperty("myprop", "plaintext");
45+
MasterSourceLookupDispatcher masterSourceLookupDispatcher =
46+
new MasterSourceLookupDispatcher(Collections.singleton(new SystemPropertyMasterSource()));
47+
// SecDispatcher "un decorates" the PW
48+
String cleartext = masterSourceLookupDispatcher.decrypt("system-property:myprop", Map.of(), Map.of());
49+
assertEquals("plaintext", cleartext);
50+
}
51+
52+
@Test
53+
void testEncrypt() {
54+
System.setProperty("myprop", "plaintext");
55+
MasterSourceLookupDispatcher masterSourceLookupDispatcher =
56+
new MasterSourceLookupDispatcher(Collections.singleton(new SystemPropertyMasterSource()));
57+
// SecDispatcher "un decorates" the PW
58+
EncryptPayload payload = masterSourceLookupDispatcher.encrypt("system-property:myprop", Map.of(), Map.of());
59+
assertEquals("system-property:myprop", payload.getEncrypted());
60+
}
61+
62+
@Test
63+
void testValidateConfiguration() {
64+
MasterSourceLookupDispatcher masterSourceLookupDispatcher =
65+
new MasterSourceLookupDispatcher(Collections.singleton(new SystemPropertyMasterSource()));
66+
ValidationResponse response = masterSourceLookupDispatcher.validateConfiguration(Collections.emptyMap());
67+
assertTrue(response.isValid());
68+
}
69+
}

0 commit comments

Comments
 (0)