Skip to content

Commit 088e194

Browse files
authored
Merge pull request #775 from Stueypoo/Improvement-to-client-function-certimportdir(v9)
Improvement to client function certimportdir(v9)
2 parents f3d2756 + 8cbbd9f commit 088e194

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

modules/ejbca-ejb-cli/src/org/ejbca/ui/cli/ca/CaImportCertDirCommand.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.ejbca.ui.cli.infrastructure.parameter.enums.ParameterMode;
4343
import org.ejbca.ui.cli.infrastructure.parameter.enums.StandaloneMode;
4444

45+
import com.keyfactor.util.CertTools;
4546
import com.keyfactor.util.CryptoProviderTools;
4647
import com.keyfactor.util.certificate.DnComponents;
4748

@@ -55,7 +56,6 @@ public class CaImportCertDirCommand extends BaseCaAdminCommand {
5556
private static final Logger log = Logger.getLogger(CaImportCertDirCommand.class);
5657

5758
public static final String DATE_FORMAT = "yyyy.MM.dd-HH:mm";
58-
5959
private static final String USERNAME_FILTER_KEY = "--filter";
6060
private static final String CA_NAME_KEY = "--caname";
6161
private static final String ACTIVE_KEY = "-a";
@@ -66,6 +66,7 @@ public class CaImportCertDirCommand extends BaseCaAdminCommand {
6666
private static final String REVOCATION_REASON = "--revocation-reason";
6767
private static final String REVOCATION_TIME = "--revocation-time";
6868
private static final String THREAD_COUNT = "--threads";
69+
private static final String CACERT = "--cacert";
6970

7071
private static final String ACTIVE = "ACTIVE";
7172
private static final String REVOKED = "REVOKED";
@@ -92,7 +93,9 @@ public class CaImportCertDirCommand extends BaseCaAdminCommand {
9293
+ DATE_FORMAT + ", i.e. 2015.05.04-10:15"));
9394
registerParameter(new Parameter(THREAD_COUNT, "Thread count", MandatoryMode.OPTIONAL, StandaloneMode.FORBID, ParameterMode.ARGUMENT,
9495
"Number of threads used during the import. Default is 1 thread."));
95-
}
96+
registerParameter(new Parameter(CACERT, "CA Certificate File", MandatoryMode.OPTIONAL, StandaloneMode.FORBID, ParameterMode.ARGUMENT,
97+
"Specify an alternate CA certificate file (in PEM). Use this option when importing certificates that were issued by the previous CA certificate. Please note that the supplied certificate is not verified."));
98+
}
9699

