Skip to content

Conversation

@hrishikesh-nalawade
Copy link
Member

@hrishikesh-nalawade hrishikesh-nalawade commented Dec 10, 2025

Description

API-Layer filters out its own certificates during client authentication but doesn't log which certificates were ignored, making troubleshooting difficult.

  • Created shared CertificateLoggingUtils utility class for certificate logging
  • Added logging to both CategorizeCertsFilter and CategorizeCertsWebFilter

Linked to #4164

Type of change

  • fix: Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code follows the style guidelines of this project
  • PR title conforms to commit message guideline ## Commit Message Structure Guideline
  • I have commented my code, particularly in hard-to-understand areas. In JS I did provide JSDoc
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

certificateForClientAuth
);

// Log ignored certificates
Copy link
Contributor

Choose a reason for hiding this comment

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

Are the comments needed? The method name is self-explanatory

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, will remove most of the comments after after review and before merging.

@pablocarle
Copy link
Contributor

What about microservices' mode CategorizeCertsFilter? Do we want to print it also there? It's still the most used configuration mode and it may be helpful to have more diagnostics there

@pablocarle
Copy link
Contributor

Does the PR fix #4164 fully? The issue also refers to documentation update

@hrishikesh-nalawade
Copy link
Member Author

hrishikesh-nalawade commented Dec 10, 2025

What about microservices' mode CategorizeCertsFilter? Do we want to print it also there? It's still the most used configuration mode and it may be helpful to have more diagnostics there

Thank You for pointing that out, I was not aware of that. I'll implement the changes in CategorizeCertsFilter as well.

…ld be done in CategorizeCertsFilter and CategorizeCertsWebFilter

Signed-off-by: hrishikesh-nalawade <[email protected]>
@hrishikesh-nalawade hrishikesh-nalawade changed the title Fix: Log ignored certificates during client authentication fix: Log ignored certificates during client authentication Dec 10, 2025
@github-actions github-actions bot added the Sensitive Sensitive change that requires peer review label Dec 10, 2025
Signed-off-by: hrishikesh-nalawade <[email protected]>
@pablocarle
Copy link
Contributor

@hrishikesh-nalawade can you take care of the 7 sonarqube issues reported?

filteredCerts,
publicKeyCertificatesBase64,
log,
CategorizeCertsWebFilter::base64EncodePublicKey
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be moved to a utility class, there's no reason to have it as a parameter everywhere

Copy link
Member Author

Choose a reason for hiding this comment

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

yes it is, I have created a separate utility class CertificateLoggingUtils to handle the certificate filtering logic

* @param logger The logger to use for output
* @param base64Encoder Function to encode certificate public key to Base64
*/
public static void logIgnoredCertificates(
Copy link
Contributor

Choose a reason for hiding this comment

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

Try to refactor a bit this method, it's too long, you can extract smaller blocks into private methods

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, Thank You for pointing that out.

Comment on lines +48 to +59
Set<String> originalKeys = Arrays.stream(originalCerts)
.map(base64Encoder)
.collect(Collectors.toSet());

Set<String> filteredKeys = filteredCerts != null
? Arrays.stream(filteredCerts)
.map(base64Encoder)
.collect(Collectors.toSet())
: new HashSet<>();

Set<String> ignoredKeys = new HashSet<>(originalKeys);
ignoredKeys.removeAll(filteredKeys);
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be one method

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, Thank You for pointing that out.

ignoredKeys.removeAll(filteredKeys);

if (!ignoredKeys.isEmpty()) {
List<X509Certificate> ignoredCerts = Arrays.stream(originalCerts)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since it's java 17+, verbosity can be somewhat reduced using var, like:

var ignoredCerts = Arrays.stream(originalCerts)

Comment on lines 67 to 79
ignoredCerts.stream()
.map(cert -> {
String subjectDN = cert.getSubjectX500Principal() != null
? cert.getSubjectX500Principal().getName()
: "Unknown";
String issuerDN = cert.getIssuerX500Principal() != null
? cert.getIssuerX500Principal().getName()
: "Unknown";
String publicKeyBase64 = base64Encoder.apply(cert);
return String.format("[Subject: %s, Issuer: %s, Public Key (first 20 chars): %s...]",
subjectDN, issuerDN, publicKeyBase64.substring(0, Math.min(20, publicKeyBase64.length())));
})
.collect(Collectors.joining(", ")));
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be extracted to a private method as well

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, Thank You for pointing that out.

}
}

@Test
Copy link
Contributor

Choose a reason for hiding this comment

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

Move these tests into a nested class, if it's only verifying logging.

Have you checked if these same scenarios are already covered in previous tests? (so you can only add the assertion to the existing test about logging)

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank You, Removed most of the tests, added assertions to the existing ones, and kept one test for a scenario that was not covered.

}

@Nested
class LogIgnoredCertificatesTests {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question, have you checked if these test conditions are covered in the existing tests?
Maybe it's easier to add assertions to the existing tests rather than writing all new ones
If the conditions were not covered previously, then let's add new tests, but the focus should be on the main validations rather than whether they are logged or not. Logging should be in addition to.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank You, Removed most of the tests, added assertions to the existing ones, and kept one test for a scenario that was not covered.

…eCertsWebFilterTest and CategorizeCertsFilterTest by adding logging assertions into existing tests

Signed-off-by: hrishikesh-nalawade <[email protected]>
Signed-off-by: hrishikesh-nalawade <[email protected]>
filteredCerts,
publicKeyCertificatesBase64,
log,
CategorizeCertsFilter::base64EncodePublicKey
Copy link
Contributor

Choose a reason for hiding this comment

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

please remove this as an argument, simply call the method or if not visible, move to a utility class that's visible in apiml-common

filteredCerts,
publicKeyCertificatesBase64,
log,
CategorizeCertsFilter::base64EncodePublicKey
Copy link
Contributor

Choose a reason for hiding this comment

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

@hrishikesh-nalawade can you confirm if you see this comment? There's some weird behaviour in the github view

* Utility class for logging certificate-related operations, particularly for logging
* certificates that were ignored/filtered during client authentication.
*/
@UtilityClass
Copy link
Contributor

Choose a reason for hiding this comment

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

This annotation doesn't provide much value here honestly, it's preferable to remove it and add a private constructor

@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Sensitive Sensitive change that requires peer review size/L

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants