Search in sources :

Example 51 with ACL

use of org.apache.zookeeper.data.ACL in project zookeeper by apache.

the class SetAclCommand method exec.

@Override
public boolean exec() throws CliException {
    String path = args[1];
    String aclStr = args[2];
    List<ACL> acl = AclParser.parse(aclStr);
    int version;
    if (cl.hasOption("v")) {
        version = Integer.parseInt(cl.getOptionValue("v"));
    } else {
        version = -1;
    }
    try {
        Stat stat = zk.setACL(path, acl, version);
        if (cl.hasOption("s")) {
            new StatPrinter(out).print(stat);
        }
    } catch (IllegalArgumentException ex) {
        throw new MalformedPathException(ex.getMessage());
    } catch (KeeperException | InterruptedException ex) {
        throw new CliWrapperException(ex);
    }
    return false;
}
Also used : Stat(org.apache.zookeeper.data.Stat) ACL(org.apache.zookeeper.data.ACL) KeeperException(org.apache.zookeeper.KeeperException)

Example 52 with ACL

use of org.apache.zookeeper.data.ACL in project zookeeper by apache.

the class PrepRequestProcessor method pRequest2Txn.

/**
 * This method will be called inside the ProcessRequestThread, which is a
 * singleton, so there will be a single thread calling this code.
 *
 * @param type
 * @param zxid
 * @param request
 * @param record
 */
