public void visit()

in src/main/java/org/apache/accumulo/testing/randomwalk/security/TableOp.java [59:301]


  public void visit(State state, RandWalkEnv env, Properties props) throws Exception {
    String tablePrincipal = WalkingSecurity.get(state, env).getTabUserName();
    try (AccumuloClient client =
        env.createClient(tablePrincipal, WalkingSecurity.get(state, env).getTabToken())) {
      TableOperations tableOps = client.tableOperations();
      SecurityOperations secOps = client.securityOperations();

      String action = props.getProperty("action", "_random");
      TablePermission tp;
      if ("_random".equalsIgnoreCase(action)) {
        tp = TablePermission.values()[env.getRandom().nextInt(TablePermission.values().length)];
      } else {
        tp = TablePermission.valueOf(action);
      }

      boolean tableExists = WalkingSecurity.get(state, env).getTableExists();
      String tableName = WalkingSecurity.get(state, env).getTableName();

      switch (tp) {
        case READ: {
          boolean canRead;
          try {
            canRead = secOps.hasTablePermission(tablePrincipal, tableName, TablePermission.READ);
          } catch (AccumuloSecurityException ase) {
            if (tableExists)
              throw new AccumuloException("Table didn't exist when it should have: " + tableName,
                  ase);
            return;
          }
          Authorizations auths = secOps.getUserAuthorizations(tablePrincipal);
          boolean ambiguousZone =
              WalkingSecurity.get(state, env).inAmbiguousZone(client.whoami(), tp);
          boolean ambiguousAuths =
              WalkingSecurity.get(state, env).ambiguousAuthorizations(client.whoami());

          Scanner scan = null;
          try {
            scan = client.createScanner(tableName, secOps.getUserAuthorizations(client.whoami()));
            int seen = 0;
            Iterator<Entry<Key,Value>> iter = scan.iterator();
            while (iter.hasNext()) {
              Entry<Key,Value> entry = iter.next();
              Key k = entry.getKey();
              seen++;
              if (!auths.contains(k.getColumnVisibilityData()) && !ambiguousAuths)
                throw new AccumuloException(
                    "Got data I should not be capable of seeing: " + k + " table " + tableName);
            }
            if (!canRead && !ambiguousZone)
              throw new AccumuloException(
                  "Was able to read when I shouldn't have had the perm with connection user "
                      + client.whoami() + " table " + tableName);
            for (Entry<String,Integer> entry : WalkingSecurity.get(state, env).getAuthsMap()
                .entrySet()) {
              if (auths.contains(entry.getKey().getBytes(UTF_8)))
                seen = seen - entry.getValue();
            }
            if (seen != 0 && !ambiguousAuths)
              throw new AccumuloException("Got mismatched amounts of data");
          } catch (TableNotFoundException tnfe) {
            if (tableExists)
              throw new AccumuloException("Accumulo and test suite out of sync: table " + tableName,
                  tnfe);
            return;
          } catch (AccumuloSecurityException ae) {
            if (ae.getSecurityErrorCode().equals(SecurityErrorCode.PERMISSION_DENIED)) {
              if (canRead && !ambiguousZone)
                throw new AccumuloException(
                    "Table read permission out of sync with Accumulo: table " + tableName, ae);
              else
                return;
            }
            if (ae.getSecurityErrorCode().equals(SecurityErrorCode.BAD_AUTHORIZATIONS)) {
              if (ambiguousAuths)
                return;
              else
                throw new AccumuloException("Mismatched authorizations! ", ae);
            }
            throw new AccumuloException("Unexpected exception!", ae);
          } catch (RuntimeException re) {
            if (re.getCause() instanceof AccumuloSecurityException
                && ((AccumuloSecurityException) re.getCause()).getSecurityErrorCode()
                    .equals(SecurityErrorCode.PERMISSION_DENIED)) {
              if (canRead && !ambiguousZone)
                throw new AccumuloException(
                    "Table read permission out of sync with Accumulo: table " + tableName,
                    re.getCause());
              else
                return;
            }
            if (re.getCause() instanceof AccumuloSecurityException
                && ((AccumuloSecurityException) re.getCause()).getSecurityErrorCode()
                    .equals(SecurityErrorCode.BAD_AUTHORIZATIONS)) {
              if (ambiguousAuths)
                return;
              else
                throw new AccumuloException("Mismatched authorizations! ", re.getCause());
            }

            throw new AccumuloException("Unexpected exception!", re);
          } finally {
            if (scan != null) {
              scan.close();
              scan = null;
            }

          }

          break;
        }
        case WRITE:
          boolean canWrite;
          try {
            canWrite = secOps.hasTablePermission(tablePrincipal, tableName, TablePermission.WRITE);
          } catch (AccumuloSecurityException ase) {
            if (tableExists)
              throw new AccumuloException("Table didn't exist when it should have: " + tableName,
                  ase);
            return;
          }

          String key = WalkingSecurity.get(state, env).getLastKey() + "1";
          Mutation m = new Mutation(new Text(key));
          for (String s : WalkingSecurity.get(state, env).getAuthsArray()) {
            m.put(new Text(), new Text(), new ColumnVisibility(s),
                new Value("value".getBytes(UTF_8)));
          }
          BatchWriter writer = null;
          try {
            try {
              writer = client.createBatchWriter(tableName,
                  new BatchWriterConfig().setMaxMemory(9000l).setMaxWriteThreads(1));
            } catch (TableNotFoundException tnfe) {
              if (tableExists)
                throw new AccumuloException("Table didn't exist when it should have: " + tableName);
              return;
            }
            boolean works = true;
            try {
              writer.addMutation(m);
              writer.close();
            } catch (MutationsRejectedException mre) {
              if (mre.getSecurityErrorCodes().size() == 1) {
                // TabletServerBatchWriter will log the error automatically so make sure its the
                // error we expect
                SecurityErrorCode errorCode = mre.getSecurityErrorCodes().entrySet().iterator()
                    .next().getValue().iterator().next();
                if (errorCode.equals(SecurityErrorCode.PERMISSION_DENIED) && !canWrite) {
                  log.info("Caught MutationsRejectedException({}) in TableOp.WRITE as expected.",
                      errorCode);
                  return;
                }
              }
              throw new AccumuloException("Unexpected MutationsRejectedException in TableOp.WRITE",
                  mre);
            }
            if (works)
              for (String s : WalkingSecurity.get(state, env).getAuthsArray())
                WalkingSecurity.get(state, env).increaseAuthMap(s, 1);
          } finally {
            if (writer != null) {
              writer.close();
              writer = null;
            }
          }
          break;
        case BULK_IMPORT:
          key = WalkingSecurity.get(state, env).getLastKey() + "1";
          SortedSet<Key> keys = new TreeSet<>();
          for (String s : WalkingSecurity.get(state, env).getAuthsArray()) {
            Key k = new Key(key, "", "", s);
            keys.add(k);
          }
          Path dir = new Path("/tmp", "bulk_" + UUID.randomUUID().toString());
          Path fail = new Path(dir.toString() + "_fail");
          FileSystem fs = WalkingSecurity.get(state, env).getFs();
          RFileWriter rFileWriter =
              RFile.newWriter().to(dir + "/securityBulk.rf").withFileSystem(fs).build();
          rFileWriter.startDefaultLocalityGroup();
          fs.mkdirs(fail);
          for (Key k : keys)
            rFileWriter.append(k, new Value("Value".getBytes(UTF_8)));
          rFileWriter.close();
          try {
            tableOps.importDirectory(dir.toString()).to(tableName).tableTime(true).load();
          } catch (TableNotFoundException tnfe) {
            if (tableExists)
              throw new AccumuloException("Table didn't exist when it should have: " + tableName);
            return;
          } catch (AccumuloSecurityException ae) {
            if (ae.getSecurityErrorCode().equals(SecurityErrorCode.PERMISSION_DENIED)) {
              if (secOps.hasTablePermission(tablePrincipal, tableName, TablePermission.BULK_IMPORT))
                throw new AccumuloException(
                    "Bulk Import failed when it should have worked: " + tableName);
              return;
            } else if (ae.getSecurityErrorCode().equals(SecurityErrorCode.BAD_CREDENTIALS)) {
              if (WalkingSecurity.get(state, env).userPassTransient(client.whoami()))
                return;
            }
            throw new AccumuloException("Unexpected exception!", ae);
          }
          for (String s : WalkingSecurity.get(state, env).getAuthsArray())
            WalkingSecurity.get(state, env).increaseAuthMap(s, 1);
          fs.delete(dir, true);
          fs.delete(fail, true);

          if (!secOps.hasTablePermission(tablePrincipal, tableName, TablePermission.BULK_IMPORT))
            throw new AccumuloException(
                "Bulk Import succeeded when it should have failed: " + dir + " table " + tableName);
          break;
        case ALTER_TABLE:
          boolean tablePerm;
          try {
            tablePerm =
                secOps.hasTablePermission(tablePrincipal, tableName, TablePermission.ALTER_TABLE);
          } catch (AccumuloSecurityException ase) {
            if (tableExists)
              throw new AccumuloException("Table didn't exist when it should have: " + tableName,
                  ase);
            return;
          }
          AlterTable.renameTable(client, state, env, tableName, tableName + "plus", tablePerm,
              tableExists);
          break;

        case GRANT:
          props.setProperty("task", "grant");
          props.setProperty("perm", "random");
          props.setProperty("source", "table");
          props.setProperty("target", "system");
          AlterTablePerm.alter(state, env, props);
          break;

        case DROP_TABLE:
          props.setProperty("source", "table");
          DropTable.dropTable(state, env, props);
          break;

        case GET_SUMMARIES:
          throw new UnsupportedOperationException("GET_SUMMARIES not implemented");
      }
    }
  }