diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-11-01 16:22:21 +0100 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-11-01 16:25:31 +0100 |
commit | 32c0d9eb1cce9fdf97137617f32c011fa7851363 (patch) | |
tree | 949e69a85da5645dc3761e239fff4a55b7e82724 /vespaclient-java/src | |
parent | 2e0be2e608099793b98bb008ca14c3d60595b64f (diff) |
Add simple token info dumping tool
Dumps key version, ID and HPKE components
Diffstat (limited to 'vespaclient-java/src')
7 files changed, 103 insertions, 4 deletions
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/Main.java b/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/Main.java index 7ca98e4b9ba..11bd8815d77 100644 --- a/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/Main.java +++ b/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/Main.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.security.tool; import com.yahoo.vespa.security.tool.crypto.DecryptTool; import com.yahoo.vespa.security.tool.crypto.EncryptTool; import com.yahoo.vespa.security.tool.crypto.KeygenTool; +import com.yahoo.vespa.security.tool.crypto.TokenInfoTool; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; @@ -44,7 +45,7 @@ public class Main { } private static final List<Tool> TOOLS = List.of( - new KeygenTool(), new EncryptTool(), new DecryptTool()); + new KeygenTool(), new EncryptTool(), new DecryptTool(), new TokenInfoTool()); private static Optional<Tool> toolFromCliArgs(String[] args) { if (args.length == 0) { diff --git a/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/KeygenTool.java b/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/KeygenTool.java index a0b9cce710b..d7885dc6455 100644 --- a/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/KeygenTool.java +++ b/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/KeygenTool.java @@ -64,8 +64,14 @@ public class KeygenTool implements Tool { OPTIONS); } - private void handleExistingFileIfAny(Path filePath, boolean allowOverwrite) throws IOException { - if (filePath.toFile().exists()) { + private static void verifyNotSameKeyPaths(Path privPath, Path pubPath) { + if (privPath.equals(pubPath)) { + throw new IllegalArgumentException("Private and public key output files must be different"); + } + } + + private static void handleExistingFileIfAny(Path filePath, boolean allowOverwrite) throws IOException { + if (Files.exists(filePath)) { if (!allowOverwrite) { throw new IllegalArgumentException(("Output file '%s' already exists. No keys written. " + "If you want to overwrite existing files, specify --%s.") @@ -83,6 +89,7 @@ public class KeygenTool implements Tool { var arguments = invocation.arguments(); var privOutPath = Paths.get(CliUtils.optionOrThrow(arguments, PRIVATE_OUT_FILE_OPTION)); var pubOutPath = Paths.get(CliUtils.optionOrThrow(arguments, PUBLIC_OUT_FILE_OPTION)); + verifyNotSameKeyPaths(privOutPath, pubOutPath); boolean allowOverwrite = arguments.hasOption(OVERWRITE_EXISTING_OPTION); handleExistingFileIfAny(privOutPath, allowOverwrite); diff --git a/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/TokenInfoTool.java b/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/TokenInfoTool.java new file mode 100644 index 00000000000..dc597e9301f --- /dev/null +++ b/vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/TokenInfoTool.java @@ -0,0 +1,56 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.security.tool.crypto; + +import com.yahoo.security.SealedSharedKey; +import com.yahoo.text.StringUtilities; +import com.yahoo.vespa.security.tool.Tool; +import com.yahoo.vespa.security.tool.ToolDescription; +import com.yahoo.vespa.security.tool.ToolInvocation; +import org.apache.commons.cli.Option; + +import java.util.List; + +import static com.yahoo.security.ArrayUtils.fromUtf8Bytes; +import static com.yahoo.security.ArrayUtils.hex; + +/** + * Tooling to dump the various components of a decryption token + * + * @author vekterli + */ +public class TokenInfoTool implements Tool { + + private static final List<Option> OPTIONS = List.of(); + + @Override + public String name() { + return "token-info"; + } + + @Override + public ToolDescription description() { + return new ToolDescription( + "<token string>", + "Dumps information about the various components of a token", + "Note: this is a BETA tool version; its interface may be changed at any time", + OPTIONS); + } + + @Override + public int invoke(ToolInvocation invocation) { + var arguments = invocation.arguments(); + var leftoverArgs = arguments.getArgs(); + if (leftoverArgs.length != 1) { + throw new IllegalArgumentException("Expected exactly 1 token string argument"); + } + var token = SealedSharedKey.fromTokenString(leftoverArgs[0]); + var stdOut = invocation.stdOut(); + + stdOut.format("Version: %d\n", token.tokenVersion()); + stdOut.format("Key ID: %s (%s)\n", StringUtilities.escape(fromUtf8Bytes(token.keyId())), hex(token.keyId())); + stdOut.format("HPKE enc: %s\n", hex(token.enc())); + stdOut.format("HPKE ciphertext: %s\n", hex(token.ciphertext())); + + return 0; + } +} diff --git a/vespaclient-java/src/test/java/com/yahoo/vespa/security/tool/CryptoToolsTest.java b/vespaclient-java/src/test/java/com/yahoo/vespa/security/tool/CryptoToolsTest.java index a3651888441..8ba24d2cccc 100644 --- a/vespaclient-java/src/test/java/com/yahoo/vespa/security/tool/CryptoToolsTest.java +++ b/vespaclient-java/src/test/java/com/yahoo/vespa/security/tool/CryptoToolsTest.java @@ -72,6 +72,11 @@ public class CryptoToolsTest { } @Test + void token_info_help_printed_if_help_option_given_to_subtool() throws IOException { + verifyStdoutMatchesFile(List.of("token-info", "--help"), "expected-token-info-help-output.txt"); + } + + @Test void missing_required_parameter_prints_error_message() throws IOException { // We don't test all possible input arguments to all tools, since it'd be too closely // bound to the order in which the implementation checks for argument presence. @@ -108,6 +113,16 @@ public class CryptoToolsTest { .formatted(absPathOf(pubKeyFile))); } + @Test + void keygen_fails_if_priv_and_pub_paths_equal() throws IOException { + Path keyFile = pathInTemp("foo.txt"); + + verifyStderrEquals(List.of("keygen", + "--private-out-file", absPathOf(keyFile), + "--public-out-file", absPathOf(keyFile)), + "Invalid command line arguments: Private and public key output files must be different\n"); + } + // ... but we'll allow it if someone enables the foot-gun option. @Test void keygen_allowed_if_output_file_exists_and_explicit_overwrite_option_specified() throws IOException { @@ -214,6 +229,17 @@ public class CryptoToolsTest { } @Test + void token_info_fails_with_error_message_if_no_token_string_given() throws IOException { + verifyStderrEquals(List.of("token-info"), + "Invalid command line arguments: Expected exactly 1 token string argument\n"); + } + + @Test + void token_info_is_printed_to_stdout() throws IOException { + verifyStdoutMatchesFile(List.of("token-info", TEST_TOKEN), "expected-token-info-output.txt"); + } + + @Test void can_end_to_end_keygen_encrypt_and_decrypt_via_files() throws IOException { String greatSecret = "Dogs can't look up"; diff --git a/vespaclient-java/src/test/resources/expected-help-output.txt b/vespaclient-java/src/test/resources/expected-help-output.txt index 45cf829c981..c973735ad46 100644 --- a/vespaclient-java/src/test/resources/expected-help-output.txt +++ b/vespaclient-java/src/test/resources/expected-help-output.txt @@ -1,4 +1,4 @@ usage: vespa-security <tool> [TOOL OPTIONS] -Where <tool> is one of: keygen, encrypt, decrypt +Where <tool> is one of: keygen, encrypt, decrypt, token-info -h,--help Show help Invoke vespa-security <tool> --help for tool-specific help diff --git a/vespaclient-java/src/test/resources/expected-token-info-help-output.txt b/vespaclient-java/src/test/resources/expected-token-info-help-output.txt new file mode 100644 index 00000000000..32b2085d07f --- /dev/null +++ b/vespaclient-java/src/test/resources/expected-token-info-help-output.txt @@ -0,0 +1,5 @@ +usage: vespa-security token-info <token string> +Dumps information about the various components of a token + -h,--help Show help +Note: this is a BETA tool version; its interface may be changed at any +time diff --git a/vespaclient-java/src/test/resources/expected-token-info-output.txt b/vespaclient-java/src/test/resources/expected-token-info-output.txt new file mode 100644 index 00000000000..f0661533765 --- /dev/null +++ b/vespaclient-java/src/test/resources/expected-token-info-output.txt @@ -0,0 +1,4 @@ +Version: 1 +Key ID: my key ID (6d79206b6579204944) +HPKE enc: 02d4f1249766bf7794a16e59dcd252759de9a0a3c4916d1224e1905cfe82682e +HPKE ciphertext: 577f2015a1494afcdc9820cb092b2358294e9699a819a551b6cd0185268aa214 |