protected void pRequest2Txn(int type, long zxid, Request request, Record record, boolean deserialize) throws KeeperException, IOException, RequestProcessorException {
    request.setHdr(new TxnHeader(request.sessionId, request.cxid, zxid, Time.currentWallTime(), type));
    switch(type) {
        case OpCode.create:
        case OpCode.create2:
        case OpCode.createTTL:
        case OpCode.createContainer:
            {
                pRequest2TxnCreate(type, request, record, deserialize);
                break;
            }
        case OpCode.deleteContainer:
            {
                String path = new String(request.request.array());
                String parentPath = getParentPathAndValidate(path);
                ChangeRecord parentRecord = getRecordForPath(parentPath);
                ChangeRecord nodeRecord = getRecordForPath(path);
                if (nodeRecord.childCount > 0) {
                    throw new KeeperException.NotEmptyException(path);
                }
                if (EphemeralType.get(nodeRecord.stat.getEphemeralOwner()) == EphemeralType.NORMAL) {
                    throw new KeeperException.BadVersionException(path);
                }
                request.setTxn(new DeleteTxn(path));
                parentRecord = parentRecord.duplicate(request.getHdr().getZxid());
                parentRecord.childCount--;
                addChangeRecord(parentRecord);
                addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path, null, -1, null));
                break;
            }
        case OpCode.delete:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            DeleteRequest deleteRequest = (DeleteRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, deleteRequest);
            String path = deleteRequest.getPath();
            String parentPath = getParentPathAndValidate(path);
            ChangeRecord parentRecord = getRecordForPath(parentPath);
            ChangeRecord nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, parentRecord.acl, ZooDefs.Perms.DELETE, request.authInfo, path, null);
            checkAndIncVersion(nodeRecord.stat.getVersion(), deleteRequest.getVersion(), path);
            if (nodeRecord.childCount > 0) {
                throw new KeeperException.NotEmptyException(path);
            }
            request.setTxn(new DeleteTxn(path));
            parentRecord = parentRecord.duplicate(request.getHdr().getZxid());
            parentRecord.childCount--;
            addChangeRecord(parentRecord);
            addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path, null, -1, null));
            break;
        case OpCode.setData:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            SetDataRequest setDataRequest = (SetDataRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, setDataRequest);
            path = setDataRequest.getPath();
            validatePath(path, request.sessionId);
            nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.WRITE, request.authInfo, path, null);
            int newVersion = checkAndIncVersion(nodeRecord.stat.getVersion(), setDataRequest.getVersion(), path);
            request.setTxn(new SetDataTxn(path, setDataRequest.getData(), newVersion));
            nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());
            nodeRecord.stat.setVersion(newVersion);
            addChangeRecord(nodeRecord);
            break;
        case OpCode.reconfig:
            if (!QuorumPeerConfig.isReconfigEnabled()) {
                LOG.error("Reconfig operation requested but reconfig feature is disabled.");
                throw new KeeperException.ReconfigDisabledException();
            }
            if (skipACL) {
                LOG.warn("skipACL is set, reconfig operation will skip ACL checks!");
            }
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            ReconfigRequest reconfigRequest = (ReconfigRequest) record;
            LeaderZooKeeperServer lzks;
            try {
                lzks = (LeaderZooKeeperServer) zks;
            } catch (ClassCastException e) {
                // standalone mode - reconfiguration currently not supported
                throw new KeeperException.UnimplementedException();
            }
            QuorumVerifier lastSeenQV = lzks.self.getLastSeenQuorumVerifier();
            // check that there's no reconfig in progress
            if (lastSeenQV.getVersion() != lzks.self.getQuorumVerifier().getVersion()) {
                throw new KeeperException.ReconfigInProgress();
            }
            long configId = reconfigRequest.getCurConfigId();
            if (configId != -1 && configId != lzks.self.getLastSeenQuorumVerifier().getVersion()) {
                String msg = "Reconfiguration from version " + configId + " failed -- last seen version is " + lzks.self.getLastSeenQuorumVerifier().getVersion();
                throw new KeeperException.BadVersionException(msg);
            }
            String newMembers = reconfigRequest.getNewMembers();
            if (newMembers != null) {
                // non-incremental membership change
                LOG.info("Non-incremental reconfig");
                // Input may be delimited by either commas or newlines so convert to common newline separated format
                newMembers = newMembers.replaceAll(",", "\n");
                try {
                    Properties props = new Properties();
                    props.load(new StringReader(newMembers));
                    request.qv = QuorumPeerConfig.parseDynamicConfig(props, lzks.self.getElectionType(), true, false);
                    request.qv.setVersion(request.getHdr().getZxid());
                } catch (IOException | ConfigException e) {
                    throw new KeeperException.BadArgumentsException(e.getMessage());
                }
            } else {
                // incremental change - must be a majority quorum system
                LOG.info("Incremental reconfig");
                List<String> joiningServers = null;
                String joiningServersString = reconfigRequest.getJoiningServers();
                if (joiningServersString != null) {
                    joiningServers = StringUtils.split(joiningServersString, ",");
                }
                List<String> leavingServers = null;
                String leavingServersString = reconfigRequest.getLeavingServers();
                if (leavingServersString != null) {
                    leavingServers = StringUtils.split(leavingServersString, ",");
                }
                if (!(lastSeenQV instanceof QuorumMaj)) {
                    String msg = "Incremental reconfiguration requested but last configuration seen has a non-majority quorum system";
                    LOG.warn(msg);
                    throw new KeeperException.BadArgumentsException(msg);
                }
                Map<Long, QuorumServer> nextServers = new HashMap<Long, QuorumServer>(lastSeenQV.getAllMembers());
                try {
                    if (leavingServers != null) {
                        for (String leaving : leavingServers) {
                            long sid = Long.parseLong(leaving);
                            nextServers.remove(sid);
                        }
                    }
                    if (joiningServers != null) {
                        for (String joiner : joiningServers) {
                            // joiner should have the following format: server.x = server_spec;client_spec
                            String[] parts = StringUtils.split(joiner, "=").toArray(new String[0]);
                            if (parts.length != 2) {
                                throw new KeeperException.BadArgumentsException("Wrong format of server string");
                            }
                            // extract server id x from first part of joiner: server.x
                            Long sid = Long.parseLong(parts[0].substring(parts[0].lastIndexOf('.') + 1));
                            QuorumServer qs = new QuorumServer(sid, parts[1]);
                            if (qs.clientAddr == null || qs.electionAddr == null || qs.addr == null) {
                                throw new KeeperException.BadArgumentsException("Wrong format of server string - each server should have 3 ports specified");
                            }
                            // check duplication of addresses and ports
                            for (QuorumServer nqs : nextServers.values()) {
                                if (qs.id == nqs.id) {
                                    continue;
                                }
                                qs.checkAddressDuplicate(nqs);
                            }
                            nextServers.remove(qs.id);
                            nextServers.put(qs.id, qs);
                        }
                    }
                } catch (ConfigException e) {
                    throw new KeeperException.BadArgumentsException("Reconfiguration failed");
                }
                request.qv = new QuorumMaj(nextServers);
                request.qv.setVersion(request.getHdr().getZxid());
            }
            if (QuorumPeerConfig.isStandaloneEnabled() && request.qv.getVotingMembers().size() < 2) {
                String msg = "Reconfig failed - new configuration must include at least 2 followers";
                LOG.warn(msg);
                throw new KeeperException.BadArgumentsException(msg);
            } else if (request.qv.getVotingMembers().size() < 1) {
                String msg = "Reconfig failed - new configuration must include at least 1 follower";
                LOG.warn(msg);
                throw new KeeperException.BadArgumentsException(msg);
            }
            if (!lzks.getLeader().isQuorumSynced(request.qv)) {
                String msg2 = "Reconfig failed - there must be a connected and synced quorum in new configuration";
                LOG.warn(msg2);
                throw new KeeperException.NewConfigNoQuorum();
            }
            nodeRecord = getRecordForPath(ZooDefs.CONFIG_NODE);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.WRITE, request.authInfo, null, null);
            request.setTxn(new SetDataTxn(ZooDefs.CONFIG_NODE, request.qv.toString().getBytes(), -1));
            nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());
            nodeRecord.stat.setVersion(-1);
            addChangeRecord(nodeRecord);
            break;
        case OpCode.setACL:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            SetACLRequest setAclRequest = (SetACLRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, setAclRequest);
            path = setAclRequest.getPath();
            validatePath(path, request.sessionId);
            List<ACL> listACL = fixupACL(path, request.authInfo, setAclRequest.getAcl());
            nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.ADMIN, request.authInfo, path, listACL);
            newVersion = checkAndIncVersion(nodeRecord.stat.getAversion(), setAclRequest.getVersion(), path);
            request.setTxn(new SetACLTxn(path, listACL, newVersion));
            nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());
            nodeRecord.stat.setAversion(newVersion);
            addChangeRecord(nodeRecord);
            break;
        case OpCode.createSession:
            request.request.rewind();
            int to = request.request.getInt();
            request.setTxn(new CreateSessionTxn(to));
            request.request.rewind();
            if (request.isLocalSession()) {
                // This will add to local session tracker if it is enabled
                zks.sessionTracker.addSession(request.sessionId, to);
            } else {
                // Explicitly add to global session if the flag is not set
                zks.sessionTracker.addGlobalSession(request.sessionId, to);
            }
            zks.setOwner(request.sessionId, request.getOwner());
            break;
        case OpCode.closeSession:
            // We don't want to do this check since the session expiration thread
            // queues up this operation without being the session owner.
            // this request is the last of the session so it should be ok
            // zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            Set<String> es = zks.getZKDatabase().getEphemerals(request.sessionId);
            synchronized (zks.outstandingChanges) {
                for (ChangeRecord c : zks.outstandingChanges) {
                    if (c.stat == null) {
                        // Doing a delete
                        es.remove(c.path);
                    } else if (c.stat.getEphemeralOwner() == request.sessionId) {
                        es.add(c.path);
                    }
                }
                for (String path2Delete : es) {
                    addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path2Delete, null, 0, null));
                }
                zks.sessionTracker.setSessionClosing(request.sessionId);
            }
            LOG.info("Processed session termination for sessionid: 0x" + Long.toHexString(request.sessionId));
            break;
        case OpCode.check:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            CheckVersionRequest checkVersionRequest = (CheckVersionRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, checkVersionRequest);
            path = checkVersionRequest.getPath();
            validatePath(path, request.sessionId);
            nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.READ, request.authInfo, path, null);
            request.setTxn(new CheckVersionTxn(path, checkAndIncVersion(nodeRecord.stat.getVersion(), checkVersionRequest.getVersion(), path)));
            break;
        default:
            LOG.warn("unknown type " + type);
            break;
    }
}
Also used : CheckVersionRequest(org.apache.zookeeper.proto.CheckVersionRequest) HashMap(java.util.HashMap) QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer) QuorumMaj(org.apache.zookeeper.server.quorum.flexible.QuorumMaj) ConfigException(org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException) Properties(java.util.Properties) ReconfigRequest(org.apache.zookeeper.proto.ReconfigRequest) DeleteTxn(org.apache.zookeeper.txn.DeleteTxn) CreateSessionTxn(org.apache.zookeeper.txn.CreateSessionTxn) BadArgumentsException(org.apache.zookeeper.KeeperException.BadArgumentsException) StringReader(java.io.StringReader) SetACLRequest(org.apache.zookeeper.proto.SetACLRequest) CheckVersionTxn(org.apache.zookeeper.txn.CheckVersionTxn) ACL(org.apache.zookeeper.data.ACL) SetDataRequest(org.apache.zookeeper.proto.SetDataRequest) SetDataTxn(org.apache.zookeeper.txn.SetDataTxn) IOException(java.io.IOException) QuorumVerifier(org.apache.zookeeper.server.quorum.flexible.QuorumVerifier) BadArgumentsException(org.apache.zookeeper.KeeperException.BadArgumentsException) SetACLTxn(org.apache.zookeeper.txn.SetACLTxn) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord) DeleteRequest(org.apache.zookeeper.proto.DeleteRequest) KeeperException(org.apache.zookeeper.KeeperException) TxnHeader(org.apache.zookeeper.txn.TxnHeader) LeaderZooKeeperServer(org.apache.zookeeper.server.quorum.LeaderZooKeeperServer)

