accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From e..@apache.org
Subject svn commit: r1489980 [2/2] - in /accumulo/branches/ACCUMULO-118: ./ assemble/ assemble/src/main/assemblies/ conf/examples/1GB/native-standalone/ conf/examples/1GB/standalone/ conf/examples/2GB/native-standalone/ conf/examples/2GB/standalone/ conf/examp...
Date Wed, 05 Jun 2013 17:36:21 GMT
Modified: accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java
URL: http://svn.apache.org/viewvc/accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java?rev=1489980&r1=1489979&r2=1489980&view=diff
==============================================================================
--- accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java (original)
+++ accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java Wed Jun  5 17:36:20 2013
@@ -16,30 +16,50 @@
  */
 package org.apache.accumulo.server.security;
 
-import java.util.Set;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
 
-import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.impl.Tables;
+import org.apache.accumulo.core.client.impl.Translator;
 import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
-import org.apache.accumulo.core.security.AuditLevel;
+import org.apache.accumulo.core.data.Column;
+import org.apache.accumulo.core.data.KeyExtent;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.thrift.IterInfo;
+import org.apache.accumulo.core.data.thrift.TColumn;
+import org.apache.accumulo.core.data.thrift.TKeyExtent;
+import org.apache.accumulo.core.data.thrift.TRange;
+import org.apache.accumulo.core.master.thrift.TableOperation;
 import org.apache.accumulo.core.security.Authorizations;
 import org.apache.accumulo.core.security.SystemPermission;
 import org.apache.accumulo.core.security.TablePermission;
 import org.apache.accumulo.core.security.thrift.TCredentials;
+import org.apache.accumulo.core.util.ByteBufferUtil;
+import org.apache.accumulo.server.client.HdfsZooInstance;
 import org.apache.accumulo.server.security.handler.Authenticator;
 import org.apache.accumulo.server.security.handler.Authorizor;
 import org.apache.accumulo.server.security.handler.PermissionHandler;
