Skip to content

Commit

Permalink
append endpoint type to certificateinfo object and access it in Mutua…
Browse files Browse the repository at this point in the history
…lSSLAuthenticator
  • Loading branch information
RusJaI committed May 29, 2024
1 parent e47ccf9 commit 475bf2a
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public class APIAuthenticationHandler extends AbstractHandler implements Managed
private String apiKeyHeader;
private String apiSecurity;
private String apiLevelPolicy;
private String environmentType;
private String certificateInformation;
private String apiUUID;
private String apiType = String.valueOf(APIConstants.ApiTypes.API); // Default API Type
Expand Down Expand Up @@ -151,6 +152,24 @@ public void setAPILevelPolicy(String apiLevelPolicy) {
this.apiLevelPolicy = apiLevelPolicy;
}

/**
* To get the environment type (whether production or sandbox).
*
* @return Relevant environment type related to the endpoint.
*/
public String getEnvironmentType() {
return environmentType;
}

/**
* To set the API level tier policy.
*
* @param environmentType Relevant environment type related to the endpoint.
*/
public void setEnvironmentType(String environmentType) {
this.environmentType = environmentType;
}

/**
* Get type of the API
* @return API Type
Expand Down Expand Up @@ -525,6 +544,7 @@ private void handleNoAuthentication(MessageContext messageContext){
authContext.setStopOnQuotaReach(true);
//Requests are throttled by the ApiKey that is set here. In an unauthenticated scenario, we will use the client's IP address for throttling.
authContext.setApiKey(clientIP);
//TODO: verify the key type
authContext.setKeyType(APIConstants.API_KEY_TYPE_PRODUCTION);
//This name is hardcoded as anonymous because there is no associated user token
authContext.setUsername(APIConstants.END_USER_ANONYMOUS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class MutualSSLAuthenticator implements Authenticator {
private boolean isMandatory;

// <UniqueIdentifierName,Tier> -Format
private HashMap<String, String> certificates;
private HashMap<String, HashMap<String, String>> certificates;

/**
* Initialized the mutual SSL authenticator.
Expand All @@ -71,14 +71,18 @@ public class MutualSSLAuthenticator implements Authenticator {
public MutualSSLAuthenticator(String apiLevelPolicy, boolean isMandatory, String certificateDetails) {
this.apiLevelPolicy = apiLevelPolicy;
certificates = new HashMap<>();
HashMap<String, String> certificateData = new HashMap<>();
if (StringUtils.isNotEmpty(certificateDetails)) {
String[] certificateParts = certificateDetails.substring(1, certificateDetails.length() - 1).split(",");
for (String certificatePart : certificateParts) {
int tierDivisionIndex = certificatePart.lastIndexOf("=");
if (tierDivisionIndex > 0) {
String uniqueIdentifier = certificatePart.substring(0, tierDivisionIndex).trim();
String tier = certificatePart.substring(tierDivisionIndex + 1);
certificates.put(uniqueIdentifier, tier);
String tierAndKeyTypeString = certificatePart.substring(tierDivisionIndex + 1);
String[] tierAndKeyType = tierAndKeyTypeString.split(APIConstants.DELEM_COLON);
certificateData.put(APIConstants.CLIENT_CERTIFICATE_TIER, tierAndKeyType[0]);
certificateData.put(APIConstants.CLIENT_CERTIFICATE_KEY_TYPE, tierAndKeyType[1]);
certificates.put(uniqueIdentifier, certificateData);
}
}
}
Expand Down Expand Up @@ -177,11 +181,12 @@ private void setAuthContext(MessageContext messageContext, Certificate certifica
String subjectDN = x509Certificate.getSubjectDN().getName();
String uniqueIdentifier = (x509Certificate.getSerialNumber() + "_" + x509Certificate.getSubjectDN()).replaceAll(",",
"#").replaceAll("\"", "'").trim();
String tier = certificates.get(uniqueIdentifier);
String tier = certificates.get(uniqueIdentifier).get(APIConstants.CLIENT_CERTIFICATE_TIER);
String keyType = certificates.get(uniqueIdentifier).get(APIConstants.CLIENT_CERTIFICATE_KEY_TYPE);
if (StringUtils.isEmpty(tier)) {
handleCertificateNotAssociatedToAPIFailure(messageContext);
}
setAuthenticationContext(messageContext, subjectDN, uniqueIdentifier, tier);
setAuthenticationContext(messageContext, subjectDN, uniqueIdentifier, tier, keyType);
}

/**
Expand All @@ -195,6 +200,7 @@ private void setAuthContext(MessageContext messageContext, Certificate[] certifi
throws APISecurityException, APIManagementException {

String tier = null;
String keyType = null;
List<X509Certificate> x509Certificates = Utils.convertCertificatesToX509Certificates(certificatesArray);
String subjectDN = x509Certificates.get(0).getSubjectDN().getName();
String issuerDNIdentifier = x509Certificates.get(x509Certificates.size() - 1).getIssuerDN().getName()
Expand All @@ -205,11 +211,12 @@ private void setAuthContext(MessageContext messageContext, Certificate[] certifi
String subjectDNIdentifier = (x509Certificate.getSerialNumber() + "_"
+ x509Certificate.getSubjectDN()).replaceAll(",", "#").replaceAll("\"", "'").trim();
subjectDNIdentifiers.add(subjectDNIdentifier);
for (Map.Entry<String, String> entry : certificates.entrySet()) {
for (Map.Entry<String, HashMap<String, String>> entry : certificates.entrySet()) {
String key = entry.getKey();
if (StringUtils.equals(subjectDNIdentifier, key)) {
uniqueIdentifier = key;
tier = entry.getValue();
tier = entry.getValue().get(APIConstants.CLIENT_CERTIFICATE_TIER);
keyType = entry.getValue().get(APIConstants.CLIENT_CERTIFICATE_KEY_TYPE);
break;
}
}
Expand All @@ -218,36 +225,41 @@ private void setAuthContext(MessageContext messageContext, Certificate[] certifi
}
}
if (StringUtils.isEmpty(tier)) {
for (Map.Entry<String, String> entry : certificates.entrySet()) {
for (Map.Entry<String, HashMap<String, String>> entry : certificates.entrySet()) {
String key = entry.getKey();
if (key.contains(issuerDNIdentifier)) {
uniqueIdentifier = key;
tier = entry.getValue();
tier = entry.getValue().get(APIConstants.CLIENT_CERTIFICATE_TIER);
keyType = entry.getValue().get(APIConstants.CLIENT_CERTIFICATE_KEY_TYPE);
}
}
}
if (StringUtils.isEmpty(tier)) {
tier = getTierFromCompleteCertificateChain(x509Certificates, subjectDNIdentifiers);
if (StringUtils.isEmpty(tier) || StringUtils.isEmpty(keyType)) {
subjectDNIdentifiers = getUniqueIdentifierFromCompleteCertificateChain(x509Certificates, subjectDNIdentifiers);
}
if (StringUtils.isEmpty(tier)) {
tier = getTierFromCompleteCertificateChain(subjectDNIdentifiers);
}
if (StringUtils.isEmpty(keyType)) {
keyType = getKeyTypeFromCompleteCertificateChain(subjectDNIdentifiers);
}
if (StringUtils.isEmpty(tier) || StringUtils.isEmpty(keyType)) {
handleCertificateNotAssociatedToAPIFailure(messageContext);
}
setAuthenticationContext(messageContext, subjectDN, uniqueIdentifier, tier);
setAuthenticationContext(messageContext, subjectDN, uniqueIdentifier, tier, keyType);
}

/**
* Fetches tier assigned to the client certificate after making the complete certificate chain using certificates
* in truststore.
* Fetches the list of uniqueIdentifiers for complete certificate chain using certificates in truststore.
*
* @param x509Certificates Client certificate chain
* @param x509Certificates client certificates chain
* @param uniqueIdentifiers Unique identifiers list for client certificate chain
* @return Tier
* @return uniqueIdentifiers
* @throws APIManagementException
*/
private String getTierFromCompleteCertificateChain(List<X509Certificate> x509Certificates,
List<String> uniqueIdentifiers) throws APIManagementException {
private List<String> getUniqueIdentifierFromCompleteCertificateChain(List<X509Certificate> x509Certificates,
List<String> uniqueIdentifiers) throws APIManagementException {

String tier = null;
X509Certificate certificate = x509Certificates.get(x509Certificates.size() - 1);
String subjectDN = certificate.getSubjectDN().getName();
String issuerDN = certificate.getIssuerDN().getName();
Expand All @@ -266,16 +278,47 @@ private String getTierFromCompleteCertificateChain(List<X509Certificate> x509Cer
isIssuerCertificateUpdated = !StringUtils.equals(subjectDN, issuerDN);
}
}
return uniqueIdentifiers;
}