Example 53 with ACL

use of org.apache.zookeeper.data.ACL in project zookeeper by apache.

the class PrepRequestProcessor method fixupACL.

/**
 * This method checks out the acl making sure it isn't null or empty,
 * it has valid schemes and ids, and expanding any relative ids that
 * depend on the requestor's authentication information.
 *
 * @param authInfo list of ACL IDs associated with the client connection
 * @param acls list of ACLs being assigned to the node (create or setACL operation)
 * @return verified and expanded ACLs
 * @throws KeeperException.InvalidACLException
 */
private List<ACL> fixupACL(String path, List<Id> authInfo, List<ACL> acls) throws KeeperException.InvalidACLException {
    // check for well formed ACLs
    // This resolves https://issues.apache.org/jira/browse/ZOOKEEPER-1877
    List<ACL> uniqacls = removeDuplicates(acls);
    List<ACL> rv = new LinkedList<ACL>();
    if (uniqacls == null || uniqacls.size() == 0) {
        throw new KeeperException.InvalidACLException(path);
    }
    for (ACL a : uniqacls) {
        LOG.debug("Processing ACL: {}", a);
        if (a == null) {
            throw new KeeperException.InvalidACLException(path);
        }
        Id id = a.getId();
        if (id == null || id.getScheme() == null) {
            throw new KeeperException.InvalidACLException(path);
        }
        if (id.getScheme().equals("world") && id.getId().equals("anyone")) {
            rv.add(a);
        } else if (id.getScheme().equals("auth")) {
            // This is the "auth" id, so we have to expand it to the
            // authenticated ids of the requestor
            boolean authIdValid = false;
            for (Id cid : authInfo) {
                ServerAuthenticationProvider ap = ProviderRegistry.getServerProvider(cid.getScheme());
                if (ap == null) {
                    LOG.error("Missing AuthenticationProvider for " + cid.getScheme());
                } else if (ap.isAuthenticated()) {
                    authIdValid = true;
                    rv.add(new ACL(a.getPerms(), cid));
                }
            }
            if (!authIdValid) {
                throw new KeeperException.InvalidACLException(path);
            }
        } else {
            ServerAuthenticationProvider ap = ProviderRegistry.getServerProvider(id.getScheme());
            if (ap == null || !ap.isValid(id.getId())) {
                throw new KeeperException.InvalidACLException(path);
            }
            rv.add(a);
        }
    }
    return rv;
}
Also used : ACL(org.apache.zookeeper.data.ACL) Id(org.apache.zookeeper.data.Id) ServerAuthenticationProvider(org.apache.zookeeper.server.auth.ServerAuthenticationProvider) LinkedList(java.util.LinkedList) KeeperException(org.apache.zookeeper.KeeperException)

