Skip to content

Commit 711d5c4

Browse files
committed
Make Dispatchers and Sources self described
Also introduce two "test" ones, one dispatcher and one source, usable ONLY for testing, as those two have nothing with "encryption".
1 parent 75f4891 commit 711d5c4

File tree

16 files changed

+470
-177
lines changed

16 files changed

+470
-177
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.codehaus.plexus.components.secdispatcher;
2+
3+
import java.util.Map;
4+
5+
/**
6+
* Meta description of master password source.
7+
*/
8+
public interface MasterMeta extends Meta {
9+
/**
10+
* Creates source configuration that can be used as "masterSource".
11+
*/
12+
String createConfig(Map<String, String> data);
13+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package org.codehaus.plexus.components.secdispatcher;
2+
3+
import java.util.Collection;
4+
import java.util.Map;
5+
import java.util.Optional;
6+
7+
import static java.util.Objects.requireNonNull;
8+
9+
/**
10+
* Meta description of dispatcher.
11+
*/
12+
public interface Meta {
13+
class Field {
14+
private final String key;
15+
private final boolean optional;
16+
private final String defaultValue;
17+
private final String description;
18+
19+
private Field(String key, boolean optional, String defaultValue, String description) {
20+
this.key = requireNonNull(key);
21+
this.optional = optional;
22+
this.defaultValue = defaultValue;
23+
this.description = requireNonNull(description);
24+
}
25+
26+
public String getKey() {
27+
return key;
28+
}
29+
30+
public boolean isOptional() {
31+
return optional;
32+
}
33+
34+
public Optional<String> getDefaultValue() {
35+
return Optional.ofNullable(defaultValue);
36+
}
37+
38+
public String getDescription() {
39+
return description;
40+
}
41+
42+
public static Builder builder(String key) {
43+
return new Builder(key);
44+
}
45+
46+
public static class Builder {
47+
private final String key;
48+
private boolean optional;
49+
private String defaultValue;
50+
private String description;
51+
52+
private Builder(String key) {
53+
this.key = requireNonNull(key);
54+
}
55+
56+
public Builder optional(boolean optional) {
57+
this.optional = optional;
58+
return this;
59+
}
60+
61+
public Builder defaultValue(String defaultValue) {
62+
this.defaultValue = defaultValue;
63+
return this;
64+
}
65+
66+
public Builder description(String description) {
67+
this.description = requireNonNull(description);
68+
return this;
69+
}
70+
71+
public Field build() {
72+
return new Field(key, optional, defaultValue, description);
73+
}
74+
}
75+
}
76+
77+
/**
78+
* The key of the item.
79+
*/
80+
String id();
81+
82+
/**
83+
* Returns the display (human) name of the item.
84+
*/
85+
String displayName();
86+
87+
/**
88+
* Returns the configuration fields of the item.
89+
*/
90+
Collection<Field> fields();
91+
}

src/main/java/org/codehaus/plexus/components/secdispatcher/SecDispatcher.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,20 @@ public interface SecDispatcher {
4646
String DISPATCHER_NAME_ATTR = "name";
4747

4848
/**
49-
* Returns the set of available dispatcher names, never {@code null}.
49+
* Returns the set of available dispatcher metadata, never {@code null}.
5050
*/
51-
Set<String> availableDispatchers();
51+
Set<Meta> availableDispatchers();
5252

5353
/**
5454
* Returns the set of available ciphers, never {@code null}.
5555
*/
5656
Set<String> availableCiphers();
5757

58+
/**
59+
* Returns the set of available master password sources metadata, never {@code null}.
60+
*/
61+
Set<MasterMeta> availableMasterSourcesMetadata();
62+
5863
/**
5964
* Encrypt given plaintext string.
6065
*
@@ -87,7 +92,7 @@ public interface SecDispatcher {
8792
* Writes the effective configuration.
8893
*
8994
* @param configuration The configuration to write, may not be {@code null}
90-
* @throws IOException In case of IO problem
95+
* x * @throws IOException In case of IO problem
9196
*/
9297
void writeConfiguration(SettingsSecurity configuration) throws IOException;
9398
}

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/DefaultSecDispatcher.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
import org.codehaus.plexus.components.cipher.PlexusCipher;
3030
import org.codehaus.plexus.components.cipher.PlexusCipherException;
31+
import org.codehaus.plexus.components.secdispatcher.MasterMeta;
32+
import org.codehaus.plexus.components.secdispatcher.Meta;
3133
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
3234
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
3335
import org.codehaus.plexus.components.secdispatcher.model.SettingsSecurity;
@@ -44,32 +46,38 @@ public class DefaultSecDispatcher implements SecDispatcher {
4446
public static final String ATTR_STOP = "]";
4547

4648
protected final PlexusCipher cipher;
47-
protected final Map<String, MasterPasswordSource> masterPasswordSources;
49+
protected final Map<String, MasterSource> masterSources;
4850
protected final Map<String, Dispatcher> dispatchers;
4951
protected final String configurationFile;
5052

5153
@Inject
5254
public DefaultSecDispatcher(
5355
PlexusCipher cipher,
54-
Map<String, MasterPasswordSource> masterPasswordSources,
56+
Map<String, MasterSource> masterSources,
5557
Map<String, Dispatcher> dispatchers,
5658
@Named("${configurationFile:-" + DEFAULT_CONFIGURATION + "}") final String configurationFile) {
5759
this.cipher = requireNonNull(cipher);
58-
this.masterPasswordSources = requireNonNull(masterPasswordSources);
60+
this.masterSources = requireNonNull(masterSources);
5961
this.dispatchers = requireNonNull(dispatchers);
6062
this.configurationFile = requireNonNull(configurationFile);
6163
}
6264

6365
@Override
64-
public Set<String> availableDispatchers() {
65-
return Set.copyOf(dispatchers.keySet());
66+
public Set<Meta> availableDispatchers() {
67+
return Set.copyOf(dispatchers.values().stream().map(Dispatcher::meta).collect(Collectors.toSet()));
6668
}
6769

6870
@Override
6971
public Set<String> availableCiphers() {
7072
return cipher.availableCiphers();
7173
}
7274

75+
@Override
76+
public Set<MasterMeta> availableMasterSourcesMetadata() {
77+
return Set.copyOf(
78+
masterSources.values().stream().map(MasterSource::meta).collect(Collectors.toSet()));
79+
}
80+
7381
@Override
7482
public String encrypt(String str, Map<String, String> attr) throws SecDispatcherException {
7583
if (isEncryptedString(str)) return str;
@@ -204,12 +212,12 @@ private SettingsSecurity getConfiguration(boolean mandatory) throws SecDispatche
204212
}
205213

206214
private String getMasterPassword(SettingsSecurity sec, boolean mandatory) throws SecDispatcherException {
207-
if (sec == null && !mandatory) {
215+
if ((sec == null || sec.getMasterSource() == null) && !mandatory) {
208216
return null;
209217
}
210218
requireNonNull(sec, "configuration is null");
211219
String masterSource = requireNonNull(sec.getMasterSource(), "masterSource is null");
212-
for (MasterPasswordSource masterPasswordSource : masterPasswordSources.values()) {
220+
for (MasterSource masterPasswordSource : masterSources.values()) {
213221
String masterPassword = masterPasswordSource.handle(masterSource);
214222
if (masterPassword != null) return masterPassword;
215223
}

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/Dispatcher.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import java.util.Map;
1717

18+
import org.codehaus.plexus.components.secdispatcher.Meta;
1819
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
1920

2021
/**
@@ -32,6 +33,11 @@ public interface Dispatcher {
3233
*/
3334
String CONF_MASTER_PASSWORD = "masterPassword";
3435

36+
/**
37+
* The metadata of this dispatcher.
38+
*/
39+
Meta meta();
40+
3541
/**
3642
* encrypt given plaintext string
3743
*
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@
1313

1414
package org.codehaus.plexus.components.secdispatcher.internal;
1515

16+
import org.codehaus.plexus.components.secdispatcher.MasterMeta;
1617
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
1718

1819
/**
1920
* Source of master password.
2021
*/
21-
public interface MasterPasswordSource {
22+
public interface MasterSource {
23+
/**
24+
* Returns the "meta" of this master source, never {@code null}.
25+
*/
26+
MasterMeta meta();
27+
2228
/**
2329
* Handles the URI to get master password. Implementation may do one of the following things:
2430
* <ul>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 org.codehaus.plexus.components.secdispatcher.Meta;
17+
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
18+
import org.codehaus.plexus.components.secdispatcher.internal.Dispatcher;
19+
20+
import javax.inject.Named;
21+
import javax.inject.Singleton;
22+
import java.util.Collection;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
/**
27+
* This dispatcher is purely for test purposes, is obviously NOT a true encryption implementation.
28+
*/
29+
@Singleton
30+
@Named(TestDispatcher.NAME)
31+
public class TestDispatcher implements Dispatcher {
32+
public static final String NAME = "test";
33+
34+
@Override
35+
public Meta meta() {
36+
return new Meta() {
37+
@Override
38+
public String id() {
39+
return NAME;
40+
}
41+
42+
@Override
43+
public String displayName() {
44+
return "Test Dispatcher (for testing only)";
45+
}
46+
47+
@Override
48+
public Collection<Field> fields() {
49+
return List.of(Field.builder("salt")
50+
.optional(false)
51+
.description("The salt for testing")
52+
.build());
53+
}
54+
};
55+
}
56+
57+
protected String getSalt(Map<String, String> config) throws SecDispatcherException {
58+
String salt = config.get("salt");
59+
if (salt == null) {
60+
throw new SecDispatcherException("The configuration is incomplete; missing salt");
61+
}
62+
return salt;
63+
}
64+
65+
@Override
66+
public String encrypt(String str, Map<String, String> attributes, Map<String, String> config) throws SecDispatcherException {
67+
return new StringBuilder(str).reverse() + "@" + getSalt(config);
68+
}
69+
70+
@Override
71+
public String decrypt(String str, Map<String, String> attributes, Map<String, String> config) throws SecDispatcherException {
72+
return new StringBuilder(str).reverse().substring(getSalt(config).length() + 1);
73+
}
74+
}
Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,55 @@
2121
import javax.inject.Named;
2222
import javax.inject.Singleton;
2323

24+
import java.util.Collection;
25+
import java.util.List;
26+
import java.util.Map;
27+
28+
import org.codehaus.plexus.components.secdispatcher.MasterMeta;
2429
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
2530

31+
import static java.util.Objects.requireNonNull;
32+
2633
/**
2734
* Password source that uses env.
2835
*/
2936
@Singleton
30-
@Named(EnvMasterPasswordSource.NAME)
31-
public final class EnvMasterPasswordSource extends PrefixMasterPasswordSourceSupport {
37+
@Named(EnvMasterSource.NAME)
38+
public final class EnvMasterSource extends PrefixMasterSourceSupport {
3239
public static final String NAME = "env";
3340

34-
public EnvMasterPasswordSource() {
41+
public EnvMasterSource() {
3542
super(NAME + ":");
3643
}
3744

45+
@Override
46+
public MasterMeta meta() {
47+
return new MasterMeta() {
48+
@Override
49+
public String id() {
50+
return NAME;
51+
}
52+
53+
@Override
54+
public String displayName() {
55+
return "Environment Variable Source";
56+
}
57+
58+
@Override
59+
public Collection<Field> fields() {
60+
return List.of(Field.builder("name")
61+
.optional(false)
62+
.description("Name of the environment variable")
63+
.build());
64+
}
65+
66+
@Override
67+
public String createConfig(Map<String, String> data) {
68+
return NAME + ":" + requireNonNull(data.get("name"), "Config incomplete");
69+
}
70+
};
71+
}
72+
3873
@Override
3974
protected String doHandle(String transformed) throws SecDispatcherException {
4075
String value = System.getenv(transformed);

0 commit comments

Comments
 (0)