/**
* Fetches tier assigned to the client certificate after making the complete certificate chain using certificates
* in truststore.
*
* @param uniqueIdentifiers Unique identifiers list for client certificate chain
* @return Tier
*/
private String getTierFromCompleteCertificateChain(List<String> uniqueIdentifiers) {

String tier = null;
for (String uniqueIdentifier : uniqueIdentifiers) {
tier = certificates.get(uniqueIdentifier);
tier = certificates.get(uniqueIdentifier).get(APIConstants.CLIENT_CERTIFICATE_TIER);
if (StringUtils.isNotEmpty(tier)) {
break;
}
}
return tier;
}

/**
* Fetches keyType assigned to the client certificate after making the complete certificate chain using certificates
* in truststore.
*
* @param uniqueIdentifiers Unique identifiers list for client certificate chain
* @return keyType
*/
private String getKeyTypeFromCompleteCertificateChain(List<String> uniqueIdentifiers) {

String keyType = null;
for (String uniqueIdentifier : uniqueIdentifiers) {
keyType = certificates.get(uniqueIdentifier).get(APIConstants.CLIENT_CERTIFICATE_KEY_TYPE);
if (StringUtils.isNotEmpty(keyType)) {
break;
}
}
return keyType;
}

/**
* Handles failures where message context does not contain client certificates.
* @param messageContext Relevant message context
Expand Down Expand Up @@ -321,7 +364,7 @@ private void handleCertificateNotAssociatedToAPIFailure(MessageContext messageCo
* @param tier Throttling policy tier
*/
private void setAuthenticationContext(MessageContext messageContext, String subjectDN, String uniqueIdentifier,
String tier) {
String tier, String keyType) {

AuthenticationContext authContext = new AuthenticationContext();
authContext.setAuthenticated(true);
Expand All @@ -340,7 +383,7 @@ private void setAuthenticationContext(MessageContext messageContext, String subj
}
authContext.setApiTier(apiLevelPolicy);
APIIdentifier apiIdentifier = getAPIIdentifier(messageContext);
authContext.setKeyType(APIConstants.API_KEY_TYPE_PRODUCTION);
authContext.setKeyType(keyType);
authContext.setStopOnQuotaReach(true);
authContext.setApiKey(uniqueIdentifier + "_" + apiIdentifier.toString());
authContext.setTier(tier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,9 @@ private Permissions() {
public static final String API_KEY_VALIDATOR_URL = API_KEY_VALIDATOR + "ServerURL";
public static final String API_KEY_VALIDATOR_USERNAME = API_KEY_VALIDATOR + "Username";
public static final String API_KEY_VALIDATOR_PASSWORD = API_KEY_VALIDATOR + "Password";
public static final String CLIENT_CERTIFICATE_TIER = "TIER";
public static final String CLIENT_CERTIFICATE_KEY_TYPE = "KEY_TYPE";

public static final String ENABLE_DEFAULT_KEY_MANAGER_REGISTRATION = API_KEY_VALIDATOR +
"EnableDefaultKeyManagerRegistration";
public static final String ENABLE_KEY_MANAGER_RETRIVAL = API_KEY_VALIDATOR +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public boolean updateClientCertificate(String certificate, String alias, String
if (StringUtils.isNotEmpty(tier)) {
clientCertificateDTO.setTierName(tier);
}
if (StringUtils.isNotEmpty(tier)) {
if (StringUtils.isNotEmpty(keyType)) {
clientCertificateDTO.setKeyType(keyType);
}
try (Connection connection = APIMgtDBUtil.getConnection()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public final class ImportExportConstants {
public static final String ALIAS_JSON_KEY = "alias";

public static final String ENDPOINT_JSON_KEY = "endpoint";
public static final String KEY_TYPE_JSON_KEY = "keyType";

public static final int REFER_REQUIRE_RE_SUBSCRIPTION_CHECK_ITEM = 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,12 @@ public static APITemplateBuilderImpl getAPITemplateBuilder(API api, String tenan
if (clientCertificateDTOS != null) {
clientCertificateObject = new HashMap<>();
for (ClientCertificateDTO clientCertificateDTO : clientCertificateDTOS) {
/* appending the values without using a data structure to store them separately to avoid conflicts
when reading from certificatesDetails string at MutualSSLAuthenticator */
clientCertificateObject.put(certificateMgtUtils
.getUniqueIdentifierOfCertificate(clientCertificateDTO.getCertificate()),
clientCertificateDTO.getTierName());
clientCertificateDTO.getTierName().concat(APIConstants.DELEM_COLON)
.concat(clientCertificateDTO.getKeyType()));
}
}

Expand Down Expand Up @@ -369,9 +372,13 @@ public static APITemplateBuilderImpl getAPITemplateBuilder(APIProduct apiProduct
if (clientCertificateDTOS != null) {
clientCertificateObject = new HashMap<>();
for (ClientCertificateDTO clientCertificateDTO : clientCertificateDTOS) {
clientCertificateObject.put(certificateMgtUtils
.getUniqueIdentifierOfCertificate(clientCertificateDTO.getCertificate()),
clientCertificateDTO.getTierName());
/* appending the values without using a data structure to store them separately to avoid conflicts
when reading from certificatesDetails string at MutualSSLAuthenticator */
clientCertificateObject.put(certificateMgtUtils.
getUniqueIdentifierOfCertificate(clientCertificateDTO.getCertificate()),
clientCertificateDTO.getTierName().concat(APIConstants.DELEM_COLON)
.concat(clientCertificateDTO.getKeyType()));

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@ private static void handleClientCertificates(JsonArray certificates, Identifier
ClientCertificateDTO cert = new ClientCertificateDTO();
cert.setApiIdentifier(apiIdentifier);
cert.setAlias(alias);
cert.setKeyType(certObject.get(ImportExportConstants.KEY_TYPE_JSON_KEY).getAsString());
cert.setTierName(certObject.get(ImportExportConstants.CERTIFICATE_TIER_NAME_PROPERTY).getAsString());
String certName = certObject.get(ImportExportConstants.CERTIFICATE_PATH_PROPERTY).getAsString();
cert.setCertificate(certName);
Expand Down

0 comments on commit 475bf2a

Please sign in to comment.