+import org.apache.hadoop.io.Text;
 import org.apache.log4j.Logger;
 
 /**
- * 
+ *
  */
 public class AuditedSecurityOperation extends SecurityOperation {
   
+  public static final Logger audit = Logger.getLogger(Constants.AUDITLOG);
+  
   public AuditedSecurityOperation(Authorizor author, Authenticator authent, PermissionHandler pm, String instanceId) {
     super(author, authent, pm, instanceId);
   }
   
-  public static final Logger log = Logger.getLogger(AuditedSecurityOperation.class);
+  public static synchronized SecurityOperation getInstance() {
+    String instanceId = HdfsZooInstance.getInstance().getInstanceID();
+    return getInstance(instanceId, false);
+  }
   
   public static synchronized SecurityOperation getInstance(String instanceId, boolean initialize) {
     if (instance == null) {
@@ -49,201 +69,326 @@ public class AuditedSecurityOperation ex
     return instance;
   }
   
+  private static String getTableName(String tableId) {
+    try {
+      return Tables.getTableName(HdfsZooInstance.getInstance(), tableId);
+    } catch (TableNotFoundException e) {
+      return "Unknown Table with ID " + tableId;
+    }
+  }
+  
+  public static StringBuilder getAuthString(List<ByteBuffer> authorizations) {
+    StringBuilder auths = new StringBuilder();
+    for (ByteBuffer bb : authorizations) {
+      auths.append(ByteBufferUtil.toString(bb)).append(",");
+    }
+    return auths;
+  }
+  
+  private static boolean shouldAudit(TCredentials credentials, String tableId) {
+    return !tableId.equals(Constants.METADATA_TABLE_ID) && shouldAudit(credentials);
+  }
+  
+  // Is INFO the right level to check? Do we even need that check?
+  private static boolean shouldAudit(TCredentials credentials) {
+    return !credentials.getPrincipal().equals(SecurityConstants.SYSTEM_PRINCIPAL);
+  }
+  
+  /*
+   * Three auditing methods try to capture the 4 states we might have here. audit is in response to a thrown exception, the operation failed (perhaps due to
+   * insufficient privs, or some other reason) audit(credentials, template, args) is a successful operation audit(credentials, permitted, template, args) is a
+   * privileges check that is either permitted or denied. We don't know if the operation went on to be successful or not at this point, we would have to go
+   * digging through loads of other code to find it.
+   */
   private void audit(TCredentials credentials, ThriftSecurityException ex, String template, Object... args) {
-    log.log(AuditLevel.AUDIT, "Error: authenticated operation failed: " + credentials.getPrincipal() + ": " + String.format(template, args));
+    audit.warn("operation: failed; user: " + credentials.getPrincipal() + "; " + String.format(template, args) + "; exception: " + ex.toString());
   }
   
   private void audit(TCredentials credentials, String template, Object... args) {
-    log.log(AuditLevel.AUDIT, "Using credentials " + credentials.getPrincipal() + ": " + String.format(template, args));
+    if (shouldAudit(credentials)) {
+      audit.info("operation: success; user: " + credentials.getPrincipal() + ": " + String.format(template, args));
+    }
   }
   
+  private void audit(TCredentials credentials, boolean permitted, String template, Object... args) {
+    if (shouldAudit(credentials)) {
+      String prefix = permitted ? "permitted" : "denied";
+      audit.info("operation: " + prefix + "; user: " + credentials.getPrincipal() + "; " + String.format(template, args));
+    }
+  }
+
+  public static final String CAN_SCAN_AUDIT_TEMPLATE = "action: scan; targetTable: %s; authorizations: %s; range: %s; columns: %s; iterators: %s; iteratorOptions: %s;";
+
+  @Override
+  public boolean canScan(TCredentials credentials, String tableId, TRange range, List<TColumn> columns, List<IterInfo> ssiList,
+      Map<String,Map<String,String>> ssio, List<ByteBuffer> authorizations) throws ThriftSecurityException {
+    if (shouldAudit(credentials, tableId)) {
+      Range convertedRange = new Range(range);
+      List<Column> convertedColumns = Translator.translate(columns, new Translator.TColumnTranslator());
+      String tableName = getTableName(tableId);
+      
+      try {
+        boolean canScan = super.canScan(credentials, tableId);
+        audit(credentials, canScan, CAN_SCAN_AUDIT_TEMPLATE, tableName, getAuthString(authorizations), convertedRange, convertedColumns, ssiList, ssio);
+        
+        return canScan;
+      } catch (ThriftSecurityException ex) {
+        audit(credentials, ex, CAN_SCAN_AUDIT_TEMPLATE, getAuthString(authorizations), tableId, convertedRange, convertedColumns, ssiList, ssio);
+        throw ex;
+      }
+    } else {
+      return super.canScan(credentials, tableId);
+    }
+  }
+  public static final String CAN_SCAN_BATCH_AUDIT_TEMPLATE = "action: scan; targetTable: %s; authorizations: %s; range: %s; columns: %s; iterators: %s; iteratorOptions: %s;";
+
   @Override
-  public boolean authenticateUser(TCredentials credentials, TCredentials toAuth) throws ThriftSecurityException {
+  public boolean canScan(TCredentials credentials, String tableId, Map<TKeyExtent,List<TRange>> tbatch, List<TColumn> tcolumns, List<IterInfo> ssiList,
+      Map<String,Map<String,String>> ssio, List<ByteBuffer> authorizations) throws ThriftSecurityException {
+    if (shouldAudit(credentials, tableId)) {
+      @SuppressWarnings({"unchecked", "rawtypes"})
+      Map<KeyExtent,List<Range>> convertedBatch = Translator.translate(tbatch, new Translator.TKeyExtentTranslator(), new Translator.ListTranslator(
+          new Translator.TRangeTranslator()));
+      List<Column> convertedColumns = Translator.translate(tcolumns, new Translator.TColumnTranslator());
+      String tableName = getTableName(tableId);
+      
+      try {
+        boolean canScan = super.canScan(credentials, tableId);
+        audit(credentials, canScan, CAN_SCAN_BATCH_AUDIT_TEMPLATE, tableName, getAuthString(authorizations), convertedBatch, convertedColumns, ssiList, ssio);
+        
+        return canScan;
+      } catch (ThriftSecurityException ex) {
+        audit(credentials, ex, CAN_SCAN_BATCH_AUDIT_TEMPLATE, getAuthString(authorizations), tableId, convertedBatch, convertedColumns, ssiList, ssio);
+        throw ex;
+      }
+    } else {
+      return super.canScan(credentials, tableId);
+    }
+  }
+  public static final String CHANGE_AUTHORIZATIONS_AUDIT_TEMPLATE = "action: changeAuthorizations; targetUser: %s; authorizations: %s";
+
+  @Override
+  public void changeAuthorizations(TCredentials credentials, String user, Authorizations authorizations) throws ThriftSecurityException {
     try {
-      boolean result = super.authenticateUser(credentials, toAuth);
-      audit(credentials, result ? "authenticated" : "failed authentication");
-      return result;
+      super.changeAuthorizations(credentials, user, authorizations);
+      audit(credentials, CHANGE_AUTHORIZATIONS_AUDIT_TEMPLATE, user, authorizations);
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "authenticateUser");
-      log.debug(ex);
+      audit(credentials, ex, CHANGE_AUTHORIZATIONS_AUDIT_TEMPLATE, user, authorizations);
       throw ex;
     }
   }
-  
+  public static final String CHANGE_PASSWORD_AUDIT_TEMPLATE = "action: changePassword; targetUser: %s;";
+
   @Override
-  public Authorizations getUserAuthorizations(TCredentials credentials, String user) throws ThriftSecurityException {
+  public void changePassword(TCredentials credentials, TCredentials newInfo) throws ThriftSecurityException {
     try {
-      Authorizations result = super.getUserAuthorizations(credentials, user);
-      audit(credentials, "got authorizations for %s", user);
-      return result;
+      super.changePassword(credentials, newInfo);
+      audit(credentials, CHANGE_PASSWORD_AUDIT_TEMPLATE, newInfo.getPrincipal());
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "getting authorizations for %s", user);
-      log.debug(ex);
+      audit(credentials, ex, CHANGE_PASSWORD_AUDIT_TEMPLATE, newInfo.getPrincipal());
       throw ex;
     }
-    
   }
-  
+  public static final String CREATE_USER_AUDIT_TEMPLATE = "action: createUser; targetUser: %s; Authorizations: %s;";
+
   @Override
-  public Authorizations getUserAuthorizations(TCredentials credentials) throws ThriftSecurityException {
+  public void createUser(TCredentials credentials, TCredentials newUser, Authorizations authorizations) throws ThriftSecurityException {
     try {
-      return getUserAuthorizations(credentials, credentials.getPrincipal());
+      super.createUser(credentials, newUser, authorizations);
+      audit(credentials, CREATE_USER_AUDIT_TEMPLATE, newUser.getPrincipal(), authorizations);
     } catch (ThriftSecurityException ex) {
-      log.debug(ex);
+      audit(credentials, ex, CREATE_USER_AUDIT_TEMPLATE, newUser.getPrincipal(), authorizations);
       throw ex;
     }
   }
-  
+  public static final String CAN_CREATE_TABLE_AUDIT_TEMPLATE = "action: createTable; targetTable: %s;";
+
   @Override
-  public void changeAuthorizations(TCredentials credentials, String user, Authorizations authorizations) throws ThriftSecurityException {
+  public boolean canCreateTable(TCredentials c, String tableName) throws ThriftSecurityException {
     try {
-      super.changeAuthorizations(credentials, user, authorizations);
-      audit(credentials, "changed authorizations for %s to %s", user, authorizations);
+      boolean result = super.canCreateTable(c);
+      audit(c, result, CAN_CREATE_TABLE_AUDIT_TEMPLATE, tableName);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "changing authorizations for %s", user);
-      log.debug(ex);
+      audit(c, ex, CAN_CREATE_TABLE_AUDIT_TEMPLATE, tableName);
       throw ex;
     }
   }
-  
+  public static final String CAN_DELETE_TABLE_AUDIT_TEMPLATE = "action: deleteTable; targetTable: %s;";
+
   @Override
-  public void changePassword(TCredentials credentials, TCredentials newInfo) throws ThriftSecurityException {
+  public boolean canDeleteTable(TCredentials c, String tableId) throws ThriftSecurityException {
+    String tableName = getTableName(tableId);
     try {
-      super.changePassword(credentials, newInfo);
-      audit(credentials, "changed password for %s", newInfo.getPrincipal());
+      boolean result = super.canDeleteTable(c, tableId);
+      audit(c, result, CAN_DELETE_TABLE_AUDIT_TEMPLATE, tableName, tableId);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "changing password for %s", newInfo.getPrincipal());
-      log.debug(ex);
+      audit(c, ex, CAN_DELETE_TABLE_AUDIT_TEMPLATE, tableName, tableId);
       throw ex;
     }
   }
-  
+  public static final String CAN_RENAME_TABLE_AUDIT_TEMPLATE = "action: renameTable; targetTable: %s; newTableName: %s;";
+
   @Override
-  public void createUser(TCredentials credentials, TCredentials newUser, Authorizations authorizations) throws ThriftSecurityException {
+  public boolean canRenameTable(TCredentials c, String tableId, String oldTableName, String newTableName) throws ThriftSecurityException {
     try {
-      super.createUser(credentials, newUser, authorizations);
-      audit(credentials, "createUser");
+      boolean result = super.canRenameTable(c, tableId, oldTableName, newTableName);
+      audit(c, result, CAN_RENAME_TABLE_AUDIT_TEMPLATE, oldTableName, newTableName);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "createUser %s", newUser.getPrincipal());
-      log.debug(ex);
+      audit(c, ex, CAN_RENAME_TABLE_AUDIT_TEMPLATE, oldTableName, newTableName);
       throw ex;
     }
   }
-  
+  public static final String CAN_CLONE_TABLE_AUDIT_TEMPLATE = "action: cloneTable; targetTable: %s; newTableName: %s";
+
   @Override
-  public void dropUser(TCredentials credentials, String user) throws ThriftSecurityException {
+  public boolean canCloneTable(TCredentials c, String tableId, String tableName) throws ThriftSecurityException {
+    String oldTableName = getTableName(tableId);
     try {
-      super.dropUser(credentials, user);
-      audit(credentials, "dropUser");
+      boolean result = super.canCloneTable(c, tableId, tableName);
+      audit(c, result, CAN_CLONE_TABLE_AUDIT_TEMPLATE, oldTableName, tableName);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "dropUser %s", user);
-      log.debug(ex);
+      audit(c, ex, CAN_CLONE_TABLE_AUDIT_TEMPLATE, oldTableName, tableName);
       throw ex;
     }
   }
-  
+  public static final String CAN_DELETE_RANGE_AUDIT_TEMPLATE = "action: deleteData; targetTable: %s; startRange: %s; endRange: %s;";
+
   @Override
-  public void grantSystemPermission(TCredentials credentials, String user, SystemPermission permission) throws ThriftSecurityException {
+  public boolean canDeleteRange(TCredentials c, String tableId, String tableName, Text startRow, Text endRow) throws ThriftSecurityException {
     try {
-      super.grantSystemPermission(credentials, user, permission);
-      audit(credentials, "granted permission %s for %s", permission, user);
+      boolean result = super.canDeleteRange(c, tableId, tableName, startRow, endRow);
+      audit(c, result, CAN_DELETE_RANGE_AUDIT_TEMPLATE, tableName, startRow.toString(), endRow.toString());
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "granting permission %s for %s", permission, user);
-      log.debug(ex);
+      audit(c, ex, CAN_DELETE_RANGE_AUDIT_TEMPLATE, tableName, startRow.toString(), endRow.toString());
       throw ex;
     }
   }
-  
+  public static final String CAN_BULK_IMPORT_AUDIT_TEMPLATE = "action: bulkImport; targetTable: %s; dataDir: %s; failDir: %s;";
+
   @Override
-  public void grantTablePermission(TCredentials credentials, String user, String table, TablePermission permission) throws ThriftSecurityException {
+  public boolean canBulkImport(TCredentials c, String tableId, String tableName, String dir, String failDir) throws ThriftSecurityException {
     try {
-      super.grantTablePermission(credentials, user, table, permission);
-      audit(credentials, "granted permission %s on table %s for %s", permission, table, user);
+      boolean result = super.canBulkImport(c, tableId);
+      audit(c, result, CAN_BULK_IMPORT_AUDIT_TEMPLATE, tableName, dir, failDir);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "granting permission %s on table for %s", permission, table, user);
-      log.debug(ex);
+      audit(c, ex, CAN_BULK_IMPORT_AUDIT_TEMPLATE, tableName, dir, failDir);
       throw ex;
     }
   }
-  
+  public static final String CAN_IMPORT_AUDIT_TEMPLATE = "action: import; targetTable: %s; dataDir: %s;";
+
   @Override
-  public void revokeSystemPermission(TCredentials credentials, String user, SystemPermission permission) throws ThriftSecurityException {
+  public boolean canImport(TCredentials credentials, String tableName, String importDir) throws ThriftSecurityException {
+    
     try {
-      super.revokeSystemPermission(credentials, user, permission);
-      audit(credentials, "revoked permission %s for %s", permission, user);
+      boolean result = super.canImport(credentials, tableName, importDir);
+      audit(credentials, result, CAN_IMPORT_AUDIT_TEMPLATE, tableName, importDir);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "revoking permission %s on %s", permission, user);
-      log.debug(ex);
+      audit(credentials, ex, CAN_IMPORT_AUDIT_TEMPLATE, tableName, importDir);
       throw ex;
     }
   }
-  
+  public static final String CAN_EXPORT_AUDIT_TEMPLATE = "action: export; targetTable: %s; dataDir: %s;";
+
   @Override
-  public void revokeTablePermission(TCredentials credentials, String user, String table, TablePermission permission) throws ThriftSecurityException {
+  public boolean canExport(TCredentials credentials, String tableId, String tableName, String exportDir) throws ThriftSecurityException {
+    
     try {
-      super.revokeTablePermission(credentials, user, table, permission);
-      audit(credentials, "revoked permission %s on table %s for %s", permission, table, user);
+      boolean result = super.canExport(credentials, tableId, tableName, exportDir);
+      audit(credentials, result, CAN_EXPORT_AUDIT_TEMPLATE, tableName, exportDir);
+      return result;
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "revoking permission %s on table for %s", permission, table, user);
-      log.debug(ex);
+      audit(credentials, ex, CAN_EXPORT_AUDIT_TEMPLATE, tableName, exportDir);
       throw ex;
     }
   }
-  
+  public static final String DROP_USER_AUDIT_TEMPLATE = "action: dropUser; targetUser: %s;";
+
   @Override
-  public boolean hasSystemPermission(TCredentials credentials, String user, SystemPermission permission) throws ThriftSecurityException {
+  public void dropUser(TCredentials credentials, String user) throws ThriftSecurityException {
     try {
-      boolean result = super.hasSystemPermission(credentials, user, permission);
-      audit(credentials, "checked permission %s on %s", permission, user);
-      return result;
+      super.dropUser(credentials, user);
+      audit(credentials, DROP_USER_AUDIT_TEMPLATE, user);
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "checking permission %s on %s", permission, user);
-      log.debug(ex);
+      audit(credentials, ex, DROP_USER_AUDIT_TEMPLATE, user);
       throw ex;
     }
   }
-  
+  public static final String GRANT_SYSTEM_PERMISSION_AUDIT_TEMPLATE = "action: grantSystemPermission; permission: %s; targetUser: %s;";
+
   @Override
-  public boolean hasTablePermission(TCredentials credentials, String user, String table, TablePermission permission) throws ThriftSecurityException {
+  public void grantSystemPermission(TCredentials credentials, String user, SystemPermission permission) throws ThriftSecurityException {
     try {
-      boolean result = super.hasTablePermission(credentials, user, table, permission);
-      audit(credentials, "checked permission %s on table %s for %s", permission, table, user);
-      return result;
+      super.grantSystemPermission(credentials, user, permission);
+      audit(credentials, GRANT_SYSTEM_PERMISSION_AUDIT_TEMPLATE, permission, user);
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "checking permission %s on %s", permission, user);
-      log.debug(ex);
+      audit(credentials, ex, GRANT_SYSTEM_PERMISSION_AUDIT_TEMPLATE, permission, user);
       throw ex;
     }
   }
-  
+  public static final String GRANT_TABLE_PERMISSION_AUDIT_TEMPLATE = "action: grantTablePermission; permission: %s; targetTable: %s; targetUser: %s;";
+
   @Override
-  public Set<String> listUsers(TCredentials credentials) throws ThriftSecurityException {
+  public void grantTablePermission(TCredentials credentials, String user, String tableId, TablePermission permission) throws ThriftSecurityException {
+    String tableName = getTableName(tableId);
     try {
-      Set<String> result = super.listUsers(credentials);
-      audit(credentials, "listUsers");
-      return result;
+      super.grantTablePermission(credentials, user, tableId, permission);
+      audit(credentials, GRANT_TABLE_PERMISSION_AUDIT_TEMPLATE, permission, tableName, user);
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "listUsers");
-      log.debug(ex);
+      audit(credentials, ex, GRANT_TABLE_PERMISSION_AUDIT_TEMPLATE, permission, tableName, user);
       throw ex;
     }
   }
-  
+  public static final String REVOKE_SYSTEM_PERMISSION_AUDIT_TEMPLATE = "action: revokeSystemPermission; permission: %s; targetUser: %s;";
+
   @Override
-  public void deleteTable(TCredentials credentials, String table) throws ThriftSecurityException {
+  public void revokeSystemPermission(TCredentials credentials, String user, SystemPermission permission) throws ThriftSecurityException {
+    
     try {
-      super.deleteTable(credentials, table);
-      audit(credentials, "deleted table %s", table);
+      super.revokeSystemPermission(credentials, user, permission);
+      audit(credentials, REVOKE_SYSTEM_PERMISSION_AUDIT_TEMPLATE, permission, user);
     } catch (ThriftSecurityException ex) {
-      audit(credentials, ex, "deleting table %s", table);
-      log.debug(ex);
+      audit(credentials, ex, REVOKE_SYSTEM_PERMISSION_AUDIT_TEMPLATE, permission, user);
       throw ex;
     }
   }
-  
+  public static final String REVOKE_TABLE_PERMISSION_AUDIT_TEMPLATE = "action: revokeTablePermission; permission: %s; targetTable: %s; targetUser: %s;";
+
   @Override
-  public void initializeSecurity(TCredentials credentials, String principal, byte[] token) throws AccumuloSecurityException, ThriftSecurityException {
-    super.initializeSecurity(credentials, principal, token);
-    log.info("Initialized root user with username: " + principal + " at the request of user " + credentials.getPrincipal());
+  public void revokeTablePermission(TCredentials credentials, String user, String tableId, TablePermission permission) throws ThriftSecurityException {
+    String tableName = getTableName(tableId);
+    try {
+      super.revokeTablePermission(credentials, user, tableId, permission);
+      audit(credentials, REVOKE_TABLE_PERMISSION_AUDIT_TEMPLATE, permission, tableName, user);
+    } catch (ThriftSecurityException ex) {
+      audit(credentials, ex, REVOKE_TABLE_PERMISSION_AUDIT_TEMPLATE, permission, tableName, user);
+      throw ex;
+    }
+  }
+  public static final String CAN_ONLINE_OFFLINE_TABLE_AUDIT_TEMPLATE = "action: %s; targetTable: %s;";
+
+  @Override
+  public boolean canOnlineOfflineTable(TCredentials credentials, String tableId, TableOperation op) throws ThriftSecurityException {
+    String tableName = getTableName(tableId);
+    String operation = null;
+    if (op == TableOperation.ONLINE)
+      operation = "onlineTable";
+    if (op == TableOperation.OFFLINE)
+      operation = "offlineTable";
+    try {
+      boolean result = super.canOnlineOfflineTable(credentials, tableId, op);
+      audit(credentials, result, CAN_ONLINE_OFFLINE_TABLE_AUDIT_TEMPLATE, operation, tableName, tableId);
+      return result;
+    } catch (ThriftSecurityException ex) {
+      audit(credentials, ex, CAN_ONLINE_OFFLINE_TABLE_AUDIT_TEMPLATE, operation, tableName, tableId);
+      throw ex;
+    }
   }
 }

Modified: accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java
URL: http://svn.apache.org/viewvc/accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java?rev=1489980&r1=1489979&r2=1489980&view=diff
==============================================================================
--- accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java (original)
+++ accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java Wed Jun  5 17:36:20 2013
@@ -16,6 +16,9 @@
  */
 package org.apache.accumulo.server.security;
 
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.accumulo.core.Constants;
@@ -26,6 +29,11 @@ import org.apache.accumulo.core.client.i
 import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.data.thrift.IterInfo;
+import org.apache.accumulo.core.data.thrift.TColumn;
+import org.apache.accumulo.core.data.thrift.TKeyExtent;
+import org.apache.accumulo.core.data.thrift.TRange;
+import org.apache.accumulo.core.master.thrift.TableOperation;
 import org.apache.accumulo.core.security.Authorizations;
 import org.apache.accumulo.core.security.CredentialHelper;
 import org.apache.accumulo.core.security.SystemPermission;
@@ -41,6 +49,7 @@ import org.apache.accumulo.server.securi
 import org.apache.accumulo.server.security.handler.ZKAuthorizor;
 import org.apache.accumulo.server.security.handler.ZKPermHandler;
 import org.apache.accumulo.server.zookeeper.ZooCache;
+import org.apache.hadoop.io.Text;
 import org.apache.log4j.Logger;
 
 /**
@@ -238,7 +247,7 @@ public class SecurityOperation {
    * 
    * @return true if a user exists and has permission; false otherwise
    */
-  private boolean hasTablePermission(String user, String table, TablePermission permission, boolean useCached) throws ThriftSecurityException {
+  protected boolean hasTablePermission(String user, String table, TablePermission permission, boolean useCached) throws ThriftSecurityException {
     if (user.equals(SecurityConstants.SYSTEM_PRINCIPAL))
       return true;
     
@@ -284,6 +293,14 @@ public class SecurityOperation {
     return hasTablePermission(credentials.getPrincipal(), table, TablePermission.READ, true);
   }
   
+  public boolean canScan(TCredentials credentials, String table, TRange range, List<TColumn> columns, List<IterInfo> ssiList, Map<String,Map<String,String>> ssio, List<ByteBuffer> authorizations) throws ThriftSecurityException {
+    return canScan(credentials, table);
+  }
+  
+  public boolean canScan(TCredentials credentials, String table, Map<TKeyExtent,List<TRange>> tbatch, List<TColumn> tcolumns, List<IterInfo> ssiList, Map<String,Map<String,String>> ssio, List<ByteBuffer> authorizations) throws ThriftSecurityException {
+    return canScan(credentials, table);
+  }
+  
   public boolean canWrite(TCredentials credentials, String table) throws ThriftSecurityException {
     authenticate(credentials);
     return hasTablePermission(credentials.getPrincipal(), table, TablePermission.WRITE, true);
@@ -316,18 +333,22 @@ public class SecurityOperation {
         || hasSystemPermission(c.getPrincipal(), SystemPermission.ALTER_TABLE, false);
   }
   
+  public boolean canCreateTable(TCredentials c, String tableName) throws ThriftSecurityException {
+    return canCreateTable(c);
+  }
+  
   public boolean canCreateTable(TCredentials c) throws ThriftSecurityException {
     authenticate(c);
     return hasSystemPermission(c.getPrincipal(), SystemPermission.CREATE_TABLE, false);
   }
   
-  public boolean canRenameTable(TCredentials c, String tableId) throws ThriftSecurityException {
+  public boolean canRenameTable(TCredentials c, String tableId, String oldTableName, String newTableName) throws ThriftSecurityException {
     authenticate(c);
     return hasSystemPermission(c.getPrincipal(), SystemPermission.ALTER_TABLE, false)
         || hasTablePermission(c.getPrincipal(), tableId, TablePermission.ALTER_TABLE, false);
   }
   
-  public boolean canCloneTable(TCredentials c, String tableId) throws ThriftSecurityException {
+  public boolean canCloneTable(TCredentials c, String tableId, String tableName) throws ThriftSecurityException {
     authenticate(c);
     return hasSystemPermission(c.getPrincipal(), SystemPermission.CREATE_TABLE, false)
         && hasTablePermission(c.getPrincipal(), tableId, TablePermission.READ, false);
@@ -339,7 +360,7 @@ public class SecurityOperation {
         || hasTablePermission(c.getPrincipal(), tableId, TablePermission.DROP_TABLE, false);
   }
   
-  public boolean canOnlineOfflineTable(TCredentials c, String tableId) throws ThriftSecurityException {
+  public boolean canOnlineOfflineTable(TCredentials c, String tableId, TableOperation op) throws ThriftSecurityException {
     authenticate(c);
     return hasSystemPermission(c.getPrincipal(), SystemPermission.SYSTEM, false) || hasSystemPermission(c.getPrincipal(), SystemPermission.ALTER_TABLE, false)
         || hasTablePermission(c.getPrincipal(), tableId, TablePermission.ALTER_TABLE, false);
@@ -351,11 +372,15 @@ public class SecurityOperation {
         || hasTablePermission(c.getPrincipal(), tableId, TablePermission.ALTER_TABLE, false);
   }
   
-  public boolean canDeleteRange(TCredentials c, String tableId) throws ThriftSecurityException {
+  public boolean canDeleteRange(TCredentials c, String tableId, String tableName, Text startRow, Text endRow) throws ThriftSecurityException {
     authenticate(c);
     return hasSystemPermission(c.getPrincipal(), SystemPermission.SYSTEM, false) || hasTablePermission(c.getPrincipal(), tableId, TablePermission.WRITE, false);
   }
   
+  public boolean canBulkImport(TCredentials c, String tableId, String tableName, String dir, String failDir) throws ThriftSecurityException {
+    return canBulkImport(c, tableId);
+  }
+  
   public boolean canBulkImport(TCredentials c, String tableId) throws ThriftSecurityException {
     authenticate(c);
     return hasTablePermission(c.getPrincipal(), tableId, TablePermission.BULK_IMPORT, false);
@@ -603,12 +628,12 @@ public class SecurityOperation {
     }
   }
   
-  public boolean canExport(TCredentials credentials, String tableId) throws ThriftSecurityException {
+  public boolean canExport(TCredentials credentials, String tableId, String tableName, String exportDir) throws ThriftSecurityException {
     authenticate(credentials);
     return hasTablePermission(credentials.getPrincipal(), tableId, TablePermission.READ, false);
   }
   
-  public boolean canImport(TCredentials credentials) throws ThriftSecurityException {
+  public boolean canImport(TCredentials credentials, String tableName, String importDir) throws ThriftSecurityException {
     authenticate(credentials);
     return hasSystemPermission(credentials.getPrincipal(), SystemPermission.CREATE_TABLE, false);
   }

Modified: accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/tabletserver/TabletServer.java
URL: http://svn.apache.org/viewvc/accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/tabletserver/TabletServer.java?rev=1489980&r1=1489979&r2=1489980&view=diff
==============================================================================
--- accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/tabletserver/TabletServer.java (original)
+++ accumulo/branches/ACCUMULO-118/server/src/main/java/org/apache/accumulo/server/tabletserver/TabletServer.java Wed Jun  5 17:36:20 2013
@@ -1096,7 +1096,7 @@ public class TabletServer extends Abstra
         throws NotServingTabletException, ThriftSecurityException, org.apache.accumulo.core.tabletserver.thrift.TooManyFilesException {
       
       Authorizations userauths = null;
-      if (!security.canScan(credentials, new String(textent.getTable())))
+      if (!security.canScan(credentials, new String(textent.getTable()), range, columns, ssiList, ssio, authorizations))
         throw new ThriftSecurityException(credentials.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
       
       userauths = security.getUserAuthorizations(credentials);
@@ -1253,7 +1253,7 @@ public class TabletServer extends Abstra
       // check if user has permission to the tables
       Authorizations userauths = null;
       for (String table : tables)
-        if (!security.canScan(credentials, table))
+        if (!security.canScan(credentials, table, tbatch, tcolumns, ssiList, ssio, authorizations))
           throw new ThriftSecurityException(credentials.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
       
       userauths = security.getUserAuthorizations(credentials);

Propchange: accumulo/branches/ACCUMULO-118/src/
------------------------------------------------------------------------------
  Merged /accumulo/trunk/src:r1489581-1489975

Added: accumulo/branches/ACCUMULO-118/test/src/test/java/org/apache/accumulo/test/AuditMessageTest.java
URL: http://svn.apache.org/viewvc/accumulo/branches/ACCUMULO-118/test/src/test/java/org/apache/accumulo/test/AuditMessageTest.java?rev=1489980&view=auto
==============================================================================
--- accumulo/branches/ACCUMULO-118/test/src/test/java/org/apache/accumulo/test/AuditMessageTest.java (added)
+++ accumulo/branches/ACCUMULO-118/test/src/test/java/org/apache/accumulo/test/AuditMessageTest.java Wed Jun  5 17:36:20 2013
@@ -0,0 +1,491 @@
+/*
+ * 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.accumulo.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.*;
+import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.security.Authorizations;
+import org.apache.accumulo.core.security.SystemPermission;
+import org.apache.accumulo.core.security.TablePermission;
+import org.apache.accumulo.minicluster.MiniAccumuloCluster;
+import org.apache.accumulo.server.security.AuditedSecurityOperation;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.hadoop.io.Text;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Tests that Accumulo is outputting audit messages as expected. Since this is using MiniAccumuloCluster, it could take a while if we test everything in
+ * isolation. We test blocks of related operations, run the whole test in one MiniAccumulo instance, trying to clean up objects between each test. The
+ * MiniAccumuloClusterTest sets up the log4j stuff differently to an installed instance, instead piping everything through stdout and writing to a set location
+ * so we have to find the logs and grep the bits we need out.
+ */
+public class AuditMessageTest {
+  
+  private static MiniAccumuloCluster accumulo;
+  private static File logDir;
+  private static List<MiniAccumuloCluster.LogWriter> logWriters;
+  private final String AUDIT_USER_1 = "AuditUser1";
+  private final String AUDIT_USER_2 = "AuditUser2";
+  private final PasswordToken PASSWORD_TOKEN = new PasswordToken("password");
+  private final String OLD_TEST_TABLE_NAME = "apples";
+  private final String NEW_TEST_TABLE_NAME = "oranges";
+  private final String THIRD_TEST_TABLE_NAME = "pears";
+  private final Authorizations auths = new Authorizations("private", "public");
+  private static TemporaryFolder folder = new TemporaryFolder();
+
+
+  // Must be static to survive Junit re-initialising the class every time.
+  private static String lastAuditTimestamp;
+  private Connector auditConnector;
+  private Connector conn;
+  
+  private static ArrayList<String> findAuditMessage(ArrayList<String> input, String pattern) {
+    ArrayList<String> result = new ArrayList<String>();
+    for (String s : input) {
+      if (s.matches(".*" + pattern + ".*"))
+        result.add(s);
+    }
+    return result;
+  }
+  
+  @BeforeClass
+  public static void setupMiniCluster() throws Exception {
+    folder.create();
+    Logger.getLogger("org.apache.zookeeper").setLevel(Level.ERROR);
+    
+    accumulo = new MiniAccumuloCluster(folder.getRoot(), "superSecret");
+    accumulo.start();
+    logDir = accumulo.getConfig().getLogDir();
+    logWriters = accumulo.getLogWriters();
+  }
+  
+
+  /**
+   * Returns a List of Audit messages that have been grep'd out of the MiniAccumuloCluster output.
+   * 
+   * @param stepName
+   *          A unique name for the test being executed, to identify the System.out messages.
+   * @return A List of the Audit messages, sorted (so in chronological order).
+   */
+  private ArrayList<String> getAuditMessages(String stepName) throws IOException {
+    
+    for (MiniAccumuloCluster.LogWriter lw : logWriters) {
+      lw.flush();
+    }
+    
+    // Grab the audit messages
+    System.out.println("Start of captured audit messages for step " + stepName);
+    
+    ArrayList<String> result = new ArrayList<String>();
+    for (File file : logDir.listFiles()) {
+      // We want to grab the files called .out
+      if (file.getName().contains(".out") && file.isFile() && file.canRead()) {
+        LineIterator it = FileUtils.lineIterator(file, "UTF-8");
+        try {
+          while (it.hasNext()) {
+            String line = it.nextLine();
+            if (line.matches(".* \\[" + Constants.AUDITLOG + "\\s*\\].*")) {
+              // Only include the message if startTimestamp is null. or the message occurred after the startTimestamp value
+              if ((lastAuditTimestamp == null) || (line.substring(0, 23).compareTo(lastAuditTimestamp) > 0))
+                result.add(line);
+            }
+          }
+        } finally {
+          LineIterator.closeQuietly(it);
+        }
+      }
+    }
+    Collections.sort(result);
+    
+    for (String s : result) {
+      System.out.println(s);
+    }
+    System.out.println("End of captured audit messages for step " + stepName);
+    if (result.size() > 0)
+      lastAuditTimestamp = (result.get(result.size() - 1)).substring(0, 23);
+    
+    return result;
+  }
+  
+  private void grantEverySystemPriv(Connector conn, String user) throws AccumuloSecurityException, AccumuloException {
+    SystemPermission[] arrayOfP = new SystemPermission[] {SystemPermission.SYSTEM, SystemPermission.ALTER_TABLE, SystemPermission.ALTER_USER,
+        SystemPermission.CREATE_TABLE, SystemPermission.CREATE_USER, SystemPermission.DROP_TABLE, SystemPermission.DROP_USER};
+    for (SystemPermission p : arrayOfP) {
+      conn.securityOperations().grantSystemPermission(user, p);
+    }
+  }
+  
+  @Before
+  public void setup() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, IOException {
+    conn = new ZooKeeperInstance(accumulo.getInstanceName(), accumulo.getZooKeepers()).getConnector("root", new PasswordToken("superSecret"));
+    
+    // I don't want to recreate the instance for every test since it will take ages.
+    // If we run every test as non-root users, I can drop these users every test which should effectively
+    // reset the environment.
+    
+    if (conn.securityOperations().listLocalUsers().contains(AUDIT_USER_1))
+      conn.securityOperations().dropLocalUser(AUDIT_USER_1);
+    if (conn.securityOperations().listLocalUsers().contains(AUDIT_USER_2))
+      conn.securityOperations().dropLocalUser(AUDIT_USER_2);
+    if (conn.securityOperations().listLocalUsers().contains(AUDIT_USER_2))
+      conn.securityOperations().dropLocalUser(THIRD_TEST_TABLE_NAME);
+    if (conn.tableOperations().exists(NEW_TEST_TABLE_NAME))
+      conn.tableOperations().delete(NEW_TEST_TABLE_NAME);
+    if (conn.tableOperations().exists(OLD_TEST_TABLE_NAME))
+      conn.tableOperations().delete(OLD_TEST_TABLE_NAME);
+    
+    // This will set the lastAuditTimestamp for the first test
+    getAuditMessages("setup");
+    
+  }
+  
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testTableOperationsAudits() throws AccumuloException, AccumuloSecurityException, TableExistsException, TableNotFoundException, IOException,
+      InterruptedException {
+    
+    conn.securityOperations().createLocalUser(AUDIT_USER_1, PASSWORD_TOKEN);
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_1, SystemPermission.SYSTEM);
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_1, SystemPermission.CREATE_TABLE);
+    
+    // Connect as Audit User and do a bunch of stuff.
+    // Testing activity begins here
+    auditConnector = new ZooKeeperInstance(accumulo.getInstanceName(), accumulo.getZooKeepers()).getConnector(AUDIT_USER_1, PASSWORD_TOKEN);
+    auditConnector.tableOperations().create(OLD_TEST_TABLE_NAME);
+    auditConnector.tableOperations().rename(OLD_TEST_TABLE_NAME, NEW_TEST_TABLE_NAME);
+    auditConnector.tableOperations().clone(NEW_TEST_TABLE_NAME, OLD_TEST_TABLE_NAME, true, Collections.EMPTY_MAP, Collections.EMPTY_SET);
+    auditConnector.tableOperations().delete(OLD_TEST_TABLE_NAME);
+    auditConnector.tableOperations().offline(NEW_TEST_TABLE_NAME);
+    auditConnector.tableOperations().delete(NEW_TEST_TABLE_NAME);
+    // Testing activity ends here
+    
+    ArrayList<String> auditMessages = getAuditMessages("testTableOperationsAudits");
+    
+    assertEquals(1, findAuditMessage(auditMessages, "action: createTable; targetTable: " + OLD_TEST_TABLE_NAME).size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: renameTable; targetTable: " + OLD_TEST_TABLE_NAME).size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: cloneTable; targetTable: " + NEW_TEST_TABLE_NAME).size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: deleteTable; targetTable: " + OLD_TEST_TABLE_NAME).size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: offlineTable; targetTable: " + NEW_TEST_TABLE_NAME).size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: deleteTable; targetTable: " + NEW_TEST_TABLE_NAME).size());
+    
+  }
+  
+  @Test
+  public void testUserOperationsAudits() throws AccumuloSecurityException, AccumuloException, TableExistsException, InterruptedException, IOException {
+    
+    conn.securityOperations().createLocalUser(AUDIT_USER_1, PASSWORD_TOKEN);
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_1, SystemPermission.SYSTEM);
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_1, SystemPermission.CREATE_USER);
+    grantEverySystemPriv(conn, AUDIT_USER_1);
+    
+    // Connect as Audit User and do a bunch of stuff.
+    // Start testing activities here
+    auditConnector = new ZooKeeperInstance(accumulo.getInstanceName(), accumulo.getZooKeepers()).getConnector(AUDIT_USER_1, PASSWORD_TOKEN);
+    auditConnector.securityOperations().createLocalUser(AUDIT_USER_2, PASSWORD_TOKEN);
+    
+    // It seems only root can grant stuff.
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_2, SystemPermission.ALTER_TABLE);
+    conn.securityOperations().revokeSystemPermission(AUDIT_USER_2, SystemPermission.ALTER_TABLE);
+    auditConnector.tableOperations().create(NEW_TEST_TABLE_NAME);
+    conn.securityOperations().grantTablePermission(AUDIT_USER_2, NEW_TEST_TABLE_NAME, TablePermission.READ);
+    conn.securityOperations().revokeTablePermission(AUDIT_USER_2, NEW_TEST_TABLE_NAME, TablePermission.READ);
+    auditConnector.securityOperations().changeLocalUserPassword(AUDIT_USER_2, new PasswordToken("anything"));
+    auditConnector.securityOperations().changeUserAuthorizations(AUDIT_USER_2, auths);
+    auditConnector.securityOperations().dropLocalUser(AUDIT_USER_2);
+    // Stop testing activities here
+    
+    ArrayList<String> auditMessages = getAuditMessages("testUserOperationsAudits");
+    
+    assertEquals(1, findAuditMessage(auditMessages, "action: createUser; targetUser: " + AUDIT_USER_2).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "action: grantSystemPermission; permission: " + SystemPermission.ALTER_TABLE.toString() + "; targetUser: " + AUDIT_USER_2).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "action: revokeSystemPermission; permission: " + SystemPermission.ALTER_TABLE.toString() + "; targetUser: " + AUDIT_USER_2).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "action: grantTablePermission; permission: " + TablePermission.READ.toString() + "; targetTable: " + NEW_TEST_TABLE_NAME).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "action: revokeTablePermission; permission: " + TablePermission.READ.toString() + "; targetTable: " + NEW_TEST_TABLE_NAME).size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: changePassword; targetUser: " + AUDIT_USER_2 + "").size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: changeAuthorizations; targetUser: " + AUDIT_USER_2 + "; authorizations: " + auths.toString())
+        .size());
+    assertEquals(1, findAuditMessage(auditMessages, "action: dropUser; targetUser: " + AUDIT_USER_2).size());
+  }
+  
+  @Test
+  public void testImportExportOperationsAudits() throws AccumuloSecurityException, AccumuloException, TableExistsException, TableNotFoundException,
+      IOException, InterruptedException {
+    
+    conn.securityOperations().createLocalUser(AUDIT_USER_1, PASSWORD_TOKEN);
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_1, SystemPermission.SYSTEM);
+    conn.securityOperations().changeUserAuthorizations(AUDIT_USER_1, auths);
+    grantEverySystemPriv(conn, AUDIT_USER_1);
+    
+    // Connect as Audit User and do a bunch of stuff.
+    // Start testing activities here
+    auditConnector = new ZooKeeperInstance(accumulo.getInstanceName(), accumulo.getZooKeepers()).getConnector(AUDIT_USER_1, PASSWORD_TOKEN);
+    auditConnector.tableOperations().create(OLD_TEST_TABLE_NAME);
+    
+    // Insert some play data
+    BatchWriter bw = auditConnector.createBatchWriter(OLD_TEST_TABLE_NAME, new BatchWriterConfig());
+    Mutation m = new Mutation("myRow");
+    m.put("cf1", "cq1", "v1");
+    m.put("cf1", "cq2", "v3");
+    bw.addMutation(m);
+    bw.close();
+    
+    // Prepare to export the table
+    File exportDir = new File(accumulo.getConfig().getDir().toString() + "/export");
+    
+    auditConnector.tableOperations().offline(OLD_TEST_TABLE_NAME);
+    auditConnector.tableOperations().exportTable(OLD_TEST_TABLE_NAME, exportDir.toString());
+    
+    // We've exported the table metadata to the MiniAccumuloCluster root dir. Grab the .rf file path to re-import it
+    File distCpTxt = new File(exportDir.toString() + "/distcp.txt");
+    File importFile = null;
+    LineIterator it = FileUtils.lineIterator(distCpTxt, "UTF-8");
+    
+    // Just grab the first rf file, it will do for now.
+    String filePrefix = "file:";
+    try {
+      while (it.hasNext() && importFile == null) {
+        String line = it.nextLine();
+        if (line.matches(".*\\.rf")) {
+          importFile = new File(line.replaceFirst(filePrefix, ""));
+        }
+      }
+    } finally {
+      LineIterator.closeQuietly(it);
+    }
+    FileUtils.copyFileToDirectory(importFile, exportDir);
+    auditConnector.tableOperations().importTable(NEW_TEST_TABLE_NAME, exportDir.toString());
+    
+    // Now do a Directory (bulk) import of the same data.
+    auditConnector.tableOperations().create(THIRD_TEST_TABLE_NAME);
+    File failDir = new File(exportDir + "/tmp");
+    failDir.mkdirs();
+    auditConnector.tableOperations().importDirectory(THIRD_TEST_TABLE_NAME, exportDir.toString(), failDir.toString(), false);
+    auditConnector.tableOperations().online(OLD_TEST_TABLE_NAME);
+    
+    // Stop testing activities here
+    
+    ArrayList<String> auditMessages = getAuditMessages("testImportExportOperationsAudits");
+    
+    assertEquals(1, findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_CREATE_TABLE_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME)).size());
+    assertEquals(1,
+        findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_ONLINE_OFFLINE_TABLE_AUDIT_TEMPLATE, "offlineTable", OLD_TEST_TABLE_NAME))
+            .size());
+    assertEquals(1,
+        findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_EXPORT_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME, exportDir.toString())).size());
+    assertEquals(1,
+        findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_IMPORT_AUDIT_TEMPLATE, NEW_TEST_TABLE_NAME, exportDir.toString())).size());
+    assertEquals(1, findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_CREATE_TABLE_AUDIT_TEMPLATE, THIRD_TEST_TABLE_NAME)).size());
+    assertEquals(
+        1,
+        findAuditMessage(
+            auditMessages,
+            String.format(AuditedSecurityOperation.CAN_BULK_IMPORT_AUDIT_TEMPLATE, THIRD_TEST_TABLE_NAME, filePrefix + exportDir.toString(), filePrefix
+                + failDir.toString())).size());
+    assertEquals(1,
+        findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_ONLINE_OFFLINE_TABLE_AUDIT_TEMPLATE, "onlineTable", OLD_TEST_TABLE_NAME))
+            .size());
+    
+  }
+  
+  @Test
+  public void testDataOperationsAudits() throws AccumuloSecurityException, AccumuloException, TableExistsException, TableNotFoundException, IOException,
+      InterruptedException {
+    
+    conn.securityOperations().createLocalUser(AUDIT_USER_1, PASSWORD_TOKEN);
+    conn.securityOperations().grantSystemPermission(AUDIT_USER_1, SystemPermission.SYSTEM);
+    conn.securityOperations().changeUserAuthorizations(AUDIT_USER_1, auths);
+    grantEverySystemPriv(conn, AUDIT_USER_1);
+    
+    // Connect as Audit User and do a bunch of stuff.
+    // Start testing activities here
+    auditConnector = new ZooKeeperInstance(accumulo.getInstanceName(), accumulo.getZooKeepers()).getConnector(AUDIT_USER_1, PASSWORD_TOKEN);
+    auditConnector.tableOperations().create(OLD_TEST_TABLE_NAME);
+    
+    // Insert some play data
+    BatchWriter bw = auditConnector.createBatchWriter(OLD_TEST_TABLE_NAME, new BatchWriterConfig());
+    Mutation m = new Mutation("myRow");
+    m.put("cf1", "cq1", "v1");
+    m.put("cf1", "cq2", "v3");
+    bw.addMutation(m);
+    bw.close();
+    
+    // Start testing activities here
+    // A regular scan
+    Scanner scanner = auditConnector.createScanner(OLD_TEST_TABLE_NAME, auths);
+    for (Map.Entry<Key,Value> entry : scanner) {
+      System.out.println("Scanner row: " + entry.getKey() + " " + entry.getValue());
+    }
+    scanner.close();
+    
+    // A batch scan
+    BatchScanner bs = auditConnector.createBatchScanner(OLD_TEST_TABLE_NAME, auths, 1);
+    bs.fetchColumn(new Text("cf1"), new Text("cq1"));
+    bs.setRanges(Arrays.asList(new Range("myRow", "myRow~")));
+    
+    for (Map.Entry<Key,Value> entry : bs) {
+      System.out.println("BatchScanner row: " + entry.getKey() + " " + entry.getValue());
+    }
+    bs.close();
+    
+    // Delete some data.
+    auditConnector.tableOperations().deleteRows(OLD_TEST_TABLE_NAME, new Text("myRow"), new Text("myRow~"));
+    
+    // End of testing activities
+    
+    ArrayList<String> auditMessages = getAuditMessages("testDataOperationsAudits");
+    assertTrue(1 <= findAuditMessage(auditMessages, "action: scan; targetTable: " + OLD_TEST_TABLE_NAME).size());
+    assertTrue(1 <= findAuditMessage(auditMessages, "action: scan; targetTable: " + OLD_TEST_TABLE_NAME).size());
+    assertEquals(1,
+        findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CAN_DELETE_RANGE_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME, "myRow", "myRow~")).size());
+    
+  }
+  
+  @Test
+  public void testDeniedAudits() throws AccumuloSecurityException, AccumuloException, TableExistsException, TableNotFoundException, IOException,
+      InterruptedException {
+    
+    // Create our user with no privs
+    conn.securityOperations().createLocalUser(AUDIT_USER_1, PASSWORD_TOKEN);
+    conn.tableOperations().create(OLD_TEST_TABLE_NAME);
+    auditConnector = new ZooKeeperInstance(accumulo.getInstanceName(), accumulo.getZooKeepers()).getConnector(AUDIT_USER_1, PASSWORD_TOKEN);
+    
+    // Start testing activities
+    // We should get denied or / failed audit messages here.
+    // We don't want the thrown exceptions to stop our tests, and we are not testing that the Exceptions are thrown.
+    
+    try {
+      auditConnector.tableOperations().create(NEW_TEST_TABLE_NAME);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      auditConnector.tableOperations().rename(OLD_TEST_TABLE_NAME, NEW_TEST_TABLE_NAME);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      auditConnector.tableOperations().clone(OLD_TEST_TABLE_NAME, NEW_TEST_TABLE_NAME, true, Collections.EMPTY_MAP, Collections.EMPTY_SET);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      auditConnector.tableOperations().delete(OLD_TEST_TABLE_NAME);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      auditConnector.tableOperations().offline(OLD_TEST_TABLE_NAME);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      Scanner scanner = auditConnector.createScanner(OLD_TEST_TABLE_NAME, auths);
+      scanner.iterator().next().getKey();
+    } catch (RuntimeException ex) {}
+    try {
+      auditConnector.tableOperations().deleteRows(OLD_TEST_TABLE_NAME, new Text("myRow"), new Text("myRow~"));
+    } catch (AccumuloSecurityException ex) {}
+    
+    // ... that will do for now.
+    // End of testing activities
+    
+    ArrayList<String> auditMessages = getAuditMessages("testDeniedAudits");
+    assertEquals(1,
+        findAuditMessage(auditMessages, "operation: denied;.*" + String.format(AuditedSecurityOperation.CAN_CREATE_TABLE_AUDIT_TEMPLATE, NEW_TEST_TABLE_NAME))
+            .size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "operation: denied;.*" + String.format(AuditedSecurityOperation.CAN_RENAME_TABLE_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME, NEW_TEST_TABLE_NAME)).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "operation: denied;.*" + String.format(AuditedSecurityOperation.CAN_CLONE_TABLE_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME, NEW_TEST_TABLE_NAME)).size());
+    assertEquals(1,
+        findAuditMessage(auditMessages, "operation: denied;.*" + String.format(AuditedSecurityOperation.CAN_DELETE_TABLE_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME))
+            .size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "operation: denied;.*" + String.format(AuditedSecurityOperation.CAN_ONLINE_OFFLINE_TABLE_AUDIT_TEMPLATE, "offlineTable", OLD_TEST_TABLE_NAME))
+            .size());
+    assertEquals(1, findAuditMessage(auditMessages, "operation: denied;.*" + "action: scan; targetTable: " + OLD_TEST_TABLE_NAME).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            "operation: denied;.*" + String.format(AuditedSecurityOperation.CAN_DELETE_RANGE_AUDIT_TEMPLATE, OLD_TEST_TABLE_NAME, "myRow", "myRow~")).size());
+  }
+  
+  @Test
+  public void testFailedAudits() throws AccumuloSecurityException, AccumuloException, TableExistsException, TableNotFoundException, IOException,
+      InterruptedException {
+    
+    // Start testing activities
+    // Test that we get a few "failed" audit messages come through when we tell it to do dumb stuff
+    // We don't want the thrown exceptions to stop our tests, and we are not testing that the Exceptions are thrown.
+    try {
+      conn.securityOperations().dropLocalUser(AUDIT_USER_2);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      conn.securityOperations().revokeSystemPermission(AUDIT_USER_2, SystemPermission.ALTER_TABLE);
+    } catch (AccumuloSecurityException ex) {}
+    try {
+      conn.securityOperations().createLocalUser("root", new PasswordToken("super secret"));
+    } catch (AccumuloSecurityException ex) {}
+    ArrayList<String> auditMessages = getAuditMessages("testFailedAudits");
+    // ... that will do for now.
+    // End of testing activities
+    
+    assertEquals(1, findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.DROP_USER_AUDIT_TEMPLATE, AUDIT_USER_2)).size());
+    assertEquals(
+        1,
+        findAuditMessage(auditMessages,
+            String.format(AuditedSecurityOperation.REVOKE_SYSTEM_PERMISSION_AUDIT_TEMPLATE, SystemPermission.ALTER_TABLE, AUDIT_USER_2)).size());
+    assertEquals(1, findAuditMessage(auditMessages, String.format(AuditedSecurityOperation.CREATE_USER_AUDIT_TEMPLATE, "root", "")).size());
+    
+  }
+
+  @AfterClass
+  public static void tearDownMiniCluster() throws Exception {
+    accumulo.stop();
+
+    // Comment this out to have a look at the logs, they will be in /tmp/junit*
+    folder.delete();
+  }
+}

Propchange: accumulo/branches/ACCUMULO-118/test/src/test/java/org/apache/accumulo/test/AuditMessageTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: accumulo/branches/ACCUMULO-118/test/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/accumulo/branches/ACCUMULO-118/test/src/test/resources/log4j.properties?rev=1489980&r1=1489979&r2=1489980&view=diff
==============================================================================
--- accumulo/branches/ACCUMULO-118/test/src/test/resources/log4j.properties (original)
+++ accumulo/branches/ACCUMULO-118/test/src/test/resources/log4j.properties Wed Jun  5 17:36:20 2013
@@ -16,7 +16,7 @@
 log4j.rootLogger=INFO, CA
 log4j.appender.CA=org.apache.log4j.ConsoleAppender
 log4j.appender.CA.layout=org.apache.log4j.PatternLayout
-log4j.appender.CA.layout.ConversionPattern=%d{ISO8601} [%-8c{2}] %-5p: %m%n
+log4j.appender.CA.layout.ConversionPattern=%d{ISO8601} [%c{2}] %-5p: %m%n
 
 log4j.logger.org.apache.accumulo.core.client.impl.ServerClient=ERROR
 log4j.logger.org.apache.accumulo.core.util.shell.Shell.audit=off



Mime
View raw message