Example 54 with ACL

use of org.apache.zookeeper.data.ACL in project zookeeper by apache.

the class PrepRequestProcessor method checkACL.

/**
 * Grant or deny authorization to an operation on a node as a function of:
 * @param zks :     the ZooKeeper server
 * @param cnxn :    the server connection
 * @param acl :     set of ACLs for the node
 * @param perm :    the permission that the client is requesting
 * @param ids :     the credentials supplied by the client
 * @param path :    the ZNode path
 * @param setAcls : for set ACL operations, the list of ACLs being set. Otherwise null.
 */
static void checkACL(ZooKeeperServer zks, ServerCnxn cnxn, List<ACL> acl, int perm, List<Id> ids, String path, List<ACL> setAcls) throws KeeperException.NoAuthException {
    if (skipACL) {
        return;
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("Permission requested: {} ", perm);
        LOG.debug("ACLs for node: {}", acl);
        LOG.debug("Client credentials: {}", ids);
    }
    if (acl == null || acl.size() == 0) {
        return;
    }
    for (Id authId : ids) {
        if (authId.getScheme().equals("super")) {
            return;
        }
    }
    for (ACL a : acl) {
        Id id = a.getId();
        if ((a.getPerms() & perm) != 0) {
            if (id.getScheme().equals("world") && id.getId().equals("anyone")) {
                return;
            }
            ServerAuthenticationProvider ap = ProviderRegistry.getServerProvider(id.getScheme());
            if (ap != null) {
                for (Id authId : ids) {
                    if (authId.getScheme().equals(id.getScheme()) && ap.matches(new ServerAuthenticationProvider.ServerObjs(zks, cnxn), new ServerAuthenticationProvider.MatchValues(path, authId.getId(), id.getId(), perm, setAcls))) {
                        return;
                    }
                }
            }
        }
    }
    throw new KeeperException.NoAuthException();
}
Also used : ACL(org.apache.zookeeper.data.ACL) Id(org.apache.zookeeper.data.Id) ServerAuthenticationProvider(org.apache.zookeeper.server.auth.ServerAuthenticationProvider)

