Commit 30796089 authored by chiaming2000's avatar chiaming2000
Browse files

Added admin API to set ACL.

Added admin API to set erase pin.
Added admin API to set lock pin.

Changed set security implementation in the simulator such that security
operation can only be set one at a time (not enforced yet until tests
are updated to use new APIs) for the above components. 
parent 8418bbf7
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -707,4 +707,95 @@ public class DefaultAdminClient implements KineticAdminClient {
        
    }

    @Override
    public void setAcl(List<ACL> acls) throws KineticException {
        this.setSecurity(acls, null, null, null, null);
    }
    
    

    @Override
    public void setLockPin(byte[] oldLockPin, byte[] newLockPin)
            throws KineticException {

        KineticMessage km = MessageFactory.createKineticMessageWithBuilder();

        Command.Builder commandBuilder = (Command.Builder) km.getCommand();

        Security.Builder security = commandBuilder.getBodyBuilder()
                .getSecurityBuilder();

        // set old lock pin
        if (oldLockPin != null) {
            security.setOldLockPIN(ByteString.copyFrom(oldLockPin));
        }

        // set new lock pin
        if (newLockPin != null) {
            security.setNewLockPIN(ByteString.copyFrom(newLockPin));
        }

        KineticMessage response = configureSecurityPolicy(km);

        if (response.getCommand().getHeader().getMessageType() != MessageType.SECURITY_RESPONSE) {
            throw new KineticException("received wrong message type.");
        }

        if (response.getCommand().getStatus().getCode() == Status.StatusCode.NOT_AUTHORIZED) {

            throw new KineticException("Authorized Exception: "
                    + response.getCommand().getStatus().getCode() + ": "
                    + response.getCommand().getStatus().getStatusMessage());
        }

        if (response.getCommand().getStatus().getCode() != Status.StatusCode.SUCCESS) {
            throw new KineticException("Unknown Error: "
                    + response.getCommand().getStatus().getCode() + ": "
                    + response.getCommand().getStatus().getStatusMessage());
        }

    }

    @Override
    public void setErasePin(byte[] oldErasePin, byte[] newErasePin)
            throws KineticException {
        
        KineticMessage km = MessageFactory.createKineticMessageWithBuilder();

        Command.Builder commandBuilder = (Command.Builder) km.getCommand();

        Security.Builder security = commandBuilder.getBodyBuilder()
                .getSecurityBuilder();

        // set old erase pin
        if (oldErasePin != null) {
            security.setOldErasePIN (ByteString.copyFrom(oldErasePin));
        }
        
        // set new erase pin
        if (newErasePin != null) {
            security.setNewErasePIN (ByteString.copyFrom(newErasePin));
        }

        KineticMessage response = configureSecurityPolicy(km);

        if (response.getCommand().getHeader().getMessageType() != MessageType.SECURITY_RESPONSE) {
            throw new KineticException("received wrong message type.");
        }

        if (response.getCommand().getStatus().getCode() == Status.StatusCode.NOT_AUTHORIZED) {

            throw new KineticException("Authorized Exception: "
                    + response.getCommand().getStatus().getCode() + ": "
                    + response.getCommand().getStatus().getStatusMessage());
        }

        if (response.getCommand().getStatus().getCode() != Status.StatusCode.SUCCESS) {
            throw new KineticException("Unknown Error: "
                    + response.getCommand().getStatus().getCode() + ": "
                    + response.getCommand().getStatus().getStatusMessage());
        }
        
    }
    
}
+35 −4
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ public interface KineticAdminClient {
     * 
     * @throws KineticException
     *             if any internal error occurred.
     * 
     * @deprecated
     */
    public void setup(byte[] pin, byte[] setPin, long newClusterVersion,
            boolean secureErase) throws KineticException;
@@ -153,6 +153,8 @@ public interface KineticAdminClient {
    /**
     * Set the access control list to the Kinetic drive.  
     * <p>
     * This API only supports setting ACL or LOCK Pin or Erase PIn one at a time.
     * <p>
     * Lock Enable: Will be utilized to enable lock on power cycle. 
     * <p>
     * If the Client sets a non-empty value for the lock pin, device will be locked after a power cycle. 
@@ -172,9 +174,38 @@ public interface KineticAdminClient {
     * @see ACL
     * @see Domain
     * @see Role
     * 
     * @deprecated
     */
    public void setSecurity(List<ACL> acls, byte[] oldLockPin, byte[] newLockPin, byte[] oldErasePin, byte[] newErasePin) throws KineticException;

    /**
     * Set Security ACL list.
     * 
     * @param acls the ACL list to be set to drive/simulator.
     * 
     * @throws KineticException if any internal error occurred.
     */
    public void setAcl (List<ACL> acls) throws KineticException;
    
    /**
     * Set Security Lock pin.
     * 
     * @param oldLockPin old lock pin used to authenticate.
     * @param newLockPin the new lock pin to set to the kinetic drive/simulator.
     * 
     * @throws KineticException if any internal error occurred.
     */
    public void setLockPin (byte[] oldLockPin, byte[] newLockPin) throws KineticException;
    
    /**
     * 
     * @param oldErasePin old erase pin used to authenticate.
     * @param newErasePin new pin to set.
     * @throws KineticException if any internal error occurred.
     */
    public void setErasePin (byte[] oldErasePin, byte[] newErasePin) throws KineticException;
    
    /**
     * Erase all data in database for the drive.
     * <p>
+153 −56
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ public abstract class SecurityHandler {

    }

    public static synchronized Map<Long, ACL> handleSecurity(
    public static synchronized void handleSecurity(
            KineticMessage request, KineticMessage response,
            SimulatorEngine engine)
            throws KVStoreException, IOException {
@@ -99,17 +99,33 @@ public abstract class SecurityHandler {
        
        commandBuilder.getHeaderBuilder().setMessageType(MessageType.SECURITY_RESPONSE);
        
        List<ACL> aclList = request.getCommand().getBody().getSecurity()
        // check if only contains one security component change (ACL or ICE or Lock Pin)
        if (isSecurityMessageValid(request) == false) {
            
            logger.warning("security not enforced at this time, should not set ACL/ICE/LOCL at the same time ...");
          
//            commandBuilder.getStatusBuilder().setCode(
//                    StatusCode.INVALID_REQUEST);
//            commandBuilder
//                    .getStatusBuilder()
//                    .setStatusMessage(
//                            "contains more than one security component change (ACL or ICE or Lock Pin");
//            
//            return;
        }

        // get ACL list
        List<ACL> requestAclList = request.getCommand().getBody().getSecurity()
                .getAclList();

        // Validate input
        for (ACL acl : aclList) {
        for (ACL acl : requestAclList) {
            // add algorithm check
            if (!acl.hasHmacAlgorithm()
                    || !HMACAlgorithmUtil.isSupported(acl.getHmacAlgorithm())) {
                commandBuilder.getStatusBuilder().setCode(
                        StatusCode.NO_SUCH_HMAC_ALGORITHM);
                return engine.getAclMap();
                return;
            }

            for (ACL.Scope domain : acl.getScopeList()) {
@@ -119,7 +135,7 @@ public abstract class SecurityHandler {
                            StatusCode.INVALID_REQUEST);
                    commandBuilder.getStatusBuilder().setStatusMessage(
                            "Offset in domain is less than 0.");
                    return engine.getAclMap();
                    return;
                }

                List<Permission> roleOfList = domain.getPermissionList();
@@ -128,7 +144,7 @@ public abstract class SecurityHandler {
                            StatusCode.INVALID_REQUEST);
                    commandBuilder.getStatusBuilder().setStatusMessage(
                            "No role set in acl");
                    return engine.getAclMap();
                    return;
                }

                for (Permission role : roleOfList) {
@@ -138,14 +154,37 @@ public abstract class SecurityHandler {
                        commandBuilder.getStatusBuilder().setStatusMessage(
                                "Role is invalid in acl. Role is: "
                                        + role.toString());
                        return engine.getAclMap();
                        return;
                    }
                }
            }
        }
        
        // get request security
        Security security = request.getCommand().getBody().getSecurity(); 
        // construct new security builder to persist
        Security.Builder securityBuilder = Security.newBuilder();
        
        // request security
        Security requestSecurity = request.getCommand().getBody().getSecurity(); 
        
        // init pins
        initSecuirtyBuilderPins (securityBuilder, engine);
        
        // check if this is an ACL update
        if (requestAclList.isEmpty()) {
            // not an ACL update, add/preserve current acl list
            securityBuilder.addAllAcl(engine.getAclMap().values());
        } else {
            // this is an ACL update, add request ack list
            securityBuilder.addAllAcl(requestAclList);
            
            // update engine cache ACL list
            for (ACL acl : requestAclList) {
                engine.getAclMap().put(acl.getIdentity(), acl);
            }
        }
       
        // check if request has ICE pin
        if (requestSecurity.hasNewErasePIN()) {
            
         // get current erase pin
            ByteString currentErasePin = engine.getSecurityPin().getErasePin();
@@ -153,7 +192,7 @@ public abstract class SecurityHandler {
            // need to compare if we need the old pin
            if ((currentErasePin != null) && (currentErasePin.isEmpty() == false)) {
                // get old erase pin
            ByteString oldErasePin = security.getOldErasePIN();
                ByteString oldErasePin = requestSecurity.getOldErasePIN();
                
                // compare old with current
                if (currentErasePin.equals(oldErasePin) == false) {
@@ -162,17 +201,25 @@ public abstract class SecurityHandler {
                    commandBuilder.getStatusBuilder().setStatusMessage(
                            "Invalid old erase pin: " + oldErasePin);
                    
                return engine.getAclMap();
                    return;
                } 
            }
            
            // set to builder to be persisted
            securityBuilder.setNewErasePIN(requestSecurity.getNewErasePIN());
            
            // set ICE pin to cache
            engine.getSecurityPin().setErasePin(requestSecurity.getNewErasePIN());  
        } 
        
        if (requestSecurity.hasNewLockPIN()) {
         // get current lock pin
            ByteString currentLockPin = engine.getSecurityPin().getLockPin();
            
            // need to compare if we need the old pin
            if ((currentLockPin != null) && (currentLockPin.isEmpty() == false)) {
                // get old lock pin
            ByteString oldLockPin = security.getOldLockPIN();
                ByteString oldLockPin = requestSecurity.getOldLockPIN();
                
                // compare old with current
                if (currentLockPin.equals(oldLockPin) == false) {
@@ -181,27 +228,24 @@ public abstract class SecurityHandler {
                    commandBuilder.getStatusBuilder().setStatusMessage(
                            "Invalid old lock pin: " + oldLockPin);
                    
                return engine.getAclMap();
            } 
                    return;
                } 
  
        // update acl map
        for (ACL acl : aclList) {
            engine.getAclMap().put(acl.getIdentity(), acl);
            }
            
        // set erase pin
        engine.getSecurityPin().setErasePin(security.getNewErasePIN());
            // set new LOCK pin to builder to be persisted
            securityBuilder.setNewLockPIN (requestSecurity.getNewLockPIN());
            
        //set lock pin
        engine.getSecurityPin().setLockPin(security.getNewLockPIN());
            // set LOCK pin to cache
            engine.getSecurityPin().setLockPin(requestSecurity.getNewLockPIN());
        } 
        
        SecurityHandler.persistAcl(request.getCommand().getBody().getSecurity()
                .toByteArray(), engine.getKineticHome());
        // persist to acl file
        SecurityHandler.persistAcl(securityBuilder.build().toByteArray(), engine.getKineticHome());
        
        // set status code
        commandBuilder.getStatusBuilder().setCode(StatusCode.SUCCESS);

        return engine.getAclMap();
        return;
    }

    private static void persistAcl(byte[] contents, String kineticHome)
@@ -233,6 +277,8 @@ public abstract class SecurityHandler {
        
        Map<Long, ACL> aclmap = new HashMap<Long, ACL>();
        
        Security security = null;
        
        if (aclFile.exists()) {
            Long fileLength = aclFile.length();
            if (fileLength != 0) {
@@ -240,7 +286,7 @@ public abstract class SecurityHandler {
                FileInputStream in = new FileInputStream(aclFile);
                in.read(fileContent);
                in.close();
                Security security = Security.parseFrom(fileContent);
                security = Security.parseFrom(fileContent);
                List<ACL> aclList = security.getAclList();

                for (ACL acl : aclList) {
@@ -273,7 +319,6 @@ public abstract class SecurityHandler {
        
        // set default hmac key map
        engine.setHmacKeyMap(HmacStore.getHmacKeyMap(aclmap));
        
    }
    
    /**
@@ -320,4 +365,56 @@ public abstract class SecurityHandler {
        logger.info("reset security data to its factory defaults ...");
    }
    
    /**
     * Check if set Security contains only ACL, or ISE, or Lock pin change.
     * 
     *  Drive only support to change one at a time.
     * 
     * @param request
     * @return true if only one
     */
    private static boolean isSecurityMessageValid (KineticMessage request) {
        
        boolean isValid = false;
        
        int count = 0;
        
        // if acl has value
        if (request.getCommand().getBody().getSecurity().getAclCount() > 0) {
            count ++;
        }
        
        // if erase pin has value
        if (request.getCommand().getBody().getSecurity().hasNewErasePIN()) {
            count ++;
        }
        
        // if lock pin has value
        if (request.getCommand().getBody().getSecurity().hasNewLockPIN()) {
            count ++;
        }
        
        // we only allow to set one at a time
        if (count <= 1) {
            isValid = true;
        }
        
        return isValid;
    }
    
    private static void initSecuirtyBuilderPins (Security.Builder securityBuilder, SimulatorEngine engine) {
        
        //preserv current lock pin
        if (engine.getSecurityPin().getLockPin() != null) {
            securityBuilder.setOldLockPIN(engine.getSecurityPin().getLockPin());
            securityBuilder.setNewLockPIN(engine.getSecurityPin().getLockPin());
        }
        
        // preserv current ICE pin
        if (engine.getSecurityPin().getErasePin() != null) {
            securityBuilder.setOldErasePIN (engine.getSecurityPin().getErasePin());
            securityBuilder.setNewErasePIN(engine.getSecurityPin().getErasePin());
        }
    }
   
}
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.seagate.kinetic.proto.Kinetic.Command;
import com.seagate.kinetic.proto.Kinetic.Command.GetLog.Configuration;
import com.seagate.kinetic.proto.Kinetic.Command.GetLog.Limits;
import com.seagate.kinetic.proto.Kinetic.Command.PinOperation.PinOpType;

import com.seagate.kinetic.proto.Kinetic.Command.Status.StatusCode;
import com.seagate.kinetic.proto.Kinetic.Local;
import com.seagate.kinetic.proto.Kinetic.Message;
+9 −2
Original line number Diff line number Diff line
@@ -167,8 +167,15 @@ public class AdminApiUsage {
		// perform set security operation
		byte[] pin = "1234".getBytes();
		
		adminClient.setSecurity(aclList, null, pin, null, pin);
		System.out.println("Set the security info for client with all roles");
		//adminClient.setSecurity(aclList, null, pin, null, pin);
		adminClient.setAcl(aclList);
		
		// set erase pin
		adminClient.setErasePin(null, pin);
		
		adminClient.setLockPin(null, pin);
		
		System.out.println("Set the security ACL for client with all roles, erase pin, and lock pin.");

		// close admin client
		adminClient.close();