Skip to content

Commit

Permalink
Allow exporting a chain to separate files
Browse files Browse the repository at this point in the history
Updated the manage-certificates tool so that the export-certificate
subcommand now includes a --separate-file-per-certificate argument
that can be used if both the --export-certificate-chain and the
--output-file arguments are also given.  If all of these arguments
are provided, and if there are multiple certificates to be exported,
then the file used to hold the first certificate will be the path
specified using the --output-file argument with ".1" appended to it,
the file for the second certificate will be the specified path with
".2" appended to it, and so on.  If the
--separate-file-per-certificate argument is not given, then all of
the certificates will be concatenated into the same file.
  • Loading branch information
dirmgr committed Dec 4, 2017
1 parent 9e930cb commit 6954c25
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 8 deletions.
7 changes: 6 additions & 1 deletion messages/unboundid-ldapsdk-cert.properties
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,11 @@ INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_FILE_DESC=The path to the output file \
optional when using the PEM format, but required when using the DER \
format. If no output file is provided, then the exported certificate will \
be written to standard output.
INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_SEPARATE_FILE_DESC=Indicates that if \
multiple certificates are to be exported, then each certificate should be \
written to a different file rather than concatenating all of them into the \
same file. This can only be used if both the --export-certificate-chain \
and --output-file arguments are also provided.
INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_DISPLAY_COMMAND_DESC=Display a command \
that can be invoked to achieve a similar result with the Java keytool \
utility. Note that this may just be an approximation, since the \
Expand Down Expand Up @@ -1728,7 +1733,7 @@ WARN_MANAGE_CERTS_EXPORT_CERT_MISSING_CERT_IN_CHAIN=WARNING: Unable to \
''{1}'' or in the JVM's default set of trusted certificates. The \
certificate chain is incomplete.
INFO_MANAGE_CERTS_EXPORT_CERT_EXPORT_SUCCESSFUL=Successfully exported the \
following certificate:
following certificate to ''{0}'':
ERR_MANAGE_CERTS_EXPORT_KEY_NO_FILE_WITH_DER=ERROR: An output file must be \
specified when exporting a private key in the binary DER format.
ERR_MANAGE_CERTS_EXPORT_KEY_NO_KEY_WITH_ALIAS=ERROR: There is no private key \
Expand Down
47 changes: 44 additions & 3 deletions src/com/unboundid/util/ssl/cert/ManageCertificates.java
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,15 @@ public void addToolArguments(final ArgumentParser parser)
exportCertOutputFile.addLongIdentifier("filename", true);
exportCertParser.addArgument(exportCertOutputFile);

final BooleanArgument exportCertSeparateFile = new BooleanArgument(null,
"separate-file-per-certificate", 1,
INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_SEPARATE_FILE_DESC.get());
exportCertSeparateFile.addLongIdentifier("separateFilePerCertificate",
true);
exportCertSeparateFile.addLongIdentifier("separate-files", true);
exportCertSeparateFile.addLongIdentifier("separateFiles", true);
exportCertParser.addArgument(exportCertSeparateFile);

final BooleanArgument exportCertDisplayCommand = new BooleanArgument(null,
"display-keytool-command", 1,
INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_DISPLAY_COMMAND_DESC.get());
Expand All @@ -654,6 +663,10 @@ public void addToolArguments(final ArgumentParser parser)

exportCertParser.addExclusiveArgumentSet(exportCertKeystorePassword,
exportCertKeystorePasswordFile, exportCertPromptForKeystorePassword);
exportCertParser.addDependentArgumentSet(exportCertSeparateFile,
exportCertChain);
exportCertParser.addDependentArgumentSet(exportCertSeparateFile,
exportCertOutputFile);

final LinkedHashMap<String[],String> exportCertExamples =
new LinkedHashMap<>(2);
Expand Down Expand Up @@ -4225,6 +4238,12 @@ private ResultCode doExportCertificate()
final boolean exportChain =
((exportChainArgument != null) && exportChainArgument.isPresent());

final BooleanArgument separateFilePerCertificateArgument =
subCommandParser.getBooleanArgument("separate-file-per-certificate");
final boolean separateFilePerCertificate =
((separateFilePerCertificateArgument != null) &&
separateFilePerCertificateArgument.isPresent());

boolean exportPEM = true;
final StringArgument outputFormatArgument =
subCommandParser.getStringArgument("output-format");
Expand Down Expand Up @@ -4388,7 +4407,9 @@ private ResultCode doExportCertificate()


// Get a PrintStream to use for the output.
final PrintStream printStream;
int fileCounter = 1;
String filename = null;
PrintStream printStream;
if (outputFile == null)
{
printStream = getOut();
Expand All @@ -4397,7 +4418,15 @@ private ResultCode doExportCertificate()
{
try
{
printStream = new PrintStream(outputFile);
if ((certificatesToExport.length > 1) && separateFilePerCertificate)
{
filename = outputFile.getAbsolutePath() + '.' + fileCounter;
}
else
{
filename = outputFile.getAbsolutePath();
}
printStream = new PrintStream(filename);
}
catch (final Exception e)
{
Expand All @@ -4416,6 +4445,18 @@ private ResultCode doExportCertificate()
{
try
{
if (separateFilePerCertificate && (certificatesToExport.length > 1))
{
if (fileCounter > 1)
{
printStream.close();
filename = outputFile.getAbsolutePath() + '.' + fileCounter;
printStream = new PrintStream(filename);
}

fileCounter++;
}

if (exportPEM)
{
writePEMCertificate(printStream,
Expand All @@ -4440,7 +4481,7 @@ private ResultCode doExportCertificate()
{
out();
wrapOut(0, WRAP_COLUMN,
INFO_MANAGE_CERTS_EXPORT_CERT_EXPORT_SUCCESSFUL.get());
INFO_MANAGE_CERTS_EXPORT_CERT_EXPORT_SUCCESSFUL.get(filename));
printCertificate(certificate, "", false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,15 +914,19 @@ public void testExportCertificate()
"--export-certificate-chain",
"--output-format", "PEM",
"--output-file", outputFile.getAbsolutePath(),
"--separate-file-per-certificate",
"--display-keytool-command");
assertTrue(outputFile.exists());
assertEquals(countPEMEntries(outputFile.getAbsolutePath()), 3);
assertFalse(outputFile.exists());
assertTrue(new File(outputFile.getAbsolutePath() + ".1").exists());
assertTrue(new File(outputFile.getAbsolutePath() + ".2").exists());
assertTrue(new File(outputFile.getAbsolutePath() + ".3").exists());


// Test exporting a DER certificate chain for a JKS keystore with a private
// key entry.
assertTrue(outputFile.delete());
assertFalse(outputFile.exists());
assertTrue(new File(outputFile.getAbsolutePath() + ".1").delete());
assertTrue(new File(outputFile.getAbsolutePath() + ".2").delete());
assertTrue(new File(outputFile.getAbsolutePath() + ".3").delete());
manageCertificates(
"export-certificate",
"--keystore", serverKeyStorePath,
Expand Down

0 comments on commit 6954c25

Please sign in to comment.