public void SecureDatabase_JoinQuerySecurity() { SecureDatabase db = BuildSampleDB(); SecureSampleDB(db); JoinQuery <SelectResult> q = new JoinQuery <SelectResult>(db, new SelectQuery() { TableName = sampleTableName, Columns = new string[] { "*" } }, new SelectQuery[] { new SelectQuery() { TableName = sampleTableName, Where = QueryParser.Parse("One") }, new SelectQuery() { TableName = sampleTableName, Where = QueryParser.Parse("SecretOwner=Bob") } }); SelectResult result; // Run a JOIN with full access - verify success (inner query expanded). q.Where = QueryParser.Parse("SecretPriority = 1 AND SecretOwner = #Q2[SecretOwner]"); result = db.Query(q, (si) => si.Name == "g1" || si.Name == "g2"); Assert.IsTrue(result.Details.Succeeded); Assert.AreEqual("[SecretPriority] = 1 AND [SecretOwner] = IN(Bob, Bob, Bob)", result.Query.Where.ToString()); // Run a JOIN with a disallowed clause on the top query - verify error q.Where = QueryParser.Parse("SecretPriority = 1 AND SecretOwner = #Q1[SecretOwner]"); result = db.Query(q, (si) => si.Name == "g2"); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual("", result.Query.Where.ToString()); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretOwner"), result.Details.Errors); // Run a JOIN where the join column in the outer query is disallowed - verify error q.Where = QueryParser.Parse("ID > 1 AND SecretOwner = #Q1[ID]"); result = db.Query(q, (si) => false); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual("", result.Query.Where.ToString()); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretOwner"), result.Details.Errors); // Run a JOIN where an inner query uses a disallowed clause - verify error q.Where = QueryParser.Parse("ID > 1 AND ID = #Q2[ID]"); result = db.Query(q, (si) => false); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual("", result.Query.Where.ToString()); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretOwner"), result.Details.Errors); // Run a JOIN where no secured columns are accessed - verify success (inner query expanded) q.Where = QueryParser.Parse("ID > 1 AND ID = #Q1[ID]"); result = db.Query(q, (si) => false); Assert.IsTrue(result.Details.Succeeded); Assert.AreEqual("[ID] > 1 AND [ID] = IN(1)", result.Query.Where.ToString()); }
public void SecureDatabase_CustomQuerySecurity() { // NOTE: Where clause security can be implemented for all queries, but // column security is custom per query types. If columns are restricted // and the query is an unknown type, it's always blocked. SecureDatabase db = BuildSampleDB(); CustomQuery c = new Model.SecureDatabaseTests.CustomQuery(); c.Columns = new string[] { "ID" }; c.TableName = sampleTableName; c.Where = QueryParser.Parse("One"); SelectResult result; // Run the Query without security. Expect no restrictions and no security checks. result = db.Query(c, (si) => true); Assert.IsTrue(result.Details.Succeeded); // Restrict the secret columns to people in "G1", or users in "G2" can see everything but only for SecretPriority < 1 items. SecureSampleDB(db); // Run the Query when the user has permission to everything. Verify success. result = db.Query(c, (si) => si.Name == "g1" || si.Name == "g2"); Assert.IsTrue(result.Details.Succeeded); // Run the Query when the user has a row restriction. Verify success with row restrictor. result = db.Query(c, (si) => si.Name == "g3"); Assert.IsTrue(result.Details.Succeeded); Assert.AreEqual("[SecretPriority] > 1 AND [*]:One", result.Query.Where.ToString()); // Run the Query when the user has a column restriction. Verify error. result = db.Query(c, (si) => false); Assert.IsFalse(result.Details.Succeeded); Assert.IsTrue(result.Details.Errors.Contains(String.Format(ExecutionDetails.DisallowedQuery, "CustomQuery"))); }
public void SecureDatabase_SelectQuerySecurity() { SecureDatabase db = BuildSampleDB(); SelectQuery q = new SelectQuery() { TableName = sampleTableName, Columns = new string[] { "*" }, Where = QueryParser.Parse("One") }; SelectResult result; // Verify default 'Query' method throws (must pass method which can report user group memberships) Verify.Exception <ArribaException>(() => db.Query(new SelectQuery(q))); // Run the Query without security. Expect no restrictions and no security checks. result = db.Query(new SelectQuery(q), (si) => { Assert.Fail("No security checks for unsecured table"); return(true); }); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, SecretOwner, SecretPriority, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Restrict the secret columns to people in "G1", or users in "G2" can see everything but only for SecretPriority < 1 items. SecureSampleDB(db); // Run the Query as a user in all column restriction groups // Verify the query is unrestricted - no WHERE clause and no filtered columns result = db.Query(new SelectQuery(q), (si) => si.Name == "g1" || si.Name == "g2"); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, SecretOwner, SecretPriority, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Run the query as a user in G1 only; verify G2 restricted columns excluded result = db.Query(new SelectQuery(q), (si) => si.Name == "g1"); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsTrue(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, SecretOwner, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Run the Query as a user in G3. // Verify WHERE clause restriction, but no column restrictions // Security design is EITHER row or column security. result = db.Query(new SelectQuery(q), (si) => si.Name == "g3"); Assert.AreEqual("[SecretPriority] > 1 AND [*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, SecretOwner, SecretPriority, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Run the Query as a user in G4. // Verify WHERE clause restriction, but no column restrictions // Security design is EITHER row or column security. result = db.Query(new SelectQuery(q), (si) => si.Name == "g4"); Assert.AreEqual("[SecretPriority] > 2 AND [*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, SecretOwner, SecretPriority, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Run the Query as a user in all groups // Verify WHERE clause restriction for *first* matching group, no column restrictions result = db.Query(new SelectQuery(q), (si) => true); Assert.AreEqual("[SecretPriority] > 1 AND [*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, SecretOwner, SecretPriority, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Run the Query as a user in no groups. // Verify all column restrictions, no where clause filter result = db.Query(new SelectQuery(q), (si) => false); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsTrue(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("ID, Priority, Title", String.Join(", ", ((SelectQuery)result.Query).Columns)); // Add a query clause for a restricted column when not in the required group. Verify error. result = db.Query(new SelectQuery(q) { Where = QueryParser.Parse("One AND SecretOwner=Bob") }, (si) => false); Assert.AreEqual("", result.Query.Where.ToString()); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretOwner"), result.Details.Errors); // Add a query clause for a restricted column when in the required group. Verify success. result = db.Query(new SelectQuery(q) { Where = QueryParser.Parse("One AND SecretOwner=Bob") }, (si) => si.Name == "g1"); Assert.AreEqual("[*]:One AND [SecretOwner] = Bob", result.Query.Where.ToString()); Assert.IsTrue(HasRestrictedClauses(result.Query.Where)); // Ask for restricted columns in result listing. Verify restricted columns allowed only for my group, warning for removed column. result = db.Query(new SelectQuery(q) { Columns = new string[] { "Title", "SecretOwner", "SecretPriority" } }, (si) => si.Name == "g1"); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsTrue(HasRestrictedClauses(result.Query.Where)); Assert.AreEqual("Title, SecretOwner", String.Join(", ", ((SelectQuery)result.Query).Columns)); Assert.AreEqual("SecretPriority", String.Join(", ", result.Details.AccessDeniedColumns)); }
public void SecureDatabase_AggregationQuerySecurity() { SecureDatabase db = BuildSampleDB(); AggregationQuery q = new AggregationQuery("sum", new string[] { "ID" }, "One"); q.TableName = sampleTableName; AggregationResult result; // Run the Query without security. Expect no restrictions and no security checks. result = db.Query(new AggregationQuery(q), (si) => { Assert.Fail("No security checks for unsecured table"); return(true); }); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); // Restrict the secret columns to people in "G1", or users in "G2" can see everything but only for SecretPriority < 1 items. SecureSampleDB(db); // Run the Query as a user in all column restriction groups // Verify the query is unrestricted - no WHERE clause and no filtered columns result = db.Query(new AggregationQuery(q), (si) => si.Name == "g1" || si.Name == "g2"); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); // Run the Query as a user in G3. // Verify WHERE clause restriction. result = db.Query(new AggregationQuery(q), (si) => si.Name == "g3"); Assert.AreEqual("[SecretPriority] > 1 AND [*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); // Run the Query as a user in all groups // Verify WHERE clause restriction for *first* matching group result = db.Query(new AggregationQuery(q), (si) => true); Assert.AreEqual("[SecretPriority] > 1 AND [*]:One", result.Query.Where.ToString()); Assert.IsFalse(HasRestrictedClauses(result.Query.Where)); // Run the Query as a user in no groups. // Verify all column restrictions, no where clause filter result = db.Query(new AggregationQuery(q), (si) => false); Assert.AreEqual("[*]:One", result.Query.Where.ToString()); Assert.IsTrue(HasRestrictedClauses(result.Query.Where)); // Add a query clause for a disallowed column when not in group. Verify error. result = db.Query(new AggregationQuery(q) { Where = QueryParser.Parse("One AND SecretOwner=Bob") }, (si) => false); Assert.AreEqual("", result.Query.Where.ToString()); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretOwner"), result.Details.Errors); // Add a query clause for a disallowed column when in group. Verify success. result = db.Query(new AggregationQuery(q) { Where = QueryParser.Parse("One AND SecretOwner=Bob") }, (si) => si.Name == "g1"); Assert.AreEqual("[*]:One AND [SecretOwner] = Bob", result.Query.Where.ToString()); Assert.IsTrue(HasRestrictedClauses(result.Query.Where)); // Ask to aggregate on a restricted column. Verify error. result = db.Query(new AggregationQuery(q) { AggregationColumns = new string[] { "SecretPriority" } }, (si) => si.Name == "g1"); Assert.AreEqual("", result.Query.Where.ToString()); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretPriority"), result.Details.Errors); // Ask to aggregate over a restricted column dimension. Verify error. AggregationQuery a = new AggregationQuery(q); a.Dimensions.Add(new AggregationDimension("Columns", new string[] { "ID > 5", "ID > 10", "SecretPriority = 1" })); result = db.Query(a, (si) => si.Name == "g1"); Assert.AreEqual("", result.Query.Where.ToString()); Assert.IsFalse(result.Details.Succeeded); Assert.AreEqual(String.Format(ExecutionDetails.DisallowedColumnQuery, "SecretPriority"), result.Details.Errors); }