Integ test cases for field-level security#5008
Integ test cases for field-level security#5008Swiddis wants to merge 12 commits intoopensearch-project:mainfrom
Conversation
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a SecurityTestBase providing role/user/DLS/FLS helpers, authenticated query and bulk utilities; introduces FGACIndexScanningIT to test index-, field-, and row-level FGAC with large datasets across two engine modes; refactors PPLPermissionsIT to use the new base; and updates integ-test build deps for JUnit parameterized tests. Changes
Sequence Diagram(s)sequenceDiagram
actor Test
participant Base as SecurityTestBase
participant OpenSearch
participant Auth as Auth/Authorization
rect rgba(230,240,255,0.5)
Note over Test,Base: Setup Phase
Test->>Base: createRoleWithIndexAccess(role, indexPattern)
Base->>OpenSearch: HTTP role creation (index/DLS/FLS/permissions)
OpenSearch-->>Base: 200 OK
Test->>Base: createUser(username, role)
Base->>OpenSearch: HTTP user creation & role-mapping
OpenSearch-->>Base: 200 OK
end
rect rgba(240,255,230,0.5)
Note over Test,Base: Bulk Load Phase
Test->>Base: performBulkInsert(bulkBody)
Base->>OpenSearch: Bulk API request (with refresh)
OpenSearch-->>Base: Bulk response
end
rect rgba(255,240,230,0.5)
Note over Test,Base: Authenticated Query Phase
Test->>Base: executeQueryAsUser(query, username)
Base->>Base: createBasicAuthHeader(username, password)
Base->>OpenSearch: PPL query + Basic Auth header
OpenSearch->>Auth: Validate credentials & evaluate roles
Auth-->>OpenSearch: Authorization decision
OpenSearch-->>Base: Query results (filtered by FGAC)
Base-->>Test: JSONObject response
end
rect rgba(245,235,255,0.5)
Note over Test: Verification
Test->>Test: Assert results match expected FGAC behavior
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
1b1ca7b to
ded19e9
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java (2)
53-64: Static initialization flag may cause issues with test isolation.The
static boolean initializedflag combined with@BeforeEachcould cause issues if tests run in parallel or if the test class is instantiated multiple times. Consider using@BeforeAllwith a static method instead, which is the idiomatic JUnit 5 pattern for one-time setup.🔎 Proposed refactor to use @BeforeAll
- private static boolean initialized = false; - - @SneakyThrows - @BeforeEach - public void initialize() { - if (!initialized) { - setUpIndices(); // Initialize client if needed - setupTestIndices(); - createSecurityRolesAndUsers(); - initialized = true; - } - } + @SneakyThrows + @BeforeAll + public static void initializeOnce() { + // Note: This requires making the setup methods static or + // using a different initialization approach + }Alternatively, if
@BeforeAllisn't compatible with the parent class, document why the static flag pattern is necessary.
74-85: Consider adding test cleanup for created indices.The test creates multiple indices (
public_logs_fgac,sensitive_logs_fgac,secure_logs_fgac,employee_records_fgac) but there's no@AfterAllor@AfterEachcleanup method. While using unique_fgacsuffix provides isolation, these indices will persist after tests complete.As per coding guidelines, integration tests should validate that tests clean up resources after execution.
🔎 Consider adding cleanup
@AfterAll public static void cleanup() throws IOException { // Delete test indices String[] indices = {PUBLIC_LOGS, SENSITIVE_LOGS, SECURE_LOGS, EMPLOYEE_RECORDS}; for (String index : indices) { try { client().performRequest(new Request("DELETE", "/" + index)); } catch (Exception e) { // Index may not exist, ignore } } }integ-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java (2)
56-98: Consider using JSONArray for permission arrays to avoid manual string building.The manual StringBuilder approach for building JSON arrays works but is error-prone. Using
JSONArraywould be cleaner and safer.🔎 Optional refactor using JSONArray
import org.json.JSONArray; // In createRoleWithPermissions: JSONArray clusterPermsArray = new JSONArray(clusterPermissions); JSONArray indexPermsArray = new JSONArray(indexPermissions); // Then use clusterPermsArray.toString() and indexPermsArray.toString() in the template
341-353: Remove unusedBulkDocumentBuilderhelper class or document its intended purpose.The
BulkDocumentBuilderis defined but never instantiated or used anywhere in the codebase. Either remove it if not needed for this PR, or add a comment documenting its intended usage in future tests.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
integ-test/build.gradleinteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.javainteg-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java
📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)
**/*.java: UsePascalCasefor class names (e.g.,QueryExecutor)
UsecamelCasefor method and variable names (e.g.,executeQuery)
UseUPPER_SNAKE_CASEfor constants (e.g.,MAX_RETRY_COUNT)
Keep methods under 20 lines with single responsibility
All public classes and methods must have proper JavaDoc
Use specific exception types with meaningful messages for error handling
PreferOptional<T>for nullable returns in Java
Avoid unnecessary object creation in loops
UseStringBuilderfor string concatenation in loops
Validate all user inputs, especially queries
Sanitize data before logging to prevent injection attacks
Use try-with-resources for proper resource cleanup in Java
Maintain Java 11 compatibility when possible for OpenSearch 2.x
Document Calcite-specific workarounds in code
Files:
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.javainteg-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java
⚙️ CodeRabbit configuration file
**/*.java: - Flag methods >50 lines as potentially too complex - suggest refactoring
- Flag classes >500 lines as needing organization review
- Check for dead code, unused imports, and unused variables
- Identify code reuse opportunities across similar implementations
- Assess holistic maintainability - is code easy to understand and modify?
- Flag code that appears AI-generated without sufficient human review
- Verify Java naming conventions (PascalCase for classes, camelCase for methods/variables)
- Check for proper JavaDoc on public classes and methods
- Flag redundant comments that restate obvious code
- Ensure proper error handling with specific exception types
- Check for Optional usage instead of null returns
- Validate proper use of try-with-resources for resource management
Files:
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.javainteg-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java
integ-test/**/*IT.java
📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)
End-to-end scenarios need integration tests in
integ-test/module
Files:
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
⚙️ CodeRabbit configuration file
integ-test/**/*IT.java: - Integration tests MUST use valid test data from resources
- Verify test data files exist in integ-test/src/test/resources/
- Check test assertions are meaningful and specific
- Validate tests clean up resources after execution
- Ensure tests are independent and can run in any order
- Flag tests that reference non-existent indices (e.g., EMP)
- Verify integration tests are in correct module (integ-test/)
- Check tests can be run with ./gradlew :integ-test:integTest
- Ensure proper test data setup and teardown
- Validate end-to-end scenario coverage
Files:
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
**/*IT.java
📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)
Name integration tests with
*IT.javasuffix in OpenSearch SQL
Files:
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
**/test/**/*.java
⚙️ CodeRabbit configuration file
**/test/**/*.java: - Verify NULL input tests for all new functions
- Check boundary condition tests (min/max values, empty inputs)
- Validate error condition tests (invalid inputs, exceptions)
- Ensure multi-document tests for per-document operations
- Flag smoke tests without meaningful assertions
- Check test naming follows pattern: test
- Verify test data is realistic and covers edge cases
- Verify test coverage for new business logic
- Ensure tests are independent and don't rely on execution order
- Validate meaningful test data that reflects real-world scenarios
- Check for proper cleanup of test resources
Files:
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.javainteg-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Applies to **/*IT.java : Name integration tests with `*IT.java` suffix in OpenSearch SQL
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Verify changes with `./gradlew :integ-test:integTest` before merge
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Verify changes with `./gradlew :integ-test:integTest` before merge
Applied to files:
integ-test/build.gradle
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Applies to integ-test/**/*IT.java : End-to-end scenarios need integration tests in `integ-test/` module
Applied to files:
integ-test/build.gradle
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Use `./gradlew :integ-test:integTest` for integration testing in OpenSearch SQL
Applied to files:
integ-test/build.gradle
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Applies to **/*IT.java : Name integration tests with `*IT.java` suffix in OpenSearch SQL
Applied to files:
integ-test/build.gradleinteg-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.javainteg-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.javainteg-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Development requires JDK 21 for the OpenSearch SQL project
Applied to files:
integ-test/build.gradle
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Applies to **/*Test.java : Name unit tests with `*Test.java` suffix in OpenSearch SQL
Applied to files:
integ-test/build.gradleinteg-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Test SQL generation and optimization paths for Calcite integration changes
Applied to files:
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
🧬 Code graph analysis (1)
integ-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java (1)
integ-test/src/test/java/org/opensearch/sql/ppl/PPLIntegTestCase.java (1)
PPLIntegTestCase(36-415)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
- GitHub Check: build-linux (21, integration)
- GitHub Check: build-linux (25, unit)
- GitHub Check: build-linux (25, integration)
- GitHub Check: build-linux (21, unit)
- GitHub Check: build-windows-macos (macos-14, 25, integration)
- GitHub Check: build-windows-macos (macos-14, 25, unit)
- GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, integration)
- GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, integration)
- GitHub Check: build-windows-macos (macos-14, 21, integration)
- GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, unit)
- GitHub Check: build-windows-macos (macos-14, 21, unit)
- GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, unit)
- GitHub Check: security-it-windows-macos (windows-latest, 25)
- GitHub Check: CodeQL-Scan (java)
🔇 Additional comments (12)
integ-test/build.gradle (2)
211-212: LGTM - Dependency addition for parameterized tests.The
junit-jupiter-paramsdependency aligns with the existing JUnit 5 version (5.9.3) used in the project.
449-453: LGTM - Test filter inclusion follows existing pattern.The
FGACIndexScanningITtest is correctly added to the security test filter alongside existing security integration tests. Based on learnings, the*IT.javanaming convention is properly followed.integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java (4)
197-223: LGTM - Bulk insert implementation follows best practices.The method correctly uses
StringBuilderfor string concatenation in loops (as per coding guidelines), sets the properContent-Type: application/x-ndjsonheader, and verifies the response status code.
363-405: LGTM - Index-level security test is comprehensive.The test properly validates both positive cases (user can access their index) and negative cases (user cannot access unauthorized index) with meaningful assertions. The exception handling verifies appropriate error messages.
407-499: LGTM - Column-level security test covers FLS comprehensively.The test validates:
- HR user can see all fields including sensitive
ssn- Manager user cannot see
ssnfield- Manager cannot even query
ssnfield- FLS is enforced even with large datasets (background scanning)
Error messages clearly indicate security violations with actionable context.
501-628: LGTM - Row-level security tests cover both V2 and V3 engines.The tests appropriately:
- Test V2 (legacy) engine by explicitly calling
disableCalcite()- Test V3 (Calcite) engine using the default enabled state
- Verify DLS filtering by counting documents per security level
- Include detailed error messages explaining ThreadContext implications
integ-test/src/test/java/org/opensearch/sql/security/SecurityTestBase.java (3)
19-26: LGTM - Well-structured base class with clear documentation.The abstract class properly inherits from
PPLIntegTestCaseand provides reusable utilities for security integration tests, reducing code duplication across test classes.
198-248: LGTM - User creation with role mapping is convenient for test setup.The method appropriately combines user creation and role mapping, which is a common pattern for test utilities. Both operations verify success via status codes.
250-277: LGTM - Clean implementation for authenticated query execution.The method properly constructs the request with Basic Auth headers and validates the response status code before parsing.
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.java (3)
31-31: LGTM - Good refactoring to extend SecurityTestBase.The class now properly inherits from
SecurityTestBase, eliminating duplicate code for role/user creation and authenticated query execution.
83-102: LGTM - Clean usage of inherited SecurityTestBase methods.The refactored setup properly delegates to the base class methods for creating roles and users, following DRY principles.
104-194: LGTM - Comprehensive negative test setup with inherited utilities.The helper methods properly use
createRoleWithPermissionsfromSecurityTestBaseto create roles with specific missing permissions, enabling thorough negative testing of permission enforcement.
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Show resolved
Hide resolved
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Outdated
Show resolved
Hide resolved
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Show resolved
Hide resolved
|
This PR is stalled because it has been open for 2 weeks with no activity. |
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In
`@integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java`:
- Around line 265-309: bulkInsertDocsWithSecurityLevel currently only inserts
documents with non-null security_level; add a few extra bulk entries that
include one document with "security_level": null and one document that omits the
security_level field entirely (use FGACIndexScanningIT.SECURE_LOGS as the
_index) so DLS behavior for null/missing values is exercised; update any
corresponding assertions in the test that verifies visibility for limited_user
to assert those null/missing-security_level docs are not visible.
- Around line 502-527: The test testFieldLevelSecurityEnforcedWithLargeDataset
currently uses a query that excludes ssn so it doesn't exercise FLS; change the
test to either (A) issue a query that directly requests the restricted field
(e.g., include "ssn" in the fields list) via
executeQueryAsUser(queryLargeDataset, MANAGER_USER) and assert that it fails
with the same ResponseException expectation used in
testManagerUserCannotQueryRestrictedField, or (B) keep the large-dataset query
but assert presence of allowed fields (name, salary, department) in the returned
schema/result to prove the query executed and FLS is not leaking extra fields;
update assertions accordingly and reuse existing constants EMPLOYEE_RECORDS and
MANAGER_USER to locate where to modify the query and assertions.
- Around line 529-600: The testRowLevelSecurity method reads datarows assuming
fixed column positions; instead read the result.getJSONArray("schema") to find
indexes for "count()" and "security_level" (e.g., locate these names in the
schema array), validate those indexes are present, then use those index
variables when extracting values from datarows in the loop; update references to
count and securityLevel accordingly and add an assertion/failure if the schema
does not contain the expected columns so the test fails loudly rather than
silently misreading columns.
- Around line 196-222: The bulk helper functions (bulkInsertDocs,
bulkInsertEmployeeRecords, bulkInsertDocsWithSecurityLevel) only assert HTTP
200, missing per-item failures; after performing the _bulk request read and
parse the response body JSON and assert the top-level "errors" field is false
(and optionally inspect "items" to fail the test with the first item error),
replacing the lone status check with this validation so partial failures cause
the test to fail.
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Show resolved
Hide resolved
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Show resolved
Hide resolved
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Show resolved
Hide resolved
integ-test/src/test/java/org/opensearch/sql/security/FGACIndexScanningIT.java
Show resolved
Hide resolved
Signed-off-by: Simeon Widdis <sawiddis@amazon.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
integ-test/src/test/java/org/opensearch/sql/security/PPLPermissionsIT.java (1)
238-240:⚠️ Potential issue | 🟡 MinorComment has incorrect index name.
The comment states "user should not be able to access the dog index" but this test verifies that
dog_usercannot access the bank index.📝 Suggested fix
} catch (ResponseException e) { - // This is expected - user should not be able to access the dog index + // This is expected - user should not be able to access the bank index String responseBody =
|
This PR is stalled because it has been open for 2 weeks with no activity. |
|
This PR is stalled because it has been open for 2 weeks with no activity. |
PR Code Analyzer ❗AI-powered 'Code-Diff-Analyzer' found issues on commit e2e95ae.
The table above displays the top 10 most important findings. Pull Requests Author(s): Please update your Pull Request according to the report above. Repository Maintainer(s): You can Thanks. |
i'd expect that reference to have shown up enough times in their training data. |
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
Description
Adds some tests to validate various scenarios for document-level security (DLS), since there was an internal scare for a bit on if DLS is working with background IO. Turns out we're protected implicitly by ContextPreservingRunnable. Just pushing some work from that to keep verifying this in the future.
Related Issues
N/A
Check List
--signoffor-s.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.