Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
AuditingTest.java
Go to the documentation of this file.
1 // Copyright 2013 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import java.util.Set;
18 
19 import junit.framework.Assert;
20 
21 import org.junit.Test;
22 
31 import com.cloudera.impala.thrift.TAccessEvent;
32 import com.cloudera.impala.thrift.TCatalogObjectType;
33 import com.google.common.collect.Sets;
34 
39 public class AuditingTest extends AnalyzerTest {
40  @Test
42  // Simple select from a table.
43  Set<TAccessEvent> accessEvents =
44  AnalyzeAccessEvents("select * from functional.alltypesagg");
45  Assert.assertEquals(accessEvents, Sets.newHashSet(
46  new TAccessEvent("functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT")));
47 
48  // Select from a view. Expect to get 3 events back - one for the view and two
49  // for the underlying objects that the view accesses.
50  accessEvents = AnalyzeAccessEvents("select * from functional.view_view");
51  Assert.assertEquals(accessEvents, Sets.newHashSet(
52  new TAccessEvent("functional.view_view", TCatalogObjectType.VIEW, "SELECT"),
53  new TAccessEvent("functional.alltypes_view", TCatalogObjectType.VIEW, "SELECT"),
54  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "SELECT")
55  ));
56 
57  // Select from an inline-view.
58  accessEvents = AnalyzeAccessEvents(
59  "select a.* from (select * from functional.alltypesagg) a");
60  Assert.assertEquals(accessEvents, Sets.newHashSet(
61  new TAccessEvent("functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT")));
62 
63  // Select from collection table references.
64  accessEvents = AnalyzeAccessEvents(
65  "select item from functional.allcomplextypes.int_array_col");
66  Assert.assertEquals(accessEvents, Sets.newHashSet(
67  new TAccessEvent("functional.allcomplextypes",
68  TCatalogObjectType.TABLE, "SELECT")));
69  accessEvents = AnalyzeAccessEvents(
70  "select item from functional.allcomplextypes a, a.int_array_col");
71  Assert.assertEquals(accessEvents, Sets.newHashSet(
72  new TAccessEvent("functional.allcomplextypes",
73  TCatalogObjectType.TABLE, "SELECT")));
74  }
75 
76  @Test
78  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
79  "select * from functional.alltypes union all " +
80  "select * from functional_rc.alltypes");
81  Assert.assertEquals(accessEvents, Sets.newHashSet(
82  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "SELECT"),
83  new TAccessEvent("functional_rc.alltypes", TCatalogObjectType.TABLE, "SELECT")));
84  }
85 
86  @Test
88  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
89  "insert into functional.alltypes " +
90  "partition(month,year) select * from functional_rc.alltypes");
91  Assert.assertEquals(accessEvents, Sets.newHashSet(
92  new TAccessEvent("functional_rc.alltypes", TCatalogObjectType.TABLE, "SELECT"),
93  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "INSERT")));
94 
95  // Insert + inline-view.
96  accessEvents = AnalyzeAccessEvents(
97  "insert into functional.alltypes partition(month,year) " +
98  "select b.* from functional.alltypesagg a join (select * from " +
99  "functional_rc.alltypes) b on (a.int_col = b.int_col)");
100  Assert.assertEquals(accessEvents, Sets.newHashSet(
101  new TAccessEvent("functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT"),
102  new TAccessEvent("functional_rc.alltypes", TCatalogObjectType.TABLE, "SELECT"),
103  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "INSERT")));
104  }
105 
106  @Test
108  // With clause. No audit event should be recorded for the with-clause view.
109  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
110  "with t as (select * from functional.alltypesagg) select * from t");
111  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
112  "functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT")));
113 
114  // With clause view referencing a catalog view.
115  accessEvents = AnalyzeAccessEvents(
116  "with t as (select * from functional.alltypes_view) select * from t");
117  Assert.assertEquals(accessEvents, Sets.newHashSet(
118  new TAccessEvent(
119  "functional.alltypes_view", TCatalogObjectType.VIEW, "SELECT"),
120  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "SELECT")));
121 
122  accessEvents =
123  AnalyzeAccessEvents("with t as (select 1 + 2) select * from t");
124  Assert.assertEquals(0, accessEvents.size());
125 
126  // Even though the with-clause view isn't selected an access event is generated.
127  accessEvents = AnalyzeAccessEvents(
128  "with t as (select * from functional.alltypes) select 'abc'");
129  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
130  "functional.alltypes", TCatalogObjectType.TABLE, "SELECT")));
131  accessEvents = AnalyzeAccessEvents("with t as (select * from functional.alltypes) " +
132  "select * from functional_seq.alltypes");
133  Assert.assertEquals(accessEvents, Sets.newHashSet(
134  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "SELECT"),
135  new TAccessEvent(
136  "functional_seq.alltypes", TCatalogObjectType.TABLE, "SELECT")));
137  }
138 
139  @Test
141  Set<TAccessEvent> accessEvents =
142  AnalyzeAccessEvents("explain select * from functional.alltypesagg");
143  Assert.assertEquals(accessEvents, Sets.newHashSet(
144  new TAccessEvent("functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT")));
145  }
146 
147  @Test
149  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents("use functional");
150  Assert.assertEquals(accessEvents, Sets.newHashSet(
151  new TAccessEvent("functional", TCatalogObjectType.DATABASE, "ANY")));
152  }
153 
154  @Test
157  Set<TAccessEvent> accessEvents =
158  AnalyzeAccessEvents("invalidate metadata functional.alltypesagg");
159  // The user didn't actually access the table, no reason to set an access event.
160  Assert.assertEquals(0, accessEvents.size());
161  accessEvents = AnalyzeAccessEvents("refresh functional.alltypesagg");
162  Assert.assertEquals(0, accessEvents.size());
163  }
164 
165  @Test
167  Set<TAccessEvent> accessEvents =
168  AnalyzeAccessEvents("create table tpch.new_table (i int)");
169  Assert.assertEquals(accessEvents, Sets.newHashSet(
170  new TAccessEvent("tpch.new_table", TCatalogObjectType.TABLE, "CREATE")));
171 
172  accessEvents =
173  AnalyzeAccessEvents("create table tpch.new_lineitem like tpch.lineitem");
174 
175  Assert.assertEquals(accessEvents, Sets.newHashSet(
176  new TAccessEvent("tpch.lineitem", TCatalogObjectType.TABLE, "VIEW_METADATA"),
177  new TAccessEvent("tpch.new_lineitem", TCatalogObjectType.TABLE, "CREATE")));
178 
179  accessEvents = AnalyzeAccessEvents("create table tpch.new_table like parquet "
180  + "'/test-warehouse/schemas/zipcode_incomes.parquet'");
181  Assert.assertEquals(accessEvents, Sets.newHashSet(
182  new TAccessEvent("tpch.new_table", TCatalogObjectType.TABLE, "CREATE")));
183  }
184 
185  @Test
187  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
188  "create view tpch.new_view as select * from functional.alltypesagg");
189  Assert.assertEquals(accessEvents, Sets.newHashSet(
190  new TAccessEvent("functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT"),
191  new TAccessEvent("tpch.new_view", TCatalogObjectType.VIEW, "CREATE")));
192  }
193 
194  @Test
196  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents("create database newdb");
197  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
198  "newdb", TCatalogObjectType.DATABASE, "CREATE")));
199  }
200 
201  @Test
203  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents("drop database tpch");
204  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
205  "tpch", TCatalogObjectType.DATABASE, "DROP")));
206  }
207 
208  @Test
210  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents("drop table tpch.lineitem");
211  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
212  "tpch.lineitem", TCatalogObjectType.TABLE, "DROP")));
213  }
214 
215  @Test
217  Set<TAccessEvent> accessEvents =
218  AnalyzeAccessEvents("drop view functional_seq_snap.alltypes_view");
219  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
220  "functional_seq_snap.alltypes_view", TCatalogObjectType.VIEW, "DROP")));
221  }
222 
223  @Test
225  // User has permissions to modify tables.
226  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
227  "ALTER TABLE functional_seq_snap.alltypes ADD COLUMNS (c1 int)");
228  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
229  "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "ALTER")));
230 
231  accessEvents = AnalyzeAccessEvents(
232  "ALTER TABLE functional_seq_snap.alltypes RENAME TO functional_seq_snap.t1");
233  Assert.assertEquals(accessEvents, Sets.newHashSet(
234  new TAccessEvent(
235  "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "ALTER"),
236  new TAccessEvent("functional_seq_snap.t1", TCatalogObjectType.TABLE, "CREATE")));
237  }
238 
239  @Test
241  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
242  "ALTER VIEW functional_seq_snap.alltypes_view " +
243  "rename to functional_seq_snap.v1");
244  Assert.assertEquals(accessEvents, Sets.newHashSet(
245  new TAccessEvent(
246  "functional_seq_snap.alltypes_view", TCatalogObjectType.VIEW, "ALTER"),
247  new TAccessEvent("functional_seq_snap.v1", TCatalogObjectType.VIEW, "CREATE")));
248  }
249 
250  @Test
252  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
253  "COMPUTE STATS functional_seq_snap.alltypes");
254  Assert.assertEquals(accessEvents, Sets.newHashSet(
255  new TAccessEvent(
256  "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "ALTER")));
257  }
258 
259  @Test
261  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents(
262  "DROP STATS functional_seq_snap.alltypes");
263  Assert.assertEquals(accessEvents, Sets.newHashSet(
264  new TAccessEvent(
265  "functional_seq_snap.alltypes", TCatalogObjectType.TABLE, "ALTER")));
266  }
267 
268  @Test
270  Set<TAccessEvent> accessEvents =
271  AnalyzeAccessEvents("describe functional.alltypesagg");
272  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
273  "functional.alltypesagg", TCatalogObjectType.TABLE, "VIEW_METADATA")));
274 
275  accessEvents = AnalyzeAccessEvents("describe functional.complex_view");
276  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
277  "functional.complex_view", TCatalogObjectType.VIEW, "VIEW_METADATA")));
278  }
279 
280  @Test
282  String[] statsQuals = new String[]{ "partitions", "table stats", "column stats" };
283  for (String qual: statsQuals) {
284  Set<TAccessEvent> accessEvents =
285  AnalyzeAccessEvents(String.format("show %s functional.alltypes", qual));
286  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
287  "functional.alltypes", TCatalogObjectType.TABLE, "VIEW_METADATA")));
288  }
289  }
290 
291  @Test
293  Set<TAccessEvent> accessEvents =
294  AnalyzeAccessEvents("show create table functional.alltypesagg");
295  Assert.assertEquals(accessEvents, Sets.newHashSet(new TAccessEvent(
296  "functional.alltypesagg", TCatalogObjectType.TABLE, "VIEW_METADATA")));
297  }
298 
299  @Test
301  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents("load data inpath " +
302  "'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
303  "into table functional.alltypes partition(month=10, year=2009)");
304  Assert.assertEquals(accessEvents, Sets.newHashSet(
305  new TAccessEvent("functional.alltypes", TCatalogObjectType.TABLE, "INSERT")));
306  }
307 
308  @Test
311  // The policy file doesn't exist so all operations will result in
312  // an AuthorizationError
313  AuthorizationConfig config = AuthorizationConfig.createHadoopGroupAuthConfig(
314  "server1", "/does/not/exist", "");
315  ImpaladCatalog catalog = new ImpaladTestCatalog(config);
316  Frontend fe = new Frontend(config, catalog);
317  Analyzer analyzer = new Analyzer(catalog, TestUtils.createQueryContext(), config);
318 
319  // We should get an audit event even when an authorization failure occurs.
320  try {
321  ParseNode node = ParsesOk("create table foo_does_not_exist(i int)");
322  node.analyze(analyzer);
323  analyzer.authorize(fe.getAuthzChecker());
324  Assert.fail("Expected AuthorizationException");
325  } catch (AuthorizationException e) {
326  Assert.assertEquals(1, analyzer.getAccessEvents().size());
327  }
328  }
329 
330  @Test
332  // Test that triggering two identical audit events only emits one de-duplicated event
333  Set<TAccessEvent> accessEvents = AnalyzeAccessEvents("select count(1), max(1) from" +
334  " functional.alltypesagg a join functional.alltypesagg b on a.id = b.id");
335  Assert.assertEquals(accessEvents, Sets.newHashSet(
336  new TAccessEvent("_impala_builtins", TCatalogObjectType.DATABASE, "VIEW_METADATA"),
337  new TAccessEvent("functional.alltypesagg", TCatalogObjectType.TABLE, "SELECT")));
338  }
339 
344  private Set<TAccessEvent> AnalyzeAccessEvents(String stmt)
347  AnalyzesOk(stmt, analyzer);
348  return analyzer.getAccessEvents();
349  }
350 }
Analyzer createAnalyzer(String defaultDb)
uint64_t Test(T *ht, const ProbeTuple *input, uint64_t num_tuples)
Set< TAccessEvent > AnalyzeAccessEvents(String stmt)
static final String DEFAULT_DB
Definition: Catalog.java:58