Skip to content

Commit

Permalink
Small improvements and incorporate review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Kartheeswaran Kalidass <[email protected]>
  • Loading branch information
kaniyan committed Dec 7, 2021
1 parent 142b98a commit 6e5e0b7
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.eclipse.hono.service.management.credentials.CredentialsManagementService;
import org.eclipse.hono.service.management.credentials.PasswordCredential;
import org.eclipse.hono.service.management.credentials.X509CertificateCredential;
import org.eclipse.hono.service.management.credentials.X509CertificateCredentialWithGeneratedAuthId;
import org.eclipse.hono.service.management.tenant.Tenant;
import org.eclipse.hono.util.Futures;
import org.eclipse.hono.util.Lifecycle;
Expand Down Expand Up @@ -289,7 +290,8 @@ private static Future<List<CommonCredential>> applyAuthIdTemplateForX509Certific
final List<CommonCredential> creds = credentials.stream()
.map(cred -> {
if (cred instanceof X509CertificateCredential) {
return ((X509CertificateCredential) cred).applyAuthIdTemplate(tenant);
return X509CertificateCredentialWithGeneratedAuthId.applyAuthIdTemplate(
(X509CertificateCredential) cred, tenant);
}
return cred;
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@

import javax.security.auth.x500.X500Principal;

import org.eclipse.hono.service.management.tenant.Tenant;
import org.eclipse.hono.util.IdentityTemplate;
import org.eclipse.hono.util.RegistryManagementConstants;
import org.eclipse.hono.util.Strings;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonCreator.Mode;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
Expand Down Expand Up @@ -81,7 +78,7 @@ protected X509CertificateCredential(final String authId, final String generatedA
* @param generatedAuthId the authentication identifier generated by applying the <em>auth-id-template</em>
* from the tenant's trust anchor to the client certificate's subject DN.
* @param secrets The credential's secret(s).
* @throws NullPointerException if subject DN and secrets are {@code null}.
* @throws NullPointerException if subject DN or secrets is {@code null}.
*/
private X509CertificateCredential(final String subjectDN, final String issuerDN, final String generatedAuthId,
final List<X509CertificateSecret> secrets) {
Expand All @@ -107,7 +104,7 @@ private X509CertificateCredential(final String subjectDN, final String issuerDN,
* @param generatedAuthId the authentication identifier generated by applying the <em>auth-id-template</em>
* from the tenant's trust anchor to the client certificate's subject DN.
* @param secrets The credential's secret(s).
* @throws NullPointerException if certificate bytes, subject DN and secrets are {@code null}.
* @throws NullPointerException if certificate bytes and either subject DN or secrets are {@code null}.
* @throws IllegalArgumentException if the given byte array cannot be decoded into an X.509 certificate or if
* the given subject and issuer DNs are not a valid X.500 distinguished name or if
* secrets is empty.
Expand Down Expand Up @@ -164,7 +161,7 @@ public static X509CertificateCredential fromSubjectDn(
* @param generatedAuthId the authentication identifier generated by applying the <em>auth-id-template</em>
* from the tenant's trust anchor to the client certificate's subject DN.
* @param secrets The credential's secret(s).
* @throws NullPointerException if any of the parameters are {@code null}.
* @throws NullPointerException if subject DN or secrets is {@code null}.
* @throws IllegalArgumentException if the given subject DN or issuer DN is not a valid X.500
* distinguished name or if secrets is empty.
* @return The credentials.
Expand Down Expand Up @@ -262,38 +259,6 @@ public final X509CertificateCredential setSecrets(final List<X509CertificateSecr
return this;
}

/**
* Applies the <em>auth-id-template</em> from the tenant's trust anchor to the client certificate's subject DN.
* <p>
* It is only applicable, if a template is configured.
*
* @param tenant The tenant information.
* @return the credential with the generated authentication identifier.
* @throws NullPointerException if the tenant is {@code null}.
*/
@JsonIgnore
public final X509CertificateCredential applyAuthIdTemplate(final Tenant tenant) {
Objects.requireNonNull(tenant, "tenant information must not be null");

final String generatedAuthId = Optional.ofNullable(issuerDN)
.flatMap(tenant::getAuthIdTemplate)
.map(IdentityTemplate::new)
.map(t -> t.apply(getAuthId()))
.orElse(null);
final X509CertificateCredential credential = new X509CertificateCredential(getAuthId(),
generatedAuthId, secrets) {

@Override
@JsonGetter(value = RegistryManagementConstants.FIELD_GENERATED_AUTH_ID)
protected String getGeneratedAuthId() {
return super.getGeneratedAuthId();
}
};

copyCommonAttributesTo(credential);
return credential;
}

/**
* Overrides the authentication identifier with the generated authentication identifier,
* if the generated one is not {@code null}.
Expand All @@ -310,6 +275,15 @@ public final X509CertificateCredential overrideAuthIdWithGeneratedAuthId() {
return credential;
}

/**
* Gets the issuer DN of the client certificate.
*
* @return The issuer DN of the client certificate or {@code null}.
*/
protected final String getIssuerDN() {
return issuerDN;
}

/**
* Gets the authentication identifier generated by applying the <em>auth-id-template</em>
* from the tenant's trust anchor to the client certificate's subject DN.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.hono.service.management.credentials;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.eclipse.hono.service.management.tenant.Tenant;
import org.eclipse.hono.util.IdentityTemplate;
import org.eclipse.hono.util.RegistryManagementConstants;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* An extended {@link X509CertificateCredential} to handle the generated authentication identifier.
*/
public class X509CertificateCredentialWithGeneratedAuthId extends X509CertificateCredential {

/**
* Creates a new credentials object from the given authentication identifier, generated authentication
* identifier and secrets.
*
* @param authId The authentication identifier.
* @param generatedAuthId the authentication identifier generated by applying the <em>auth-id-template</em>
* from the tenant's trust anchor to the client certificate's subject DN.
* @param secrets The credential's secret(s).
* @throws NullPointerException if authentication identifier or secrets is {@code null}.
*/
private X509CertificateCredentialWithGeneratedAuthId(final String authId, final String generatedAuthId,
final List<X509CertificateSecret> secrets) {
super(authId, generatedAuthId, secrets);
}

/**
* Gets the authentication identifier generated by applying the <em>auth-id-template</em> from the tenant's
* trust anchor to the client certificate's subject DN.
*
* @return The generated authentication identifier or {@code null}.
*/
@JsonGetter(value = RegistryManagementConstants.FIELD_GENERATED_AUTH_ID)
@Override
public final String getGeneratedAuthId() {
return super.getGeneratedAuthId();
}

/**
* Applies the <em>auth-id-template</em> from the tenant's trust anchor to the client certificate's subject DN.
* <p>
* It is only applicable, if a template is configured.
*
* @param credential The x509 certificate credential.
* @param tenant The tenant information.
* @return the credential with generated authentication identifier.
* @throws NullPointerException if the tenant is {@code null}.
*/
@JsonIgnore
public static X509CertificateCredentialWithGeneratedAuthId applyAuthIdTemplate(
final X509CertificateCredential credential, final Tenant tenant) {
Objects.requireNonNull(credential, "credential must not be null");
Objects.requireNonNull(tenant, "tenant information must not be null");

final String generatedAuthId = Optional.ofNullable(credential.getIssuerDN())
.flatMap(tenant::getAuthIdTemplate)
.map(IdentityTemplate::new)
.map(t -> t.apply(credential.getAuthId()))
.orElse(null);
final X509CertificateCredentialWithGeneratedAuthId credWithId = new X509CertificateCredentialWithGeneratedAuthId(
credential.getAuthId(), generatedAuthId, credential.getSecrets());

credWithId.setComment(credential.getComment());
credWithId.setEnabled(credential.isEnabled());
credWithId.setExtensions(credential.getExtensions());

return credWithId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,6 @@ private X509CertificateCredential getCertificateByApplyingTemplate(final String
.setNotAfter(Instant.now().plus(2, ChronoUnit.DAYS));
final var tenant = new Tenant().setTrustedCertificateAuthorities(List.of(trustedCa));

return credential.applyAuthIdTemplate(tenant);
return X509CertificateCredentialWithGeneratedAuthId.applyAuthIdTemplate(credential, tenant);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,35 @@ public JsonObject document() {

/**
* Sets the json object with the given credentials type and auth id.
* <p>
* If the type equals {@value RegistryManagementConstants#SECRETS_TYPE_X509_CERT},
* the MongoDB query is framed to match the given auth id
* <ul>
* <li>with the field <em>generated-auth-id</em>.</li>
* <li>if no match found and the <em>generated-auth-id</em> is {@code null}, the field <em>auth-id</em> is used.
* </li>
* </ul>
* Example query with type as {@value RegistryManagementConstants#SECRETS_TYPE_X509_CERT}
* and auth id as "Device1-Hono-Eclipse":
* <pre>
* {
* "credentials": {
* "$elemMatch": {
* "type": {@value RegistryManagementConstants#SECRETS_TYPE_X509_CERT},
* "$or": [
* {
* "generated-auth-id": "Device1-Hono-Eclipse"
* },
* {
* "generated-auth-id": null,
* "auth-id": "Device1-Hono-Eclipse"
* }
* ]
* }
* }
* }
* </pre>
* Else the given auth-id is matched with the field <em>auth-id</em>.
*
* @param type The credentials type.
* @param authId The authentication identifier
Expand Down

0 comments on commit 6e5e0b7

Please sign in to comment.