瀏覽代碼

[docs] Prevent DLS/FLS if replication is assigned (#108839)

This commit adds documentation for the DLS/FLS restriction for RCS 2.0 API keys 
where both access and replication are defined and access has DSL/FLS.
This commit also fixes a few misleading variable names.
related: #108600
Jake Landis 1 年之前
父節點
當前提交
ff92296217

+ 5 - 3
docs/reference/rest-api/security/create-cross-cluster-api-key.asciidoc

@@ -65,10 +65,12 @@ At least one of them must be specified.
 `names`:::: (required, list) A list of indices or name patterns to which the
 permissions in this entry apply.
 `field_security`:::: (optional, object) The document fields that the owners of the role have
-read access to. For more information, check <<field-and-document-access-control>>.
+read access to. This may not be set when the `replication` field is also defined. For more information,
+see <<ccx-apikeys-dls-fls, Field and document level security with cross-cluster API keys>>.
 `query`:::: (optional) A search query that defines the documents the owners of the role have
-read access to. A document within the specified indices must match this query to be accessible by the owners of the role. For more information, check
-<<field-and-document-access-control>>.
+read access to. A document within the specified indices must match this query to be accessible by the
+owners of the role. This may not be set when the `replication` field is also defined. For more information,
+see <<ccx-apikeys-dls-fls, Field and document level security with cross-cluster API keys>>.
 `allow_restricted_indices`:::: (optional, boolean) This needs to be set to `true` (default
 is `false`) if the patterns in the `names` field should cover <<system-indices,system indices>>.
 `replication`::: (optional, list) A list of indices permission entries for cross-cluster replication.

+ 28 - 4
docs/reference/security/authorization/field-and-document-access-control.asciidoc

@@ -3,10 +3,10 @@
 === Setting up field and document level security
 
 You can control access to data within a data stream or index by adding field and document level
-security permissions to a role. 
-<<field-level-security,Field level security permissions>> restrict access to 
-particular fields within a document. 
-<<document-level-security,Document level security permissions>> restrict access 
+security permissions to a role.
+<<field-level-security,Field level security permissions>> restrict access to
+particular fields within a document.
+<<document-level-security,Document level security permissions>> restrict access
 to particular documents.
 
 NOTE: Document and field level security is currently meant to operate with
@@ -59,3 +59,27 @@ documents by index instead.
 
 include::role-templates.asciidoc[]
 include::set-security-user.asciidoc[]
+
+
+[[ccx-apikeys-dls-fls]]
+==== Field and document level security with Cross-cluster API keys
+
+<<security-api-create-cross-cluster-api-key, Cross-Cluster API keys>> can be used to authenticate
+requests to a remote cluster. The `search` parameter defines permissions for cross-cluster search.
+The `replication` parameter defines permissions for cross-cluster replication.
+
+`replication` does not support any field or document level security. `search` supports field and document level security.
+
+For reasons similar to those described in <<multiple-roles-dls-fls,Multiple roles with document and field level security>>,
+you can't create a single cross-cluster API key with both the `search` and `replication` parameters if the
+`search` parameter has document or field level security defined.
+
+If you need to use both of these parameters, and you need to define document or field level security for the `search` parameter,
+create two separate cross-cluster API keys, one using the `search` parameter,
+and one using the `replication` parameter. You will also need to set up two different
+remote connections to the same cluster, with each named connection using the appropriate cross-cluster API key.
+
+
+
+
+

+ 4 - 4
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/apikey/CrossClusterApiKeyRoleDescriptorBuilder.java

@@ -162,8 +162,8 @@ public class CrossClusterApiKeyRoleDescriptorBuilder {
         final String[] clusterPrivileges = roleDescriptor.getClusterPrivileges();
         // only need to check if both "search" and "replication" are defined
         // no need to check for DLS if set of cluster privileges are not the set used pre 8.14
-        final String[] pre8_14ClusterPrivileges = { "cross_cluster_search", "cross_cluster_replication" };
-        final boolean hasBoth = Arrays.equals(clusterPrivileges, pre8_14ClusterPrivileges);
+        final String[] legacyClusterPrivileges = { "cross_cluster_search", "cross_cluster_replication" };
+        final boolean hasBoth = Arrays.equals(clusterPrivileges, legacyClusterPrivileges);
         if (false == hasBoth) {
             return;
         }
@@ -171,9 +171,9 @@ public class CrossClusterApiKeyRoleDescriptorBuilder {
         final RoleDescriptor.IndicesPrivileges[] indicesPrivileges = roleDescriptor.getIndicesPrivileges();
         for (RoleDescriptor.IndicesPrivileges indexPrivilege : indicesPrivileges) {
             final String[] privileges = indexPrivilege.getPrivileges();
-            final String[] pre8_14IndicesPrivileges = { "read", "read_cross_cluster", "view_index_metadata" };
+            final String[] legacyIndicesPrivileges = { "read", "read_cross_cluster", "view_index_metadata" };
             // find the "search" privilege, no need to check for DLS if set of index privileges are not the set used pre 8.14
-            if (Arrays.equals(privileges, pre8_14IndicesPrivileges)) {
+            if (Arrays.equals(privileges, legacyIndicesPrivileges)) {
                 if (indexPrivilege.isUsingDocumentOrFieldLevelSecurity()) {
                     throw new IllegalArgumentException(
                         "Cross cluster API key ["

+ 22 - 20
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/apikey/CrossClusterApiKeyRoleDescriptorBuilderTests.java

@@ -246,18 +246,20 @@ public class CrossClusterApiKeyRoleDescriptorBuilderTests extends ESTestCase {
     }
 
     public void testCheckForInvalidLegacyRoleDescriptors() {
-        final String[] pre8_14ClusterPrivileges_searchAndReplication = { "cross_cluster_search", "cross_cluster_replication" };
-        final String[] pre8_14ClusterPrivileges_searchOnly = { "cross_cluster_search" };
-        final String[] pre8_14IndexPrivileges = { "read", "read_cross_cluster", "view_index_metadata" };
+        // legacy here is in reference to RCS API privileges pre GA, we know which privileges are used in those versions and is used for
+        // minor optimizations. the "legacy" privileges might also be the same as in newer versions, and that is OK too.
+        final String[] legacyClusterPrivileges_searchAndReplication = { "cross_cluster_search", "cross_cluster_replication" };
+        final String[] legacyClusterPrivileges_searchOnly = { "cross_cluster_search" };
+        final String[] legacyIndexPrivileges = { "read", "read_cross_cluster", "view_index_metadata" };
         final String[] otherPrivileges = randomArray(1, 5, String[]::new, () -> randomAlphaOfLength(5));
         String apiKeyId = randomAlphaOfLength(5);
-        RoleDescriptor.IndicesPrivileges pre8_14SearchIndexPrivileges_noDLS = RoleDescriptor.IndicesPrivileges.builder()
+        RoleDescriptor.IndicesPrivileges legacySearchIndexPrivileges_noDLS = RoleDescriptor.IndicesPrivileges.builder()
             .indices(randomAlphaOfLength(5))
-            .privileges(pre8_14IndexPrivileges)
+            .privileges(legacyIndexPrivileges)
             .build();
-        RoleDescriptor.IndicesPrivileges pre8_14SearchIndexPrivileges_withDLS = RoleDescriptor.IndicesPrivileges.builder()
+        RoleDescriptor.IndicesPrivileges legacySearchIndexPrivileges_withDLS = RoleDescriptor.IndicesPrivileges.builder()
             .indices(randomAlphaOfLength(5))
-            .privileges(pre8_14IndexPrivileges)
+            .privileges(legacyIndexPrivileges)
             .query("{\"term\":{\"tag\":42}}")
             .build();
         RoleDescriptor.IndicesPrivileges otherIndexPrivilege = RoleDescriptor.IndicesPrivileges.builder()
@@ -265,18 +267,18 @@ public class CrossClusterApiKeyRoleDescriptorBuilderTests extends ESTestCase {
             .privileges(otherPrivileges) // replication has fixed index privileges, but for this test we don't care about the actual values
             .build();
 
-        // role descriptor emulates pre 8.14 with search and replication with DLS: this is the primary case we are trying to catch
-        RoleDescriptor pre8_14ApiKeyRoleDescriptor_withSearchAndReplication_withDLS = new RoleDescriptor(
+        // role descriptor emulates pre GA with search and replication with DLS: this is the primary case we are trying to catch
+        RoleDescriptor legacyApiKeyRoleDescriptor_withSearchAndReplication_withDLS = new RoleDescriptor(
             ROLE_DESCRIPTOR_NAME,
-            pre8_14ClusterPrivileges_searchAndReplication,
-            new RoleDescriptor.IndicesPrivileges[] { pre8_14SearchIndexPrivileges_withDLS, otherIndexPrivilege },
+            legacyClusterPrivileges_searchAndReplication,
+            new RoleDescriptor.IndicesPrivileges[] { legacySearchIndexPrivileges_withDLS, otherIndexPrivilege },
             null
         );
         IllegalArgumentException exception = expectThrows(
             IllegalArgumentException.class,
             () -> CrossClusterApiKeyRoleDescriptorBuilder.checkForInvalidLegacyRoleDescriptors(
                 apiKeyId,
-                List.of(pre8_14ApiKeyRoleDescriptor_withSearchAndReplication_withDLS)
+                List.of(legacyApiKeyRoleDescriptor_withSearchAndReplication_withDLS)
             )
         );
         assertThat(
@@ -287,32 +289,32 @@ public class CrossClusterApiKeyRoleDescriptorBuilderTests extends ESTestCase {
                     + "] is invalid: search does not support document or field level security if replication is assigned"
             )
         );
-        // role descriptor emulates search only with DLS, this could be a valid role descriptor for pre/post 8.14
+        // role descriptor emulates search only with DLS, this could be a valid role descriptor for pre/post GA
         RoleDescriptor apiKeyRoleDescriptor_withSearch_withDLS = new RoleDescriptor(
             ROLE_DESCRIPTOR_NAME,
-            pre8_14ClusterPrivileges_searchOnly,
-            new RoleDescriptor.IndicesPrivileges[] { pre8_14SearchIndexPrivileges_withDLS },
+            legacyClusterPrivileges_searchOnly,
+            new RoleDescriptor.IndicesPrivileges[] { legacySearchIndexPrivileges_withDLS },
             null
         );
         noErrorCheckRoleDescriptor(apiKeyRoleDescriptor_withSearch_withDLS);
 
-        // role descriptor emulates search and replication without DLS, this could be a valid role descriptor for pre/post 8.14
+        // role descriptor emulates search and replication without DLS, this could be a valid role descriptor for pre/post GA
         RoleDescriptor apiKeyRoleDescriptor_withSearchAndReplication_noDLS = new RoleDescriptor(
             ROLE_DESCRIPTOR_NAME,
-            pre8_14ClusterPrivileges_searchAndReplication,
-            new RoleDescriptor.IndicesPrivileges[] { pre8_14SearchIndexPrivileges_noDLS, otherIndexPrivilege },
+            legacyClusterPrivileges_searchAndReplication,
+            new RoleDescriptor.IndicesPrivileges[] { legacySearchIndexPrivileges_noDLS, otherIndexPrivilege },
             null
         );
         noErrorCheckRoleDescriptor(apiKeyRoleDescriptor_withSearchAndReplication_noDLS);
 
         // role descriptor that will never have search and replication with DLS but may have other privileges
-        RoleDescriptor notpre8_14_apiKeyRoleDescriptor_withSearchAndReplication_DLS = new RoleDescriptor(
+        RoleDescriptor notLegacyApiKeyRoleDescriptor_withSearchAndReplication_DLS = new RoleDescriptor(
             ROLE_DESCRIPTOR_NAME,
             otherPrivileges,
             new RoleDescriptor.IndicesPrivileges[] { otherIndexPrivilege, otherIndexPrivilege },
             null
         );
-        noErrorCheckRoleDescriptor(notpre8_14_apiKeyRoleDescriptor_withSearchAndReplication_DLS);
+        noErrorCheckRoleDescriptor(notLegacyApiKeyRoleDescriptor_withSearchAndReplication_DLS);
     }
 
     private void noErrorCheckRoleDescriptor(RoleDescriptor roleDescriptor) {