diff options
author | Endi S. Dewata <edewata@redhat.com> | 2016-03-21 21:40:02 +0100 |
---|---|---|
committer | Endi S. Dewata <edewata@redhat.com> | 2016-03-28 18:59:10 +0200 |
commit | 93179af9333197cbdce843f16c02107b8d1db17e (patch) | |
tree | a0311796ed3c168ad0997b24af457cd79576fba3 | |
parent | c22d9a99240d2f24eb7b0ee11c3153fa475d47a1 (diff) | |
download | pki-93179af9333197cbdce843f16c02107b8d1db17e.tar.gz pki-93179af9333197cbdce843f16c02107b8d1db17e.tar.xz pki-93179af9333197cbdce843f16c02107b8d1db17e.zip |
Generating TEMP_LOST to UNINITIALIZED/ACTIVE transitions dynamically.
The TPS subsystem has been modified to generate the token state
transitions from TEMP_LOST to UNINITIALIZED or ACTIVE dynamically
depending on whether the token has certificates.
The TEMP_LOST to ACTIVE transition has been removed from the CS.cfg.
Duplicate code that loads the allowed transitions list has been
merged and moved into TPSSubsystem.
https://fedorahosted.org/pki/ticket/1808
-rw-r--r-- | base/tps-client/doc/CS.cfg.in | 2 | ||||
-rw-r--r-- | base/tps/shared/conf/CS.cfg.in | 2 | ||||
-rw-r--r-- | base/tps/shared/conf/token-states.properties | 1 | ||||
-rw-r--r-- | base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java | 68 | ||||
-rw-r--r-- | base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java | 41 | ||||
-rw-r--r-- | base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java | 114 |
6 files changed, 98 insertions, 130 deletions
diff --git a/base/tps-client/doc/CS.cfg.in b/base/tps-client/doc/CS.cfg.in index ddfab8824..f1a79032a 100644 --- a/base/tps-client/doc/CS.cfg.in +++ b/base/tps-client/doc/CS.cfg.in @@ -1545,7 +1545,7 @@ tokendb.confirmDeleteConfigTemplate=confirmDeleteConfig.template log.instance.SignedAudit.selected.events=ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,CONFIG,CONFIG_ROLE,CONFIG_TOKEN,CONFIG_PROFILE,CONFIG_AUDIT,APPLET_UPGRADE,KEY_CHANGEOVER,RENEWAL log.instance.SignedAudit.selectable.events=ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE,PRIVATE_KEY_ARCHIVE_PROCESSED,KEY_RECOVERY_REQUEST,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_PROCESSED,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,CONFIG,CONFIG_ROLE,CONFIG_TOKEN,CONFIG_PROFILE,CONFIG_AUDIT,APPLET_UPGRADE,KEY_CHANGEOVER,RENEWAL log.instance.SignedAudit.nonselectable.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_PROCESSED,SERVER_SIDE_KEYGEN_REQUEST -tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:4,3:6,4:1,4:2,4:3,4:6 +tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:6,4:1,4:2,4:3,4:6 target._000=######################################### target._001=# entries to enable configuration of parameter sets through the TPS UI agent and admin tabs target._002=# diff --git a/base/tps/shared/conf/CS.cfg.in b/base/tps/shared/conf/CS.cfg.in index 2285300ec..d7a10729d 100644 --- a/base/tps/shared/conf/CS.cfg.in +++ b/base/tps/shared/conf/CS.cfg.in @@ -1966,7 +1966,7 @@ tokendb.addConfigTemplate=addConfig.template tokendb.addResultTemplate=addResults.template tokendb.agentSelectConfigTemplate=agentSelectConfig.template tokendb.agentViewConfigTemplate=agentViewConfig.template -tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:4,3:6,4:1,4:2,4:3,4:6 +tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:6,4:1,4:2,4:3,4:6 tokendb.auditAdminTemplate=auditAdmin.template tokendb.auditLog=[PKI_INSTANCE_PATH]/logs/tokendb-audit.log tokendb.baseDN=ou=Tokens,[TOKENDB_ROOT] diff --git a/base/tps/shared/conf/token-states.properties b/base/tps/shared/conf/token-states.properties index f67688d4b..a64d940c6 100644 --- a/base/tps/shared/conf/token-states.properties +++ b/base/tps/shared/conf/token-states.properties @@ -15,6 +15,7 @@ UNINITIALIZED.TERMINATED = This token has been terminated. TEMP_LOST.ACTIVE = This temporarily lost token has been found. TEMP_LOST.PERM_LOST = This temporarily lost token has become permanently lost. TEMP_LOST.TERMINATED = This temporarily lost token has been terminated. +TEMP_LOST.UNINITIALIZED = This temporarily lost token has been found. ACTIVE.DAMAGED = This token has been physically damaged. ACTIVE.PERM_LOST = This token has been permanently lost. ACTIVE.TEMP_LOST = This token has been temporarily lost. diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java index e8734a9b8..008f61333 100644 --- a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java +++ b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java @@ -17,6 +17,11 @@ // --- END COPYRIGHT BLOCK --- package org.dogtagpki.server.tps; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; + import org.dogtagpki.server.tps.authentication.AuthenticationManager; import org.dogtagpki.server.tps.cms.ConnectionManager; import org.dogtagpki.server.tps.config.AuthenticatorDatabase; @@ -26,7 +31,9 @@ import org.dogtagpki.server.tps.config.ProfileDatabase; import org.dogtagpki.server.tps.config.ProfileMappingDatabase; import org.dogtagpki.server.tps.dbs.ActivityDatabase; import org.dogtagpki.server.tps.dbs.TPSCertDatabase; +import org.dogtagpki.server.tps.dbs.TPSCertRecord; import org.dogtagpki.server.tps.dbs.TokenDatabase; +import org.dogtagpki.server.tps.dbs.TokenRecord; import org.dogtagpki.server.tps.engine.TPSEngine; import org.dogtagpki.server.tps.mapping.MappingResolverManager; import org.mozilla.jss.CryptoManager; @@ -43,6 +50,7 @@ import com.netscape.certsrv.dbs.IDBSubsystem; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.request.IRequestListener; import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.tps.token.TokenStatus; import com.netscape.cmscore.dbs.DBSubsystem; /** @@ -70,8 +78,10 @@ public class TPSSubsystem implements IAuthority, ISubsystem { public ConnectionManager connManager; public AuthenticationManager authManager; public MappingResolverManager mappingResolverManager; + public TPSEngine engine; public TPSTokendb tdb; + public Map<TokenStatus, Collection<TokenStatus>> allowedTransitions = new HashMap<TokenStatus, Collection<TokenStatus>>(); @Override public String getId() { @@ -105,6 +115,26 @@ public class TPSSubsystem implements IAuthority, ISubsystem { connectorDatabase = new ConnectorDatabase(); profileDatabase = new ProfileDatabase(); profileMappingDatabase = new ProfileMappingDatabase(); + + CMS.debug("TokenSubsystem: allowed transitions:"); + + // initialize allowed token state transitions with empty containers + for (TokenStatus state : TokenStatus.values()) { + allowedTransitions.put(state, new LinkedHashSet<TokenStatus>()); + } + + // load allowed token state transitions from TPS configuration + for (String transition : cs.getString(TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS).split(",")) { + String states[] = transition.split(":"); + + TokenStatus fromState = TokenStatus.fromInt(Integer.valueOf(states[0])); + TokenStatus toState = TokenStatus.fromInt(Integer.valueOf(states[1])); + CMS.debug("TokenSubsystem: - " + fromState + " to " + toState); + + Collection<TokenStatus> nextStates = allowedTransitions.get(fromState); + nextStates.add(toState); + } + tdb = new TPSTokendb(this); engine = new TPSEngine(); @@ -112,6 +142,44 @@ public class TPSSubsystem implements IAuthority, ISubsystem { } + /** + * Return the allowed next states for a given token based on TPS configuration. + * + * If the current state is TEMP_LOST, token will be allowed transition to either + * UNINITIALIZED or ACTIVE depending on whether the token has certificates. + * + * @param tokenRecord + * @return A non-null collection of allowed next token states. + */ + public Collection<TokenStatus> getNextTokenStates(TokenRecord tokenRecord) throws Exception { + + TokenStatus currentState = tokenRecord.getTokenStatus(); + Collection<TokenStatus> nextStates = allowedTransitions.get(currentState); + + if (currentState == TokenStatus.TEMP_LOST) { + + Collection<TokenStatus> ns = new LinkedHashSet<TokenStatus>(); + + // check token certificates + Collection<TPSCertRecord> certRecords = tdb.tdbGetCertRecordsByCUID(tokenRecord.getId()); + + // if token has no certificates, allow token to become uninitialized again + if (certRecords.isEmpty()) { + ns.add(TokenStatus.UNINITIALIZED); + + } else { // otherwise, allow token to become active again + ns.add(TokenStatus.ACTIVE); + } + + // add the original allowed next states + ns.addAll(nextStates); + + return ns; + } + + return nextStates; + } + @Override public void startup() throws EBaseException { CMS.debug("TPSSubsystem: startup() begins"); diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java index 15e85fb32..51f496652 100644 --- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java +++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -31,7 +30,6 @@ import org.dogtagpki.server.tps.cms.CARevokeCertResponse; import org.dogtagpki.server.tps.dbs.ActivityDatabase; import org.dogtagpki.server.tps.dbs.TPSCertRecord; import org.dogtagpki.server.tps.dbs.TokenRecord; -import org.dogtagpki.server.tps.engine.TPSEngine; import org.dogtagpki.server.tps.main.ExternalRegAttrs; import org.dogtagpki.server.tps.main.ExternalRegCertToRecover; import org.dogtagpki.tps.main.TPSException; @@ -48,8 +46,8 @@ import netscape.security.x509.RevocationReason; * TPSTokendb class offers a collection of tokendb management convenience routines */ public class TPSTokendb { + private TPSSubsystem tps; - private Map<TokenStatus, Collection<TokenStatus>> allowedTransitions = new HashMap<TokenStatus, Collection<TokenStatus>>(); public TPSTokendb(TPSSubsystem tps) throws EBaseException { if (tps == null) { @@ -58,44 +56,17 @@ public class TPSTokendb { throw new EBaseException(msg); } this.tps = tps; - try { - initAllowedTransitions(); - } catch (Exception e) { - CMS.debug("TPSTokendb: initAllowedTransitions() failed:" + e); - throw new EBaseException(e.toString()); - } } - void initAllowedTransitions() - throws Exception { - CMS.debug("TPSTokendb.initAllowedTransitions()"); - IConfigStore configStore = CMS.getConfigStore(); - - // load allowed token state transitions - CMS.debug("TPSTokendbs: allowed transitions:"); - - for (String transition : configStore.getString(TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS).split(",")) { - String states[] = transition.split(":"); - TokenStatus fromState = TokenStatus.fromInt(Integer.valueOf(states[0])); - TokenStatus toState = TokenStatus.fromInt(Integer.valueOf(states[1])); - CMS.debug("TPSTokendb: - " + fromState + " to " + toState); - - Collection<TokenStatus> nextStates = allowedTransitions.get(fromState); - if (nextStates == null) { - nextStates = new HashSet<TokenStatus>(); - allowedTransitions.put(fromState, nextStates); - } - nextStates.add(toState); - } - } - - public boolean isTransitionAllowed(TokenRecord tokenRecord, TokenStatus newState) { + public boolean isTransitionAllowed(TokenRecord tokenRecord, TokenStatus newState) throws Exception { boolean result = false; TokenStatus currentTokenStatus = tokenRecord.getTokenStatus(); + CMS.debug("TokenRecord.isTransitionAllowed(): current status: " + currentTokenStatus); - Collection<TokenStatus> nextStatuses = allowedTransitions.get(currentTokenStatus); + Collection<TokenStatus> nextStatuses = tps.getNextTokenStates(tokenRecord); + CMS.debug("TokenRecord.isTransitionAllowed(): allowed next statuses: " + nextStatuses); - if (nextStatuses == null || !nextStatuses.contains(newState)) { + if (!nextStatuses.contains(newState)) { CMS.debug("TokenRecord.isTransitionAllowed(): next status not allowed: " + newState); result = false; diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java index a0ca7add3..958843e5b 100644 --- a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java +++ b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java @@ -24,7 +24,6 @@ import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.ResourceBundle; @@ -39,15 +38,12 @@ import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; import org.dogtagpki.server.tps.TPSSubsystem; import org.dogtagpki.server.tps.dbs.ActivityDatabase; -import org.dogtagpki.server.tps.dbs.TPSCertRecord; import org.dogtagpki.server.tps.dbs.TokenDatabase; import org.dogtagpki.server.tps.dbs.TokenRecord; -import org.dogtagpki.server.tps.engine.TPSEngine; import org.jboss.resteasy.plugins.providers.atom.Link; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.BadRequestException; -import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.PKIException; import com.netscape.certsrv.dbs.EDBException; import com.netscape.certsrv.ldap.LDAPExceptionConverter; @@ -77,58 +73,8 @@ public class TokenService extends PKIService implements TokenResource { @Context private HttpServletRequest servletRequest; - public Map<TokenStatus, Collection<TokenStatus>> transitions = new HashMap<TokenStatus, Collection<TokenStatus>>(); - public TokenService() throws Exception { CMS.debug("TokenService.<init>()"); - IConfigStore configStore = CMS.getConfigStore(); - - // load allowed token state transitions - CMS.debug("TokenService: allowed transitions:"); - - for (String transition : configStore.getString(TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS).split(",")) { - String states[] = transition.split(":"); - TokenStatus fromState = TokenStatus.fromInt(Integer.valueOf(states[0])); - TokenStatus toState = TokenStatus.fromInt(Integer.valueOf(states[1])); - CMS.debug("TokenService: - " + fromState + " to " + toState); - - Collection<TokenStatus> nextStates = transitions.get(fromState); - if (nextStates == null) { - nextStates = new HashSet<TokenStatus>(); - transitions.put(fromState, nextStates); - } - nextStates.add(toState); - } - - } - - public TokenStatus getTokenStatus(TokenRecord tokenRecord) { - String status = tokenRecord.getStatus(); - - if ("uninitialized".equals(status)) { - return TokenStatus.UNINITIALIZED; - - } else if ("active".equals(status)) { - return TokenStatus.ACTIVE; - - } else if ("lost".equals(status)) { - String reason = tokenRecord.getReason(); - - if ("keyCompromise".equals(reason)) { - return TokenStatus.PERM_LOST; - - } else if ("destroyed".equals(reason)) { - return TokenStatus.DAMAGED; - - } else if ("onHold".equals(reason)) { - return TokenStatus.TEMP_LOST; - } - - } else if ("terminated".equals(status)) { - return TokenStatus.TERMINATED; - } - - return TokenStatus.PERM_LOST; } public void setTokenStatus(TokenRecord tokenRecord, TokenStatus tokenState, String ipAddress, String remoteUser) @@ -142,33 +88,14 @@ public class TokenService extends PKIService implements TokenResource { break; case ACTIVE: - String origStatus = tokenRecord.getStatus(); - String origReason = tokenRecord.getReason(); - - if (origStatus.equalsIgnoreCase("lost") && - origReason.equalsIgnoreCase("onHold")) { - - Collection<TPSCertRecord> certRecords = tps.tdb.tdbGetCertRecordsByCUID(tokenRecord.getId()); - if (certRecords.isEmpty()) { // token was uninitialized - // restore to uninitialized state - tokenRecord.setStatus("uninitialized"); - tokenRecord.setReason(null); - - } else { // token was active - // unrevoke certs - tps.tdb.unRevokeCertsByCUID(tokenRecord.getId(), ipAddress, remoteUser); - - // restore to active state - tokenRecord.setStatus("active"); - tokenRecord.setReason(null); - } - - } else { - // switch to active state - tokenRecord.setStatus("active"); - tokenRecord.setReason(null); + if (tokenRecord.getTokenStatus() == TokenStatus.TEMP_LOST) { + // unrevoke certs + tps.tdb.unRevokeCertsByCUID(tokenRecord.getId(), ipAddress, remoteUser); } + tokenRecord.setStatus("active"); + tokenRecord.setReason(null); + break; case PERM_LOST: @@ -221,6 +148,8 @@ public class TokenService extends PKIService implements TokenResource { public TokenData createTokenData(TokenRecord tokenRecord) throws Exception { + TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + ResourceBundle labels = getResourceBundle("token-states"); TokenData tokenData = new TokenData(); @@ -229,23 +158,21 @@ public class TokenService extends PKIService implements TokenResource { tokenData.setUserID(tokenRecord.getUserID()); tokenData.setType(tokenRecord.getType()); - TokenStatus status = getTokenStatus(tokenRecord); + TokenStatus status = tokenRecord.getTokenStatus(); TokenStatusData statusData = new TokenStatusData(); statusData.name = status; statusData.label = labels.getString(status.toString()); tokenData.setStatus(statusData); - Collection<TokenStatus> nextStates = transitions.get(status); - if (nextStates != null) { - Collection<TokenStatusData> nextStatesData = new ArrayList<TokenStatusData>(); - for (TokenStatus nextState : nextStates) { - TokenStatusData nextStateData = new TokenStatusData(); - nextStateData.name = nextState; - nextStateData.label = labels.getString(status + "." + nextState); - nextStatesData.add(nextStateData); - } - tokenData.setNextStates(nextStatesData); + Collection<TokenStatus> nextStates = subsystem.getNextTokenStates(tokenRecord); + Collection<TokenStatusData> nextStatesData = new ArrayList<TokenStatusData>(); + for (TokenStatus nextState : nextStates) { + TokenStatusData nextStateData = new TokenStatusData(); + nextStateData.name = nextState; + nextStateData.label = labels.getString(status + "." + nextState); + nextStatesData.add(nextStateData); } + tokenData.setNextStates(nextStatesData); tokenData.setAppletID(tokenRecord.getAppletID()); tokenData.setKeyInfo(tokenRecord.getKeyInfo()); @@ -588,7 +515,7 @@ public class TokenService extends PKIService implements TokenResource { TokenDatabase database = subsystem.getTokenDatabase(); tokenRecord = database.getRecord(tokenID); - TokenStatus currentTokenStatus = getTokenStatus(tokenRecord); + TokenStatus currentTokenStatus = tokenRecord.getTokenStatus(); CMS.debug("TokenService.changeTokenStatus(): current status: " + currentTokenStatus); if (currentTokenStatus == tokenStatus) { @@ -601,9 +528,10 @@ public class TokenService extends PKIService implements TokenResource { msg = msg + " from " + currentTokenStatus + " to " + tokenStatus; // make sure transition is allowed - Collection<TokenStatus> nextStatuses = transitions.get(currentTokenStatus); + Collection<TokenStatus> nextStatuses = subsystem.getNextTokenStates(tokenRecord); CMS.debug("TokenService.changeTokenStatus(): allowed next statuses: " + nextStatuses); - if (nextStatuses == null || !nextStatuses.contains(tokenStatus)) { + + if (!nextStatuses.contains(tokenStatus)) { CMS.debug("TokenService.changeTokenStatus(): next status not allowed: " + tokenStatus); throw new BadRequestException("Invalid token status transition"); } |