Skip to content

Commit 666766a

Browse files
authored
Enhancements: Example Config File, Default Path, and Error Handling Improvements (#199)
Add default helper config Improving java-spiffe-helper Runner and Config logic Improve error handling in java-spiffe-helper Update README Signed-off-by: Max Lambrecht <[email protected]>
1 parent 56bb734 commit 666766a

File tree

8 files changed

+131
-99
lines changed

8 files changed

+131
-99
lines changed

conf/java-spiffe-helper.properties

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Example java-spiffe-helper configuration
2+
3+
# KeyStore Path
4+
keyStorePath = keystore.p12
5+
6+
# Password for the KeyStore
7+
keyStorePass = REPLACE_WITH_YOUR_KEYSTORE_PASSWORD
8+
9+
# Password for the private key within the KeyStore
10+
keyPass = REPLACE_WITH_YOUR_PRIVATE_KEY_PASSWORD
11+
12+
# Path to the TrustStore file
13+
trustStorePath = truststore.p12
14+
15+
# TrustStore Password: Password for the TrustStore
16+
trustStorePass = REPLACE_WITH_YOUR_TRUSTSTORE_PASSWORD
17+
18+
# KeyStore Type: 'pkcs12' (default) or 'jks'
19+
keyStoreType = pkcs12
20+
21+
# Key Alias: Alias of the key within the KeyStore (Default: `spiffe`)
22+
keyAlias = spiffe
23+
24+
# SPIFFE Socket Path: Path to the SPIRE Agent's public API socket
25+
spiffeSocketPath = unix:/tmp/spire-agent/public/api.sock

java-spiffe-helper/README.md

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ The Helper automatically gets the SVID updates and stores them in the KeyStore a
1010

1111
On Linux:
1212

13-
`java -jar java-spiffe-helper-0.7.0-linux-x86_64.jar -c helper.conf`
13+
`java -jar java-spiffe-helper-0.8.4-linux-x86_64.jar`
1414

1515
On Mac OS:
1616

17-
`java -jar java-spiffe-helper-0.7.0-osx-x86_64.jar -c helper.conf`
17+
`java -jar java-spiffe-helper-0.8.4-osx-x86_64.jar`
1818

19-
Either `-c` or `--config` should be used to pass the path to the config file.
20-
21-
(The jar can be downloaded from [Github releases](https://github.com/spiffe/java-spiffe/releases/tag/v0.7.0))
19+
You can run the utility with the `-c` or `--config` option to specify the path to the configuration file. By default, it
20+
will look for a configuration file named `conf/java-spiffe-helper.properties` in the current working directory.
2221

2322
## Config file
2423

@@ -39,20 +38,19 @@ spiffeSocketPath = unix:/tmp/agent.sock
3938

4039
### Configuration Properties
4140

42-
|Configuration | Description | Default value |
43-
|------------------|--------------------------------------------------------------------------------| ------------- |
44-
|`keyStorePath` | Path to the Java KeyStore File for storing the Private Key and chain of certs | none |
45-
|`keyStorePass` | Password to protect the Java KeyStore File | none |
46-
|`keyPass` | Password to protect the Private Key entry in the KeyStore | none |
47-
|`trustStorePath` | Path to the Java TrustStore File for storing the trusted bundles | none |
48-
|`trustStorePass` | Password to protect the Java TrustStore File | none |
49-
|`keyStoreType` | Java KeyStore Type. (`pkcs12` and `jks` are supported). Case insensitive. | pkcs12 |
50-
|`keyAlias` | Alias for the Private Key entry | spiffe |
51-
|`spiffeSocketPath`| Path the Workload API | Read from the system variable: SPIFFE_ENDPOINT_SOCKET |
52-
53-
KeyStore and TrustStore **must** be in separate files. If `keyStorePath` and `trustStorePath` points to the same file, an error
54-
is shown
55-
.
41+
| Configuration | Description | Default value |
42+
|--------------------|-------------------------------------------------------------------------------|-------------------------------------------------------|
43+
| `keyStorePath` | Path to the Java KeyStore File for storing the Private Key and chain of certs | none |
44+
| `keyStorePass` | Password to protect the Java KeyStore File | none |
45+
| `keyPass` | Password to protect the Private Key entry in the KeyStore | none |
46+
| `trustStorePath` | Path to the Java TrustStore File for storing the trusted bundles | none |
47+
| `trustStorePass` | Password to protect the Java TrustStore File | none |
48+
| `keyStoreType` | Java KeyStore Type. (`pkcs12` and `jks` are supported). Case insensitive. | pkcs12 |
49+
| `keyAlias` | Alias for the Private Key entry | spiffe |
50+
| `spiffeSocketPath` | Path the Workload API | Read from the system variable: SPIFFE_ENDPOINT_SOCKET |
51+
52+
KeyStore and TrustStore **must** be in separate files. If `keyStorePath` and `trustStorePath` points to the same file,
53+
an error is shown.
5654
If the store files do not exist, they are created.
5755

5856
The default and **recommended KeyStore Type** is `PKCS12`. The same type is used for both KeyStore and TrustStore.

java-spiffe-helper/src/main/java/io/spiffe/helper/cli/Config.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,26 @@
44
import io.spiffe.helper.keystore.KeyStoreHelper.KeyStoreOptions;
55
import io.spiffe.helper.keystore.KeyStoreType;
66
import lombok.val;
7-
import org.apache.commons.cli.CommandLineParser;
8-
import org.apache.commons.cli.DefaultParser;
9-
import org.apache.commons.cli.Option;
10-
import org.apache.commons.cli.Options;
11-
import org.apache.commons.cli.ParseException;
7+
import org.apache.commons.cli.*;
128
import org.apache.commons.lang3.StringUtils;
139

1410
import java.io.IOException;
1511
import java.io.InputStream;
1612
import java.nio.file.Files;
1713
import java.nio.file.Path;
1814
import java.nio.file.Paths;
19-
import java.security.InvalidParameterException;
2015
import java.util.Properties;
2116

2217
class Config {
2318

19+
private static final String DEFAULT_CONFIG_FILENAME = "conf/java-spiffe-helper.properties";
20+
2421
static final Option CONFIG_FILE_OPTION =
2522
Option.builder("c")
26-
.longOpt("config")
27-
.hasArg(true)
28-
.required(true)
29-
.build();
23+
.longOpt("config")
24+
.hasArg(true)
25+
.required(false)
26+
.build();
3027

3128
private Config() {
3229
}
@@ -42,17 +39,17 @@ static Properties parseConfigFileProperties(final Path configFilePath) throws Ru
4239
return properties;
4340
}
4441

45-
static String getCliConfigOption(final String... args) throws RunnerException {
42+
static String getCliConfigOption(final String... args) throws ParseException {
4643
final Options cliOptions = new Options();
4744
cliOptions.addOption(CONFIG_FILE_OPTION);
4845
CommandLineParser parser = new DefaultParser();
49-
try {
50-
val cmd = parser.parse(cliOptions, args);
51-
return cmd.getOptionValue("config");
52-
} catch (ParseException e) {
53-
val error = String.format("%s. Use -c, --config <arg>", e.getMessage());
54-
throw new RunnerException(error);
55-
}
46+
47+
CommandLine cmd = parser.parse(cliOptions, args);
48+
return cmd.getOptionValue("config", getDefaultConfigPath());
49+
}
50+
51+
private static String getDefaultConfigPath() {
52+
return Paths.get(System.getProperty("user.dir"), DEFAULT_CONFIG_FILENAME).toString();
5653
}
5754

5855
static KeyStoreOptions createKeyStoreOptions(final Properties properties) {
@@ -89,7 +86,7 @@ static KeyStoreOptions createKeyStoreOptions(final Properties properties) {
8986
static String getProperty(final Properties properties, final String key) {
9087
final String value = properties.getProperty(key);
9188
if (StringUtils.isBlank(value)) {
92-
throw new InvalidParameterException(String.format("Missing value for config property: %s", key));
89+
throw new IllegalArgumentException(String.format("Missing value for config property: %s", key));
9390
}
9491
return value;
9592
}

java-spiffe-helper/src/main/java/io/spiffe/helper/cli/Runner.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,42 @@
66
import io.spiffe.helper.keystore.KeyStoreHelper;
77
import lombok.extern.java.Log;
88
import lombok.val;
9+
import org.apache.commons.cli.ParseException;
10+
import org.apache.commons.lang3.exception.ExceptionUtils;
911

1012
import java.nio.file.Paths;
11-
import java.security.InvalidParameterException;
1213
import java.security.KeyStoreException;
1314

1415
/**
15-
* Entry point of the CLI to run the KeyStoreHelper.
16+
* Entry point of the java-spiffe-helper CLI application.
1617
*/
1718
@Log
1819
public class Runner {
1920

2021
private Runner() {
2122
}
2223

23-
/**
24-
* Entry method of the CLI to run the {@link KeyStoreHelper}.
25-
* <p>
26-
* In the args needs to be passed the config file option as: "-c" and "path_to_config_file"
27-
*
28-
* @param args contains the option with the config file path
29-
* @throws RunnerException is there is an error configuring or creating the KeyStoreHelper.
30-
*/
31-
public static void main(final String ...args) throws RunnerException {
24+
public static void main(final String... args) {
25+
try {
26+
runApplication(args);
27+
} catch (RunnerException e) {
28+
log.severe(ExceptionUtils.getStackTrace(e));
29+
System.exit(1);
30+
} catch (ParseException | IllegalArgumentException e) {
31+
log.severe(e.getMessage());
32+
System.exit(1);
33+
}
34+
}
35+
36+
static void runApplication(final String... args) throws RunnerException, ParseException {
3237
try {
3338
val configFilePath = Config.getCliConfigOption(args);
3439
val properties = Config.parseConfigFileProperties(Paths.get(configFilePath));
3540
val options = Config.createKeyStoreOptions(properties);
3641
try (val keyStoreHelper = KeyStoreHelper.create(options)) {
3742
keyStoreHelper.run(true);
3843
}
39-
} catch (SocketEndpointAddressException | KeyStoreHelperException | RunnerException | InvalidParameterException | KeyStoreException e) {
40-
log.severe(e.getMessage());
44+
} catch (SocketEndpointAddressException | KeyStoreHelperException | KeyStoreException e) {
4145
throw new RunnerException(e);
4246
}
4347
}

java-spiffe-helper/src/main/java/io/spiffe/helper/keystore/KeyStore.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,29 @@ class KeyStore {
4444

4545
private java.security.KeyStore loadKeyStore() throws KeyStoreException {
4646
try {
47-
val keyStore = java.security.KeyStore.getInstance(keyStoreType.value());
48-
49-
// Initialize KeyStore
50-
if (Files.exists(keyStoreFilePath)) {
51-
try (final InputStream inputStream = Files.newInputStream(keyStoreFilePath)) {
52-
keyStore.load(inputStream, keyStorePassword.toCharArray());
53-
}
54-
} else {
55-
//create new keyStore
56-
keyStore.load(null, keyStorePassword.toCharArray());
57-
}
58-
return keyStore;
47+
return loadKeyStoreFromFile();
5948
} catch (IOException | NoSuchAlgorithmException | CertificateException e) {
6049
throw new KeyStoreException("KeyStore cannot be created", e);
6150
}
6251
}
6352

53+
private java.security.KeyStore loadKeyStoreFromFile() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
54+
val keyStore = java.security.KeyStore.getInstance(keyStoreType.value());
55+
56+
// Initialize KeyStore
57+
if (Files.exists(keyStoreFilePath)) {
58+
try (final InputStream inputStream = Files.newInputStream(keyStoreFilePath)) {
59+
keyStore.load(inputStream, keyStorePassword.toCharArray());
60+
} catch (IOException e) {
61+
throw new KeyStoreException("KeyStore cannot be opened", e);
62+
}
63+
} else {
64+
// Create a new KeyStore if it doesn't exist
65+
keyStore.load(null, keyStorePassword.toCharArray());
66+
}
67+
return keyStore;
68+
}
69+
6470

6571
/**
6672
* Store a private key and X.509 certificate chain in a Java KeyStore

java-spiffe-helper/src/test/java/io/spiffe/helper/cli/ConfigTest.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.spiffe.helper.keystore.KeyStoreHelper;
55
import io.spiffe.helper.keystore.KeyStoreType;
66
import lombok.val;
7+
import org.apache.commons.cli.ParseException;
78
import org.apache.commons.lang3.RandomStringUtils;
89
import org.junit.jupiter.api.Test;
910

@@ -12,8 +13,7 @@
1213
import java.util.Properties;
1314

1415
import static io.spiffe.utils.TestUtils.toUri;
15-
import static org.junit.jupiter.api.Assertions.assertEquals;
16-
import static org.junit.jupiter.api.Assertions.fail;
16+
import static org.junit.jupiter.api.Assertions.*;
1717

1818
class ConfigTest {
1919

@@ -56,7 +56,7 @@ void getCliConfigOption_validOption() {
5656
try {
5757
String option = Config.getCliConfigOption("-c", "test");
5858
assertEquals("test", option);
59-
} catch (RunnerException e) {
59+
} catch (ParseException e) {
6060
fail();
6161
}
6262
}
@@ -66,27 +66,28 @@ void getCliConfigOption_validLongOption() {
6666
try {
6767
String option = Config.getCliConfigOption("--config", "example");
6868
assertEquals("example", option);
69-
} catch (RunnerException e) {
69+
} catch (ParseException e) {
7070
fail();
7171
}
7272
}
7373

7474
@Test
75-
void getCliConfigOption_unknownOption() {
75+
void testGetCliConfigOption_unknownLongOption() {
7676
try {
77-
String option = Config.getCliConfigOption("-a", "test");
78-
} catch (RunnerException e) {
79-
assertEquals("Unrecognized option: -a. Use -c, --config <arg>", e.getMessage());
77+
Config.getCliConfigOption("--unknown", "example");
78+
fail("expected parse exception");
79+
} catch (ParseException e) {
80+
assertTrue(e.getMessage().startsWith("Unrecognized option: --unknown"));
8081
}
8182
}
8283

8384
@Test
84-
void testGetCliConfigOption_unknownLongOption() {
85+
void getCliConfigOption_unknownOption() {
8586
try {
86-
Config.getCliConfigOption("--unknown", "example");
87+
String option = Config.getCliConfigOption("-a", "test");
8788
fail("expected parse exception");
88-
} catch (RunnerException e) {
89-
assertEquals("Unrecognized option: --unknown. Use -c, --config <arg>", e.getMessage());
89+
} catch (ParseException e) {
90+
assertTrue(e.getMessage().startsWith("Unrecognized option: -a"));
9091
}
9192
}
9293

0 commit comments

Comments
 (0)