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

* add change and test

* improve test
This commit is contained in:
Ankit Sethi 2025-07-01 09:45:54 -05:00 committed by GitHub
parent 1e6473a427
commit 6520fa2b7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 19 deletions

View File

@ -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();
}
}
}

View File

@ -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)
);

View File

@ -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);