Skip to content

Commit 5dd6acb

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 5dd6acb

File tree

4 files changed

+175
-158
lines changed

4 files changed

+175
-158
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,94 @@
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 javax.inject.Inject;
15+
import javax.inject.Named;
16+
import javax.inject.Singleton;
17+
18+
import java.util.Collection;
19+
import java.util.Collections;
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.Objects;
23+
import java.util.Optional;
24+
25+
import org.codehaus.plexus.components.secdispatcher.Dispatcher;
26+
import org.codehaus.plexus.components.secdispatcher.DispatcherMeta;
27+
import org.codehaus.plexus.components.secdispatcher.MasterSource;
28+
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
29+
import org.codehaus.plexus.components.secdispatcher.SecDispatcher.ValidationResponse.Level;
30+
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
31+
32+
/**
33+
* This dispatcher does not actually perform any crypto operations, but just forwards the string to be decrypted
34+
* to a {@link MasterSource}. The given string is supposed to contain a valid source reference which is resolvable
35+
* by one of the bound {@link MasterSource} implementations (and not actually an encrypted value).
36+
* This dispatcher doesn't support encryption, but just validates and returns the given master source reference.
37+
*/
38+
@Singleton
39+
@Named(MasterSourceLookupDispatcher.NAME)
40+
public class MasterSourceLookupDispatcher implements Dispatcher, DispatcherMeta {
41+
public static final String NAME = "masterSourceLookup";
42+
43+
protected final Collection<MasterSource> sources;
44+
45+
@Inject
46+
public MasterSourceLookupDispatcher(Collection<MasterSource> sources) {
47+
this.sources = sources;
48+
}
49+
50+
@Override
51+
public String name() {
52+
return NAME;
53+
}
54+
55+
@Override
56+
public String displayName() {
57+
return "Master Source Lookup Dispatcher";
58+
}
59+
60+
@Override
61+
public Collection<Field> fields() {
62+
return Collections.emptyList();
63+
}
64+
65+
@Override
66+
public EncryptPayload encrypt(String str, Map<String, String> attributes, Map<String, String> config)
67+
throws SecDispatcherException {
68+
// just make sure the given string is a valid reference!
69+
decrypt(str, attributes, config);
70+
return new EncryptPayload(attributes, str);
71+
}
72+
73+
@Override
74+
public String decrypt(String str, Map<String, String> attributes, Map<String, String> config)
75+
throws SecDispatcherException {
76+
Optional<String> plain = sources.stream()
77+
.map(source -> source.handle(str))
78+
.filter(Objects::nonNull)
79+
.findFirst();
80+
if (plain.isPresent()) {
81+
return plain.get();
82+
} else {
83+
throw new SecDispatcherException("No master source found for : " + str);
84+
}
85+
}
86+
87+
@Override
88+
public SecDispatcher.ValidationResponse validateConfiguration(Map<String, String> config) {
89+
// there is nothing really to validate without having a master reference at hand (which is outside the config)
90+
Map<Level, List<String>> report = Collections.singletonMap(
91+
SecDispatcher.ValidationResponse.Level.INFO, List.of("Configured Source configuration valid"));
92+
return new SecDispatcher.ValidationResponse(getClass().getSimpleName(), true, report, Collections.emptyList());
93+
}
94+
}

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

Lines changed: 12 additions & 15 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;
@@ -82,15 +84,15 @@ void masterWithSystemPropertyRoundTrip() throws Exception {
8284
}
8385

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

9092
@Test
91-
void forwardingWithSystemPropertyDecrypt() throws Exception {
92-
saveSec("forwarding", Map.of("source", "system-property"));
93-
decryptForwarding("{[name=forwarding,version=something]system-property:masterPassword}", "masterPw");
93+
void masterSourceLookupWithSystemPropertyDecrypt() throws Exception {
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)