Allow null name when deserialising API key document (#59485) (#59496)

API keys can be created without names using grant API key action. This is considered as a bug (#59484). Since the feature has already been released, we need to accomodate existing keys that are created with null names. This PR relaxes the parser logic so that a null name is accepted.
This commit is contained in:
Yang Wang 2020-07-14 16:08:32 +10:00 committed by GitHub
parent 7d20d32a8c
commit 4350add12c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 11 deletions

View File

@ -1040,11 +1040,11 @@ public class ApiKeyService {
builder.declareLong(constructorArg(), new ParseField("creation_time")); builder.declareLong(constructorArg(), new ParseField("creation_time"));
builder.declareLongOrNull(constructorArg(), -1, new ParseField("expiration_time")); builder.declareLongOrNull(constructorArg(), -1, new ParseField("expiration_time"));
builder.declareBoolean(constructorArg(), new ParseField("api_key_invalidated")); builder.declareBoolean(constructorArg(), new ParseField("api_key_invalidated"));
builder.declareString(optionalConstructorArg(), new ParseField("api_key_hash")); builder.declareString(constructorArg(), new ParseField("api_key_hash"));
builder.declareString(constructorArg(), new ParseField("name")); builder.declareStringOrNull(optionalConstructorArg(), new ParseField("name"));
builder.declareInt(constructorArg(), new ParseField("version")); builder.declareInt(constructorArg(), new ParseField("version"));
ObjectParserHelper<ApiKeyDoc, Void> parserHelper = new ObjectParserHelper<>(); ObjectParserHelper<ApiKeyDoc, Void> parserHelper = new ObjectParserHelper<>();
parserHelper.declareRawObject(builder, optionalConstructorArg(), new ParseField("role_descriptors")); parserHelper.declareRawObject(builder, constructorArg(), new ParseField("role_descriptors"));
parserHelper.declareRawObject(builder, constructorArg(), new ParseField("limited_by_role_descriptors")); parserHelper.declareRawObject(builder, constructorArg(), new ParseField("limited_by_role_descriptors"));
builder.declareObject(constructorArg(), (p, c) -> p.map(), new ParseField("creator")); builder.declareObject(constructorArg(), (p, c) -> p.map(), new ParseField("creator"));
PARSER = builder.build(); PARSER = builder.build();
@ -1054,11 +1054,10 @@ public class ApiKeyService {
final long creationTime; final long creationTime;
final long expirationTime; final long expirationTime;
final Boolean invalidated; final Boolean invalidated;
@Nullable
final String hash; final String hash;
@Nullable
final String name; final String name;
final int version; final int version;
@Nullable
final BytesReference roleDescriptorsBytes; final BytesReference roleDescriptorsBytes;
final BytesReference limitedByRoleDescriptorsBytes; final BytesReference limitedByRoleDescriptorsBytes;
final Map<String, Object> creator; final Map<String, Object> creator;
@ -1068,10 +1067,10 @@ public class ApiKeyService {
long creationTime, long creationTime,
long expirationTime, long expirationTime,
Boolean invalidated, Boolean invalidated,
@Nullable String hash, String hash,
String name, @Nullable String name,
int version, int version,
@Nullable BytesReference roleDescriptorsBytes, BytesReference roleDescriptorsBytes,
BytesReference limitedByRoleDescriptorsBytes, BytesReference limitedByRoleDescriptorsBytes,
Map<String, Object> creator) { Map<String, Object> creator) {

View File

@ -800,19 +800,19 @@ public class ApiKeyServiceTests extends ESTestCase {
public void testApiKeyDocDeserialization() throws IOException { public void testApiKeyDocDeserialization() throws IOException {
final String apiKeyDocumentSource = final String apiKeyDocumentSource =
"{\"doc_type\":\"api_key\",\"creation_time\":1591919944598,\"expiration_time\":null,\"api_key_invalidated\":false," + "{\"doc_type\":\"api_key\",\"creation_time\":1591919944598,\"expiration_time\":1591919944599,\"api_key_invalidated\":false," +
"\"api_key_hash\":\"{PBKDF2}10000$abc\",\"role_descriptors\":{\"a\":{\"cluster\":[\"all\"]}}," + "\"api_key_hash\":\"{PBKDF2}10000$abc\",\"role_descriptors\":{\"a\":{\"cluster\":[\"all\"]}}," +
"\"limited_by_role_descriptors\":{\"limited_by\":{\"cluster\":[\"all\"]," + "\"limited_by_role_descriptors\":{\"limited_by\":{\"cluster\":[\"all\"]," +
"\"metadata\":{\"_reserved\":true},\"type\":\"role\"}}," + "\"metadata\":{\"_reserved\":true},\"type\":\"role\"}}," +
"\"name\":\"key-1\",\"version\":7000099," + "\"name\":\"key-1\",\"version\":7000099," +
"\"creator\":{\"principal\":\"admin\",\"metadata\":{\"foo\":\"bar\"},\"realm\":\"file1\",\"realm_type\":\"file\"}}\n"; "\"creator\":{\"principal\":\"admin\",\"metadata\":{\"foo\":\"bar\"},\"realm\":\"file1\",\"realm_type\":\"file\"}}";
final ApiKeyDoc apiKeyDoc = ApiKeyDoc.fromXContent(XContentHelper.createParser(NamedXContentRegistry.EMPTY, final ApiKeyDoc apiKeyDoc = ApiKeyDoc.fromXContent(XContentHelper.createParser(NamedXContentRegistry.EMPTY,
LoggingDeprecationHandler.INSTANCE, LoggingDeprecationHandler.INSTANCE,
new BytesArray(apiKeyDocumentSource), new BytesArray(apiKeyDocumentSource),
XContentType.JSON)); XContentType.JSON));
assertEquals("api_key", apiKeyDoc.docType); assertEquals("api_key", apiKeyDoc.docType);
assertEquals(1591919944598L, apiKeyDoc.creationTime); assertEquals(1591919944598L, apiKeyDoc.creationTime);
assertEquals(-1L, apiKeyDoc.expirationTime); assertEquals(1591919944599L, apiKeyDoc.expirationTime);
assertFalse(apiKeyDoc.invalidated); assertFalse(apiKeyDoc.invalidated);
assertEquals("{PBKDF2}10000$abc", apiKeyDoc.hash); assertEquals("{PBKDF2}10000$abc", apiKeyDoc.hash);
assertEquals("key-1", apiKeyDoc.name); assertEquals("key-1", apiKeyDoc.name);
@ -828,6 +828,22 @@ public class ApiKeyServiceTests extends ESTestCase {
assertEquals("bar", ((Map<String, Object>)creator.get("metadata")).get("foo")); assertEquals("bar", ((Map<String, Object>)creator.get("metadata")).get("foo"));
} }
public void testApiKeyDocDeserializationWithNullValues() throws IOException {
final String apiKeyDocumentSource =
"{\"doc_type\":\"api_key\",\"creation_time\":1591919944598,\"expiration_time\":null,\"api_key_invalidated\":false," +
"\"api_key_hash\":\"{PBKDF2}10000$abc\",\"role_descriptors\":{}," +
"\"limited_by_role_descriptors\":{\"limited_by\":{\"cluster\":[\"all\"]}}," +
"\"name\":null,\"version\":7000099," +
"\"creator\":{\"principal\":\"admin\",\"metadata\":{},\"realm\":\"file1\"}}";
final ApiKeyDoc apiKeyDoc = ApiKeyDoc.fromXContent(XContentHelper.createParser(NamedXContentRegistry.EMPTY,
LoggingDeprecationHandler.INSTANCE,
new BytesArray(apiKeyDocumentSource),
XContentType.JSON));
assertEquals(-1L, apiKeyDoc.expirationTime);
assertNull(apiKeyDoc.name);
assertEquals(new BytesArray("{}"), apiKeyDoc.roleDescriptorsBytes);
}
public static class Utils { public static class Utils {
private static final AuthenticationContextSerializer authenticationContextSerializer = new AuthenticationContextSerializer(); private static final AuthenticationContextSerializer authenticationContextSerializer = new AuthenticationContextSerializer();