Skip to content

Commit

Permalink
[#2825] Extend credentials management service to support auth-id temp…
Browse files Browse the repository at this point in the history
…late

* Add issuer-DN to credentials management specification.
* Extend credentials management service implementations
  to populate the new field generated-auth-id by applying
  the auth-id-template to the given subject DN.
* During find credentials by type and auth-id operation,
  the generated-auth-id is looked for any matching value.
  If there is no value, then the auth-id field is used.

Signed-off-by: Kartheeswaran Kalidass <[email protected]>
  • Loading branch information
kaniyan committed Dec 3, 2021
1 parent da94888 commit a9af944
Show file tree
Hide file tree
Showing 20 changed files with 482 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public final class CredentialsConstants extends RequestResponseApiConstants {
* The name of the field that contains the authentication identifier.
*/
public static final String FIELD_AUTH_ID = "auth-id";
/**
* The name of the field that contains the generated authentication identifier
* by applying the template to the subject DN.
*/
public static final String FIELD_GENERATED_AUTH_ID = "generated-auth-id";
/**
* The name of the field that contains the secret(s) of the credentials.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ public final class RegistryManagementConstants extends RequestResponseApiConstan
* The name of the field that contains the authentication identifier.
*/
public static final String FIELD_AUTH_ID = "auth-id";
/**
* The name of the field that contains the generated authentication identifier
* by applying the template to the subject DN.
*/
public static final String FIELD_GENERATED_AUTH_ID = "generated-auth-id";
/**
* The name of the field that contains the issuer DN of the client certificate.
*/
public static final String FIELD_ISSUER_DN = "issuer-dn";
/**
* The name of the field that contains the secret(s) of the credentials.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.hono.service.management.device.Device;
import org.eclipse.hono.service.management.tenant.Tenant;
import org.eclipse.hono.tracing.TracingHelper;
import org.eclipse.hono.util.RegistryManagementConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -162,6 +163,7 @@ public TableManagementStore(final SQLClient client, final Tracer tracer, final S
"device_id",
"type",
"auth_id",
"generated_auth_id",
"data");

this.deleteAllCredentialsStatement = cfg
Expand Down Expand Up @@ -692,8 +694,9 @@ public Future<Versioned<Boolean>> setCredentials(
.expand(map -> {
map.put("tenant_id", key.getTenantId());
map.put("device_id", key.getDeviceId());
map.put("type", c.getString("type"));
map.put("auth_id", c.getString("auth-id"));
map.put("type", c.getString(RegistryManagementConstants.FIELD_TYPE));
map.put("auth_id", c.getString(RegistryManagementConstants.FIELD_AUTH_ID));
map.put("generated_auth_id", c.getString(RegistryManagementConstants.FIELD_GENERATED_AUTH_ID));
map.put("data", c.toString());
})
.trace(this.tracer, span.context())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ insertCredentialEntry: |
device_id,
type,
auth_id,
generated_auth_id,
data
) VALUES (
:tenant_id,
:device_id,
:type,
:auth_id,
:generated_auth_id,
:data::jsonb
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ findCredentials: |
WHERE
tenant_id=:tenant_id
AND
auth_id=:auth_id
COALESCE(generated_auth_id, auth_id)=:auth_id
AND
type=:type
Expand All @@ -112,12 +112,14 @@ insertCredentialEntry: |
device_id,
type,
auth_id,
generated_auth_id,
data
) VALUES (
:tenant_id,
:device_id,
:type,
:auth_id,
:generated_auth_id,
:data
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ CREATE TABLE IF NOT EXISTS device_credentials
TENANT_ID VARCHAR(256) NOT NULL,
DEVICE_ID VARCHAR(256) NOT NULL,

TYPE VARCHAR(64) NOT NULL,
AUTH_ID VARCHAR(256) NOT NULL,
TYPE VARCHAR(64) NOT NULL,
AUTH_ID VARCHAR(256) NOT NULL,
GENERATED_AUTH_ID VARCHAR(256),

DATA TEXT,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ CREATE TABLE IF NOT EXISTS device_credentials
TENANT_ID VARCHAR(36) NOT NULL,
DEVICE_ID VARCHAR(256) NOT NULL,

TYPE VARCHAR(64) NOT NULL,
AUTH_ID VARCHAR(256) NOT NULL,
TYPE VARCHAR(64) NOT NULL,
AUTH_ID VARCHAR(256) NOT NULL,
GENERATED_AUTH_ID VARCHAR(256),

DATA JSONB,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.eclipse.hono.service.management.credentials.CommonCredential;
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.tenant.Tenant;
import org.eclipse.hono.util.Futures;
import org.eclipse.hono.util.Lifecycle;
import org.eclipse.hono.util.Strings;
Expand Down Expand Up @@ -177,10 +179,11 @@ public final Future<OperationResult<Void>> updateCredentials(
Objects.requireNonNull(resourceVersion);
Objects.requireNonNull(span);

return this.tenantInformationService
.getTenant(tenantId, span)
final Future<Tenant> tenantFuture = tenantInformationService.getTenant(tenantId, span);
return tenantFuture
.compose(tenant -> tenant.checkCredentialsLimitExceeded(tenantId, credentials))
.compose(ok -> verifyAndEncodePasswords(credentials))
.compose(ok -> applyAuthIdTemplateForX509CertificateCredentials(tenantFuture.result(), credentials))
.compose(this::verifyAndEncodePasswords)
.compose(encodedCredentials -> processUpdateCredentials(
DeviceKey.from(tenantId, deviceId),
encodedCredentials,
Expand Down Expand Up @@ -279,4 +282,13 @@ protected List<CommonCredential> checkCredentials(final List<CommonCredential> c
return credentials;
}

private static Future<List<CommonCredential>> applyAuthIdTemplateForX509CertificateCredentials(
final Tenant tenant,
final List<CommonCredential> credentials) {
credentials.stream()
.filter(X509CertificateCredential.class::isInstance)
.map(X509CertificateCredential.class::cast)
.forEach(c -> c.applyAuthIdTemplate(tenant));
return Future.succeededFuture(credentials);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.hono.util.CredentialsConstants;
import org.eclipse.hono.util.CredentialsResult;
import org.eclipse.hono.util.Lifecycle;
import org.eclipse.hono.util.RegistryManagementConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -180,6 +181,7 @@ public final Future<CredentialsResult<JsonObject>> get(
}
});
})
.map(AbstractCredentialsService::overrideAuthIdWithGeneratedAuthIdIfExists)
.recover(error -> {
LOG.debug("error getting credentials [tenant: {}, type: {}, auth-id: {}]", tenantId, type, authId, error);
TracingHelper.logError(span, error);
Expand All @@ -190,8 +192,20 @@ public final Future<CredentialsResult<JsonObject>> get(
});
}

private static CredentialsResult<JsonObject> overrideAuthIdWithGeneratedAuthIdIfExists(
final CredentialsResult<JsonObject> credentialsResult) {
if (!credentialsResult.isError()) {
final JsonObject credential = credentialsResult.getPayload();
Optional.ofNullable(credential)
.map(c -> c.getString(RegistryManagementConstants.FIELD_TYPE))
.filter(RegistryManagementConstants.SECRETS_TYPE_X509_CERT::equals)
.map(ok -> credential.getString(RegistryManagementConstants.FIELD_GENERATED_AUTH_ID))
.ifPresent(id -> credential.put(RegistryManagementConstants.FIELD_AUTH_ID, id));
}
return credentialsResult;
}

private boolean isAutoProvisioningConfigured() {
return this.deviceAndGatewayAutoProvisioner != null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ private DeviceRegistryUtils() {
*/
public static <T> Future<T> mapError(final Throwable error, final String tenantId) {
if (error instanceof IllegalArgumentException) {
return Future.failedFuture(new ClientErrorException(tenantId, HttpURLConnection.HTTP_BAD_REQUEST, error.getMessage()));
return Future.failedFuture(
new ClientErrorException(tenantId, HttpURLConnection.HTTP_BAD_REQUEST, error.getMessage(), error));
}
return Future.failedFuture(error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ public static PskCredential createPSKCredential(final String authId, final Strin
return new PskCredential(authId, List.of(s));
}

/**
* Creates a X509 certificate based credential from the given subject DN.
*
* @param subjectDN The subject DN.
* @return The X509 certificate credential.
*/
public static X509CertificateCredential createX509CertificateCredential(final String subjectDN) {
return X509CertificateCredential.fromSubjectDn(subjectDN, List.of(new X509CertificateSecret()));
}

/**
* Creates a password type based credential containing a hashed password secret.
*
Expand Down
Loading

0 comments on commit a9af944

Please sign in to comment.