Skip to content

Improvement to client function certimportdir(v9) #775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Stueypoo
Copy link
Contributor

Describe your changes

Two main changes:

  • Added an option to use an alternate CA certificate.

When importing certificates into a newly migrated CA, the code performs a certificate verification based upon the CA's certificate that is stored in the DB. A problem with this occurs when the certificates being imported had been issued from the CA's previous certificate (ie., the CA has been renewed).

To remedy this, I added a "--cacert" option that allows the Operator to provide the CA's previous certificate that will then be used to verify the certificate being imported.

  • Added an option to get the revocation details from the filename.

When importing revoked certificates, the Operator should supply the revocation REASON and INVALIDITY_TIME to ensure the CA can generate the CRL with the same contents. However, this means the Operator will have to perform each certificate import manually.

To import revoked certificates in bulk, then an idea is to have the REASON and TIME value encoded within the filename of each certificate. The code would then extract these revocation details and apply them as each certificate is imported.

The filename convention is: CertName!REASON!TIME, where:

  1. REASON is the reason code value or the name. eg., For suspended certs, use either "6" or "CERTIFICATEHOLD" or "CERTIFICATE_HOLD"
  2. TIME format is YYYY.MM.DD-hh.mm

How has this been tested?

A systemtest has been ammended to test these changes:
ant test:runone -Dtest.runone=CaImportCertDirCommandSystemTest

Checklist before requesting a review

  • [X ] I have performed a self-review of my code
  • [X ] I have kept the patch limited to only change the parts related to the patch
  • This change requires a documentation update

NOTE: This pull request is to replace #711

Added ability to provide an alternate CA certificate (for renewed CAs) and allow revocation details to be derived from the filename.
Added additional tests for changes to the associated client function.
@primetomas
Copy link
Collaborator

I'm sorry, but this fell between the chairs due to travels. If you rebase this one I promise to get it fixed for the next release.

@Stueypoo
Copy link
Contributor Author

Synced to latest keyfactor:main.

@primetomas
Copy link
Collaborator

Internal ticket tracker: ECA-13369

if ( sRevCode.equals("CESSATIONOFOPERATION")) sRevCode = "CESSATION_OF_OPERATION";
if ( sRevCode.equals("CERTIFICATEHOLD")) sRevCode = "CERTIFICATE_HOLD";
if ( sRevCode.equals("PRIVILEGESWITHDRAWN")) sRevCode = "PRIVILEGES_WITHDRAWN";
if ( sRevCode.equals("CERTIFICATEHOLD")) sRevCode = "AA_COMPROMISE";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug here in string names

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. Will fix that.

"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."));
registerParameter(new Parameter(REVOKEDETAILS, "Revocation Details", MandatoryMode.OPTIONAL, StandaloneMode.FORBID, ParameterMode.FLAG,
"Revocation details are to be derived from the filename of the certificate. The filename must end with '!<REASON>!<INVALIDITY_TIME>'. The REASON can be the value or label as described in RFC5280 section 5.3.1. "
+ "INVALIDITY_TIME is formatted as '"+DATE_FORMAT_WINSAFE+"' and assumed to be the local timezone. Note: Filename extensions (ie., '.crt. or '.pem') are not supported. Please also note that any file without "
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would feel more consistent if revocation reason was an integer, the same as used when revoking certificates with ejbca.sh ra revokecert. Unessecary to have different parameters values in different places.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it can be...I think the ability to use label complicates things and I would rather do without it. See RevokeCertificateCommand

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps. The CaImportCertCommand takes a text entry for revocation reason and not an integer code. The revocation reason text was confusing to me as the EJBCA's RevocationReason takes a different form than that in the RFC. I thought I'd allow an integer code, the RFC text label, as well as the EJBCA's text label.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}

} catch (NumberFormatException e) {
// Not an integer, must be the full text
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do without the full text imho. Keeping parameters simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See earlier comment.

// Find the revocation details from the filename. The details are separated with an exclamation (!) character.
final String[] sa = file.getName().split("!");
if (sa.length <3) {
log.error("ERROR: The revocation details are not found in filename '"+file.getName()+"'. Ignoring this file.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply ignoring a file makes the import process fragile. The import job reports error about succesful or non-succesful imports. Simply ignoring it here makes this reporting not reporting correctly. Either the report job should instead report that details was missing for this file and thus import failed, or we should allow missing revocation reason and then allowing "standard" import for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the operation is for a bulk set of files, the thinking here is to report an error, but allow the other files in the batch to be tried. Of course, if the whole batch is incorrectly labelled, then all files will show an error.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the skipping of import and error reporting should be part of the CertificateImporter then. If so it will be part of the import summary printed in the end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really follow this comment. If the option to use '--revoke-details-in-filename' is enabled, then the code should report any issues with each filename in the directory being imported, especially if the Revocation Reason or Invalidity Time is not provided in the filename. The Operator should not use the option '--revoke-details-in-filename' if the certificate filenames do not include the extra revocation syntax in the filename.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But there is still some files will be imported that have the correct filename while other will be skipped with just a warning in the log that can easily disappear since it's only logged to the console. And in the end the command will state an "Import summary" which does not report anything on these skipped records. That is a bad "Import summary" imho. '--revoke-details-in-filename' should be robust against filenaming errors similar to it handling issuer errors, or errors with the file content being wrong. Wrong filename is a similar error to wrong file content and should be dealt with similarly.

This wh9le parsing for the reason code can be done in CertificateImporter instead, why not do it there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added any errors to the Results, so as to fix the Import Summary. Example below of 3 incorrect filenames:

ERROR: The revocation details are not found in filename 'A_15710.cer'. Ignoring this file.
ERROR: '2023.OCT.09-12.01' was not a valid revocation time. Use this time format 'yyyy.MM.dd-HH.mm'. Ignoring this file '2024_11.!6!2023.OCT.09-12.01'.
ERROR: 'KEYSCOMPROMISE' is not a valid revocation reason. Ignoring this file '2024_12!KEYSCOMPROMISE!2022.05.04-20.59'.

Import summary:
0 certificates were imported successfully.
Time: 0.0 seconds (Infinity tps)
3 certificates were not imported due to other errors.

The Revocation "Reason Code" is not checked by CertificateImporter, so checking it is legal needs to be done in this code..

Copy link
Contributor Author

@Stueypoo Stueypoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added replies and one code fix.

@primetomas
Copy link
Collaborator

I just though of a question on the revocation options. After importing certificates the CRL should also be imported which would also set the options of they are on the CRL. You anyhow must import the latest CRL for the CRL number to become correct.

Can you describe the benefits of this in addition to importing the CRL?
(I can think of some)

@Stueypoo
Copy link
Contributor Author

Stueypoo commented Jun 3, 2025 via email

@primetomas
Copy link
Collaborator

There is this command today: bin/ejbca.sh ca importcrl --help

@Stueypoo
Copy link
Contributor Author

Oh, I had not noticed the 'importcrl' command. I did some testing and this command works perfectly to revoke certs after importing them into the DB. I guess there isn't any real need for this pull request now. Feel free to cancel it.

@primetomas
Copy link
Collaborator

Great to hear it worked well. Perhaps we can point to the importcrl command in the help text for importcert?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants