blob: 78a8a5404d0309185ab39e8875a3c5f6bf1ae945 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.kerby.kerberos.kerb.identity.backend;
import java.io.IOException;
import java.util.Collections;
import org.apache.kerby.config.Configured;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.identity.BatchTrans;
import org.apache.kerby.kerberos.kerb.request.KdcClientRequest;
import org.apache.kerby.kerberos.kerb.request.KrbIdentity;
import org.apache.kerby.kerberos.kerb.type.ad.AdToken;
import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationDataEntry;
import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationType;
import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
import org.apache.kerby.kerberos.kerb.type.base.TokenFormat;
import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An abstract identity backend that provides default behaviors and a cache
* with FIFO and size limit. Note only limited recently active identities are
* kept in the cache, and other identities are meant to be loaded from
* persistent storage by specific backend, like memory, file, SQL DB, LDAP,
* and etc.
*/
public abstract class AbstractIdentityBackend
extends Configured implements IdentityBackend {
private static Logger logger =
LoggerFactory.getLogger(AbstractIdentityBackend.class);
/**
* Get the Backend Config.
* @return The backend config
*/
protected BackendConfig getBackendConfig() {
return (BackendConfig) getConfig();
}
/**
* {@inheritDoc}
*/
@Override
public void initialize() throws KrbException {
logger.debug("initialize called");
doInitialize();
}
/**
* {@inheritDoc}
*/
@Override
public boolean supportBatchTrans() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public BatchTrans startBatchTrans() throws KrbException {
throw new KrbException("Transaction isn't supported");
}
/**
* Perform the real initialization work for the backend.
* @throws KrbException e
*/
protected void doInitialize() throws KrbException { }
/**
* {@inheritDoc}
*/
@Override
public void start() {
doStart();
logger.debug("start called");
}
/**
* Perform the real start work for the backend.
*/
protected void doStart() { }
/**
* {@inheritDoc}
*/
@Override
public void stop() throws KrbException {
doStop();
logger.debug("stop called");
}
/**
* Perform the real stop work for the backend.
* @throws KrbException e
*/
protected void doStop() throws KrbException { }
/**
* {@inheritDoc}
*/
@Override
public void release() {
doRelease();
logger.debug("release called");
}
/**
* Perform the real release work for the backend.
*/
protected void doRelease() { }
/**
* {@inheritDoc}
*/
@Override
public Iterable<String> getIdentities() throws KrbException {
logger.debug("getIdentities called");
return doGetIdentities();
}
/**
* Perform the real work to get identities.
* @return The identities
* @throws KrbException e
*/
protected abstract Iterable<String> doGetIdentities() throws KrbException;
/**
* {@inheritDoc}
*/
@Override
public KrbIdentity getIdentity(String principalName) throws KrbException {
if (principalName == null || principalName.isEmpty()) {
throw new IllegalArgumentException("Invalid principal name");
}
logger.debug("getIdentity called, principalName = {}", principalName);
KrbIdentity identity = doGetIdentity(principalName);
logger.debug("getIdentity {}, principalName = {}",
(identity != null ? "successful" : "failed"), principalName);
return identity;
}
/**
* Add an identity, invoked by addIdentity.
* @param principalName The principal name
* @return The added identity
* @throws KrbException e
*/
protected abstract KrbIdentity doGetIdentity(String principalName) throws KrbException;
/**
* {@inheritDoc}
*/
@Override
public AuthorizationData getIdentityAuthorizationData(KdcClientRequest kdcClientRequest,
EncTicketPart encTicketPart) throws KrbException {
if (kdcClientRequest == null) {
throw new IllegalArgumentException("Invalid identity");
}
logger.debug("getIdentityAuthorizationData called, krbIdentity = {}",
kdcClientRequest.getClientPrincipal());
AuthorizationData authData = doGetIdentityAuthorizationData(kdcClientRequest,
encTicketPart);
logger.debug("getIdentityAuthorizationData {}, authData = {}",
(authData != null ? "successful" : "failed"), authData);
return authData;
}
/**
* Get an identity's Authorization Data, invoked by getIdentityAuthorizationData.
* @param kdcClientRequest The KdcClientRequest
* @param encTicketPart The EncTicketPart being built for the KrbIdentity
* @return The Authorization Data
* @throws KrbException e
*/
protected AuthorizationData doGetIdentityAuthorizationData(
KdcClientRequest kdcClientRequest, EncTicketPart encTicketPart)
throws KrbException {
if (kdcClientRequest.isToken()) {
KrbToken krbToken = new KrbToken(kdcClientRequest.getToken(), TokenFormat.JWT);
AdToken adToken = new AdToken();
adToken.setToken(krbToken);
AuthorizationData authzData = new AuthorizationData();
AuthorizationDataEntry authzDataEntry = new AuthorizationDataEntry();
try {
authzDataEntry.setAuthzData(adToken.encode());
} catch (IOException e) {
throw new KrbException("Error encoding AdToken", e);
}
authzDataEntry.setAuthzType(AuthorizationType.AD_TOKEN);
authzData.setElements(Collections.singletonList(authzDataEntry));
return authzData;
}
return null;
}
/** {@inheritDoc} */
@Override
public KrbIdentity addIdentity(KrbIdentity identity) throws KrbException {
if (identity == null) {
throw new IllegalArgumentException("null identity to add");
}
if (doGetIdentity(identity.getPrincipalName()) != null) {
throw new KrbException("Principal already exists: "
+ identity.getPrincipalName());
}
KrbIdentity added = doAddIdentity(identity);
logger.debug("addIdentity {}, principalName = {}",
(added != null ? "successful" : "failed"), identity.getPrincipalName());
return added;
}
/**
* Add an identity, invoked by addIdentity, and return added identity.
* @param identity The identity to be added
* @return The added identity
* @throws KrbException e
*/
protected abstract KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException;
/**
* {@inheritDoc}
*/
@Override
public KrbIdentity updateIdentity(KrbIdentity identity) throws KrbException {
if (identity == null) {
throw new IllegalArgumentException("null identity to update");
}
if (doGetIdentity(identity.getPrincipalName()) == null) {
logger.error("Error occurred while updating identity, principal "
+ identity.getPrincipalName() + " does not exists.");
throw new KrbException("Principal does not exist.");
}
KrbIdentity updated = doUpdateIdentity(identity);
logger.debug("updateIdentity {}, principalName = {}",
(updated != null ? "successful" : "failed"), identity.getPrincipalName());
return updated;
}
/**
* Update an identity, invoked by updateIdentity, and return updated identity.
* @param identity The origin identity
* @return The updated identity
* @throws KrbException e
*/
protected abstract KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException;
/**
* {@inheritDoc}
*/
@Override
public void deleteIdentity(String principalName) throws KrbException {
logger.debug("deleteIdentity called, principalName = {}", principalName);
if (principalName == null) {
throw new IllegalArgumentException("null identity to remove");
}
if (doGetIdentity(principalName) == null) {
logger.error("Error occurred while deleting identity, principal "
+ principalName + " does not exist.");
throw new KrbException("Principal does not exist.");
}
doDeleteIdentity(principalName);
}
/**
* Delete an identity, invoked by deleteIndentity.
* @param principalName The principal name
* @throws KrbException e
*/
protected abstract void doDeleteIdentity(String principalName) throws KrbException;
}