Bläddra i källkod

Add cloud API keys to auth info report (#130041)

* add change and test

* improve test
Ankit Sethi 3 månader sedan
förälder
incheckning
6520fa2b7c

+ 11 - 4
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/xcontent/XContentUtils.java

@@ -112,9 +112,7 @@ public class XContentUtils {
     private static void addSubjectInfo(XContentBuilder builder, Subject subject) throws IOException {
         switch (subject.getType()) {
             case USER -> builder.array(User.Fields.ROLES.getPreferredName(), subject.getUser().roles());
-            case API_KEY -> {
-                addApiKeyInfo(builder, subject);
-            }
+            case API_KEY -> addApiKeyInfo(builder, subject);
             case SERVICE_ACCOUNT -> builder.field("service_account", subject.getUser().principal());
             case CROSS_CLUSTER_ACCESS -> {
                 builder.startObject("cross_cluster_access");
@@ -129,7 +127,16 @@ public class XContentUtils {
                 builder.endObject();
             }
             case CLOUD_API_KEY -> {
-                // TODO Add cloud API key information here
+                builder.startObject("cloud_api_key");
+                Map<String, Object> metadata = subject.getUser().metadata();
+                builder.field("id", subject.getUser().principal());
+                Object name = metadata.get(AuthenticationField.API_KEY_NAME_KEY);
+                if (name instanceof String) {
+                    builder.field("name", name);
+                }
+                builder.field("internal", metadata.get(AuthenticationField.API_KEY_INTERNAL_KEY));
+                builder.array(User.Fields.ROLES.getPreferredName(), subject.getUser().roles());
+                builder.endObject();
             }
         }
     }

+ 23 - 15
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authc/AuthenticationTestHelper.java

@@ -92,6 +92,27 @@ public class AuthenticationTestHelper {
         );
     }
 
+    public static User randomCloudApiKeyUser() {
+        return randomCloudApiKeyUser(null);
+    }
+
+    public static User randomCloudApiKeyUser(String principal) {
+        final Map<String, Object> metadata = ESTestCase.randomBoolean()
+            ? null
+            : Map.ofEntries(
+                Map.entry(AuthenticationField.API_KEY_NAME_KEY, ESTestCase.randomAlphanumericOfLength(64)),
+                Map.entry(AuthenticationField.API_KEY_INTERNAL_KEY, ESTestCase.randomBoolean())
+            );
+        return new User(
+            principal == null ? ESTestCase.randomAlphanumericOfLength(64) : principal,
+            ESTestCase.randomArray(1, 3, String[]::new, () -> "role_" + ESTestCase.randomAlphaOfLengthBetween(3, 8)),
+            null,
+            null,
+            metadata,
+            true
+        );
+    }
+
     public static InternalUser randomInternalUser() {
         return ESTestCase.randomFrom(InternalUsers.get());
     }
@@ -260,27 +281,14 @@ public class AuthenticationTestHelper {
         if (apiKeyId == null) {
             apiKeyId = user != null ? user.principal() : ESTestCase.randomAlphanumericOfLength(64);
         }
-        final Map<String, Object> metadata = ESTestCase.randomBoolean()
-            ? null
-            : Map.ofEntries(
-                Map.entry(AuthenticationField.API_KEY_NAME_KEY, ESTestCase.randomAlphanumericOfLength(64)),
-                Map.entry(AuthenticationField.API_KEY_INTERNAL_KEY, ESTestCase.randomBoolean())
-            );
         if (user == null) {
-            user = new User(
-                apiKeyId,
-                ESTestCase.randomArray(1, 3, String[]::new, () -> "role_" + ESTestCase.randomAlphaOfLengthBetween(3, 8)),
-                null,
-                null,
-                metadata,
-                true
-            );
+            user = randomCloudApiKeyUser(apiKeyId);
         }
 
         assert user.principal().equals(apiKeyId) : "user principal must match cloud API key ID";
 
         return Authentication.newCloudApiKeyAuthentication(
-            AuthenticationResult.success(user, metadata),
+            AuthenticationResult.success(user, user.metadata()),
             "node_" + ESTestCase.randomAlphaOfLengthBetween(3, 8)
         );
 

+ 17 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/xcontent/XContentUtilsTests.java

@@ -24,8 +24,10 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_ID_KEY;
+import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_INTERNAL_KEY;
 import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_NAME_KEY;
 import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.CROSS_CLUSTER_ACCESS_AUTHENTICATION_KEY;
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 
 public class XContentUtilsTests extends ESTestCase {
@@ -62,6 +64,21 @@ public class XContentUtilsTests extends ESTestCase {
         assertThat(json, equalTo("{\"authorization\":{\"api_key\":{\"id\":\"" + apiKeyId + "\",\"name\":\"" + apiKeyName + "\"}}}"));
     }
 
+    public void testAddAuthorizationInfoWithCloudApiKey() throws IOException {
+        User user = AuthenticationTestHelper.randomCloudApiKeyUser();
+        Authentication authentication = AuthenticationTestHelper.randomCloudApiKeyAuthentication(user);
+        String json = generateJson(Map.of(AuthenticationField.AUTHENTICATION_KEY, authentication.encode()));
+        assertThat(json, containsString("{\"authorization\":{\"cloud_api_key\":{\"id\":\"" + user.principal()));
+        assertThat(json, containsString("\"internal\":" + user.metadata().getOrDefault(API_KEY_INTERNAL_KEY, null)));
+        if (user.metadata().containsKey(API_KEY_NAME_KEY)) {
+            assertThat(json, containsString("\"name\":\"" + user.metadata().getOrDefault(API_KEY_NAME_KEY, null) + "\""));
+        }
+        for (String role : user.roles()) {
+            assertThat(json, containsString(role));
+        }
+
+    }
+
     public void testAddAuthorizationInfoWithServiceAccount() throws IOException {
         String account = "elastic/" + randomFrom("kibana", "fleet-server");
         User user = new User(account);