97100
@Override
98101
public String getMainCommand() {
@@ -115,6 +118,7 @@ public CommandResult execute(final ParameterContainer parameters) {
115118
final String revocationReasonString = parameters.get(REVOCATION_REASON);
116119
final String revocationTimeString = parameters.get(REVOCATION_TIME);
117120
final int threadCount = parameters.get(THREAD_COUNT) == null ? 1 : Integer.valueOf(StringUtils.strip(parameters.get(THREAD_COUNT)));
121+
final String caCertFile = parameters.get(CACERT);
118122

119123
if (threadCount > 1 && !usernameFilter.equalsIgnoreCase("FILE")) {
120124
log.error("If more than one thread is being used, filename must be used as filter (use the argument --filter FILE).");
@@ -174,7 +178,29 @@ public CommandResult execute(final ParameterContainer parameters) {
174178

175179
// Fetch CA info
176180
final CAInfo caInfo = getCAInfo(getAuthenticationToken(), caName);
177-
final X509Certificate cacert = (X509Certificate) caInfo.getCertificateChain().iterator().next();
181+
182+
X509Certificate cacert = (X509Certificate) caInfo.getCertificateChain().iterator().next();
183+
// Override the CA certificate if provided in the options
184+
if ( caCertFile != null) {
185+
final File fileCaCertFile = new File(caCertFile);
186+
if (!fileCaCertFile.isFile()) {
187+
log.error("CA Certificate file '" + caCertFile + "' is not found. Please check the supplied parameters.");
188+
return CommandResult.CLI_FAILURE;
189+
} else {
190+
List<X509Certificate> certsInFile = CertTools.getCertsFromPEM( fileCaCertFile.getCanonicalPath(), X509Certificate.class);
191+
if ( (certsInFile == null) || (certsInFile.size()<1)) {
192+
log.error("CA Certificate file '" + caCertFile + "' could not be processed. Please check the file.");
193+
return CommandResult.CLI_FAILURE;
194+
}
195+
if ( certsInFile.size()>1) {
196+
log.warn("CA Certificate file '" + caCertFile + "' contains more than one certificate. Assuming the first certificate.");
197+
}
198+
// Assume the first certificate, in case more than one provided.
199+
cacert = certsInFile.get(0);
200+
log.warn("The certificate for the CA has been overidden. This certificate has not been verified. Use at your own risk. Certificate details: "+cacert.toString());
201+
}
202+
}
203+
178204
final String issuer = DnComponents.stringToBCDNString(cacert.getSubjectDN().toString());
179205
log.info("CA: " + issuer);
180206
// Fetch End Entity Profile info

modules/systemtests/src-test/org/ejbca/ui/cli/ca/CaImportCertDirCommandSystemTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
import static org.junit.Assert.assertEquals;
6161
import static org.junit.Assert.assertNotNull;
62+
import static org.junit.Assert.assertNull;
6263

6364
/**
6465
* @version $Id$
@@ -191,4 +192,41 @@ public void testImportRevokedWithReasonAndTime() throws AuthorizationDeniedExcep
191192
assertEquals("Certificate revocation date was incorrectly imported.", new SimpleDateFormat(CaImportCertDirCommand.DATE_FORMAT).parse("2015.05.04-10:15"),
192193
certificateStatus.revocationDate);
193194
}
195+
196+
@Test
197+
public void testImportFromAnotherCA() throws Exception {
198+
// Import a certificate from another CA. One way to do this is to save the current CA cert, re-create the CA, then import EE cert.
199+
// Get the CA cert and save it to file
200+
Certificate caCert = ca.getCACertificate();
201+
File caCertFile = File.createTempFile("cacert", null, tempDirectory);
202+
FileOutputStream fileOutputStream = new FileOutputStream(caCertFile);
203+
try {
204+
fileOutputStream.write(CertTools.getPemFromCertificateChain(Arrays.asList(caCert)));
205+
} finally {
206+
fileOutputStream.close();
207+
}
208+
// Delete the CA
209+
CaTestUtils.removeCa(authenticationToken, ca.getCAInfo());
210+
211+
// Create a new CA
212+
ca = CaTestUtils.createTestX509CA(CA_DN, null, false);
213+
caSession.addCA(authenticationToken, ca);
214+
215+
// First check that the EE certificate cannot be imported as the current CA's key is different
216+
String[] args = new String[] { "DN", CA_NAME, "ACTIVE", tempDirectory.getAbsolutePath(), "--eeprofile", "EMPTY", "--certprofile", "ENDUSER"};
217+
assertEquals(CommandResult.SUCCESS, command.execute(args));
218+
EndEntityInformation endEntityInformation = endEntityAccessSession.findUser(authenticationToken, CERTIFICATE_DN);
219+
assertNull("Certificate should not have been imported.", endEntityInformation);
220+
221+
// Now check the EE cert can be imported with the --cacert option
222+
args = new String[] { "DN", CA_NAME, "ACTIVE", tempDirectory.getAbsolutePath(), "--eeprofile", "EMPTY", "--certprofile", "ENDUSER",
223+
"--cacert", caCertFile.getCanonicalPath()};
224+
assertEquals(CommandResult.SUCCESS, command.execute(args));
225+
endEntityInformation = endEntityAccessSession.findUser(authenticationToken, CERTIFICATE_DN);
226+
assertNotNull("Certificate was not imported.", endEntityInformation);
227+
228+
assertEquals("Certificate was imported with incorrect status", EndEntityConstants.STATUS_GENERATED, endEntityInformation.getStatus());
229+
CertificateStatus certificateStatus = certificateStoreSession.getStatus(CA_DN, certificateSerialNumber);
230+
assertEquals("Certificate was revoked but should have been Active.", false, certificateStatus.isRevoked());
231+
}
194232
}

0 commit comments

Comments
 (0)