Example 55 with ACL

use of org.apache.zookeeper.data.ACL in project zookeeper by apache.

the class ACLCountTest method testAclCount.

/**
 * Create a node and add 4 ACL values to it, but there are only 2 unique ACL values,
 * and each is repeated once:
 *
 *   ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE);
 *   ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS);
 *   ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE);
 *   ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS);
 *
 * Even though we've added 4 ACL values, there should only be 2 ACLs for that node,
 * since there are only 2 *unique* ACL values.
 */
@Test
public void testAclCount() throws Exception {
    File tmpDir = ClientBase.createTmpDir();
    ClientBase.setupTestEnv();
    ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
    SyncRequestProcessor.setSnapCount(1000);
    final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
    ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
    f.startup(zks);
    ZooKeeper zk;
    final ArrayList<ACL> CREATOR_ALL_AND_WORLD_READABLE = new ArrayList<ACL>() {

        {
            add(new ACL(ZooDefs.Perms.READ, ZooDefs.Ids.ANYONE_ID_UNSAFE));
            add(new ACL(ZooDefs.Perms.ALL, ZooDefs.Ids.AUTH_IDS));
            add(new ACL(ZooDefs.Perms.READ, ZooDefs.Ids.ANYONE_ID_UNSAFE));
            add(new ACL(ZooDefs.Perms.ALL, ZooDefs.Ids.AUTH_IDS));
        }
    };
    try {
        LOG.info("starting up the zookeeper server .. waiting");
        Assert.assertTrue("waiting for server being up", ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
        zk = ClientBase.createZKClient(HOSTPORT);
        zk.addAuthInfo("digest", "pat:test".getBytes());
        zk.setACL("/", Ids.CREATOR_ALL_ACL, -1);
        String path = "/path";
        try {
            Assert.assertEquals(4, CREATOR_ALL_AND_WORLD_READABLE.size());
        } catch (Exception e) {
            LOG.error("Something is fundamentally wrong with ArrayList's add() method. add()ing four times to an empty ArrayList should result in an ArrayList with 4 members.");
            throw e;
        }
        zk.create(path, path.getBytes(), CREATOR_ALL_AND_WORLD_READABLE, CreateMode.PERSISTENT);
        List<ACL> acls = zk.getACL("/path", new Stat());
        Assert.assertEquals(2, acls.size());
    } catch (Exception e) {
        // test failed somehow.
        Assert.assertTrue(false);
    }
    f.shutdown();
    zks.shutdown();
}
Also used : ZooKeeper(org.apache.zookeeper.ZooKeeper) Stat(org.apache.zookeeper.data.Stat) ArrayList(java.util.ArrayList) ServerCnxnFactory(org.apache.zookeeper.server.ServerCnxnFactory) ACL(org.apache.zookeeper.data.ACL) File(java.io.File) ZooKeeperServer(org.apache.zookeeper.server.ZooKeeperServer) Test(org.junit.Test)

Aggregations

ACL (org.apache.zookeeper.data.ACL)108 Id (org.apache.zookeeper.data.Id)43 Test (org.junit.Test)43 ArrayList (java.util.ArrayList)33 Stat (org.apache.zookeeper.data.Stat)19 KeeperException (org.apache.zookeeper.KeeperException)17 Configuration (org.apache.hadoop.conf.Configuration)10 ZooKeeper (org.apache.zookeeper.ZooKeeper)10 Test (org.testng.annotations.Test)9 CuratorFramework (org.apache.curator.framework.CuratorFramework)8 IOException (java.io.IOException)6 File (java.io.File)5 ACLProvider (org.apache.curator.framework.api.ACLProvider)5 TestableZooKeeper (org.apache.zookeeper.TestableZooKeeper)5 HashMap (java.util.HashMap)4 List (java.util.List)4 Map (java.util.Map)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3 HBaseConfiguration (org.apache.hadoop.hbase.HBaseConfiguration)3