Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLRC: add support for retrieval/invalidation of owned API keys #45474

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ static Request getApiKey(final GetApiKeyRequest getApiKeyRequest) throws IOExcep
if (Strings.hasText(getApiKeyRequest.getRealmName())) {
request.addParameter("realm_name", getApiKeyRequest.getRealmName());
}

request.addParameter("owner", Boolean.toString(getApiKeyRequest.ownedByAuthenticatedUser()));
return request;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,34 @@ public final class GetApiKeyRequest implements Validatable, ToXContentObject {
private final String userName;
private final String id;
private final String name;
private final boolean ownedByAuthenticatedUser;

// pkg scope for testing
GetApiKeyRequest(@Nullable String realmName, @Nullable String userName, @Nullable String apiKeyId,
@Nullable String apiKeyName) {
@Nullable String apiKeyName, boolean ownedByAuthenticatedUser) {
if (Strings.hasText(realmName) == false && Strings.hasText(userName) == false && Strings.hasText(apiKeyId) == false
&& Strings.hasText(apiKeyName) == false) {
throwValidationError("One of [api key id, api key name, username, realm name] must be specified");
&& Strings.hasText(apiKeyName) == false && ownedByAuthenticatedUser == false) {
throwValidationError("One of [api key id, api key name, username, realm name] must be specified if [owner] flag is false");
}
if (Strings.hasText(apiKeyId) || Strings.hasText(apiKeyName)) {
if (Strings.hasText(realmName) || Strings.hasText(userName)) {
throwValidationError(
"username or realm name must not be specified when the api key id or api key name is specified");
}
}
if (ownedByAuthenticatedUser) {
if (Strings.hasText(realmName) || Strings.hasText(userName)) {
throwValidationError("neither username nor realm-name may be specified when retrieving owned API keys");
}
}
if (Strings.hasText(apiKeyId) && Strings.hasText(apiKeyName)) {
throwValidationError("only one of [api key id, api key name] can be specified");
}
this.realmName = realmName;
this.userName = userName;
this.id = apiKeyId;
this.name = apiKeyName;
this.ownedByAuthenticatedUser = ownedByAuthenticatedUser;
}

private void throwValidationError(String message) {
Expand All @@ -79,13 +86,17 @@ public String getName() {
return name;
}

public boolean ownedByAuthenticatedUser() {
return ownedByAuthenticatedUser;
}

/**
* Creates get API key request for given realm name
* @param realmName realm name
* @return {@link GetApiKeyRequest}
*/
public static GetApiKeyRequest usingRealmName(String realmName) {
return new GetApiKeyRequest(realmName, null, null, null);
return new GetApiKeyRequest(realmName, null, null, null, false);
}

/**
Expand All @@ -94,7 +105,7 @@ public static GetApiKeyRequest usingRealmName(String realmName) {
* @return {@link GetApiKeyRequest}
*/
public static GetApiKeyRequest usingUserName(String userName) {
return new GetApiKeyRequest(null, userName, null, null);
return new GetApiKeyRequest(null, userName, null, null, false);
}

/**
Expand All @@ -104,25 +115,36 @@ public static GetApiKeyRequest usingUserName(String userName) {
* @return {@link GetApiKeyRequest}
*/
public static GetApiKeyRequest usingRealmAndUserName(String realmName, String userName) {
return new GetApiKeyRequest(realmName, userName, null, null);
return new GetApiKeyRequest(realmName, userName, null, null, false);
}

/**
* Creates get API key request for given api key id
* @param apiKeyId api key id
* @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current
* authenticated user else{@code false}
* @return {@link GetApiKeyRequest}
*/
public static GetApiKeyRequest usingApiKeyId(String apiKeyId) {
return new GetApiKeyRequest(null, null, apiKeyId, null);
public static GetApiKeyRequest usingApiKeyId(String apiKeyId, boolean ownedByAuthenticatedUser) {
return new GetApiKeyRequest(null, null, apiKeyId, null, ownedByAuthenticatedUser);
}

/**
* Creates get API key request for given api key name
* @param apiKeyName api key name
* @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current
* authenticated user else{@code false}
* @return {@link GetApiKeyRequest}
*/
public static GetApiKeyRequest usingApiKeyName(String apiKeyName) {
return new GetApiKeyRequest(null, null, null, apiKeyName);
public static GetApiKeyRequest usingApiKeyName(String apiKeyName, boolean ownedByAuthenticatedUser) {
return new GetApiKeyRequest(null, null, null, apiKeyName, ownedByAuthenticatedUser);
}

/**
* Creates get api key request to retrieve api key information for the api keys owned by the current authenticated user.
*/
public static GetApiKeyRequest forOwnedApiKeys() {
return new GetApiKeyRequest(null, null, null, null, true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,34 @@ public final class InvalidateApiKeyRequest implements Validatable, ToXContentObj
private final String userName;
private final String id;
private final String name;
private final boolean ownedByAuthenticatedUser;

// pkg scope for testing
InvalidateApiKeyRequest(@Nullable String realmName, @Nullable String userName, @Nullable String apiKeyId,
@Nullable String apiKeyName) {
@Nullable String apiKeyName, boolean ownedByAuthenticatedUser) {
if (Strings.hasText(realmName) == false && Strings.hasText(userName) == false && Strings.hasText(apiKeyId) == false
&& Strings.hasText(apiKeyName) == false) {
throwValidationError("One of [api key id, api key name, username, realm name] must be specified");
&& Strings.hasText(apiKeyName) == false && ownedByAuthenticatedUser == false) {
throwValidationError("One of [api key id, api key name, username, realm name] must be specified if [owner] flag is false");
}
if (Strings.hasText(apiKeyId) || Strings.hasText(apiKeyName)) {
if (Strings.hasText(realmName) || Strings.hasText(userName)) {
throwValidationError(
"username or realm name must not be specified when the api key id or api key name is specified");
}
}
if (ownedByAuthenticatedUser) {
if (Strings.hasText(realmName) || Strings.hasText(userName)) {
throwValidationError("neither username nor realm-name may be specified when invalidating owned API keys");
}
}
if (Strings.hasText(apiKeyId) && Strings.hasText(apiKeyName)) {
throwValidationError("only one of [api key id, api key name] can be specified");
}
this.realmName = realmName;
this.userName = userName;
this.id = apiKeyId;
this.name = apiKeyName;
this.ownedByAuthenticatedUser = ownedByAuthenticatedUser;
}

private void throwValidationError(String message) {
Expand All @@ -79,13 +86,17 @@ public String getName() {
return name;
}

public boolean ownedByAuthenticatedUser() {
return ownedByAuthenticatedUser;
}

/**
* Creates invalidate API key request for given realm name
* @param realmName realm name
* @return {@link InvalidateApiKeyRequest}
*/
public static InvalidateApiKeyRequest usingRealmName(String realmName) {
return new InvalidateApiKeyRequest(realmName, null, null, null);
return new InvalidateApiKeyRequest(realmName, null, null, null, false);
}

/**
Expand All @@ -94,7 +105,7 @@ public static InvalidateApiKeyRequest usingRealmName(String realmName) {
* @return {@link InvalidateApiKeyRequest}
*/
public static InvalidateApiKeyRequest usingUserName(String userName) {
return new InvalidateApiKeyRequest(null, userName, null, null);
return new InvalidateApiKeyRequest(null, userName, null, null, false);
}

/**
Expand All @@ -104,25 +115,36 @@ public static InvalidateApiKeyRequest usingUserName(String userName) {
* @return {@link InvalidateApiKeyRequest}
*/
public static InvalidateApiKeyRequest usingRealmAndUserName(String realmName, String userName) {
return new InvalidateApiKeyRequest(realmName, userName, null, null);
return new InvalidateApiKeyRequest(realmName, userName, null, null, false);
}

/**
* Creates invalidate API key request for given api key id
* @param apiKeyId api key id
* @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current authenticated user else
* {@code false}
* @return {@link InvalidateApiKeyRequest}
*/
public static InvalidateApiKeyRequest usingApiKeyId(String apiKeyId) {
return new InvalidateApiKeyRequest(null, null, apiKeyId, null);
public static InvalidateApiKeyRequest usingApiKeyId(String apiKeyId, boolean ownedByAuthenticatedUser) {
return new InvalidateApiKeyRequest(null, null, apiKeyId, null, ownedByAuthenticatedUser);
}

/**
* Creates invalidate API key request for given api key name
* @param apiKeyName api key name
* @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current authenticated user else
* {@code false}
* @return {@link InvalidateApiKeyRequest}
*/
public static InvalidateApiKeyRequest usingApiKeyName(String apiKeyName) {
return new InvalidateApiKeyRequest(null, null, null, apiKeyName);
public static InvalidateApiKeyRequest usingApiKeyName(String apiKeyName, boolean ownedByAuthenticatedUser) {
return new InvalidateApiKeyRequest(null, null, null, apiKeyName, ownedByAuthenticatedUser);
}

/**
* Creates invalidate api key request to invalidate api keys owned by the current authenticated user.
*/
public static InvalidateApiKeyRequest forOwnedApiKeys() {
return new InvalidateApiKeyRequest(null, null, null, null, true);
}

@Override
Expand All @@ -140,6 +162,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
if (name != null) {
builder.field("name", name);
}
builder.field("owner", ownedByAuthenticatedUser);
return builder.endObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1917,7 +1917,7 @@ public void testGetApiKey() throws Exception {
Instant.now().plusMillis(expiration.getMillis()), false, "test_user", "default_file");
{
// tag::get-api-key-id-request
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId());
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId(), false);
// end::get-api-key-id-request

// tag::get-api-key-execute
Expand All @@ -1931,7 +1931,7 @@ public void testGetApiKey() throws Exception {

{
// tag::get-api-key-name-request
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyName(createApiKeyResponse1.getName());
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyName(createApiKeyResponse1.getName(), false);
// end::get-api-key-name-request

GetApiKeyResponse getApiKeyResponse = client.security().getApiKey(getApiKeyRequest, RequestOptions.DEFAULT);
Expand Down Expand Up @@ -1965,6 +1965,18 @@ public void testGetApiKey() throws Exception {
verifyApiKey(getApiKeyResponse.getApiKeyInfos().get(0), expectedApiKeyInfo);
}

{
// tag::get-api-keys-owned-by-authenticated-user-request
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.forOwnedApiKeys();
// end::get-api-keys-owned-by-authenticated-user-request

GetApiKeyResponse getApiKeyResponse = client.security().getApiKey(getApiKeyRequest, RequestOptions.DEFAULT);

assertThat(getApiKeyResponse.getApiKeyInfos(), is(notNullValue()));
assertThat(getApiKeyResponse.getApiKeyInfos().size(), is(1));
verifyApiKey(getApiKeyResponse.getApiKeyInfos().get(0), expectedApiKeyInfo);
}

{
// tag::get-user-realm-api-keys-request
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingRealmAndUserName("default_file", "test_user");
Expand All @@ -1980,7 +1992,7 @@ public void testGetApiKey() throws Exception {
}

{
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId());
GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId(), false);

ActionListener<GetApiKeyResponse> listener;
// tag::get-api-key-execute-listener
Expand Down Expand Up @@ -2041,7 +2053,7 @@ public void testInvalidateApiKey() throws Exception {

{
// tag::invalidate-api-key-id-request
InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId());
InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId(), false);
// end::invalidate-api-key-id-request

// tag::invalidate-api-key-execute
Expand All @@ -2066,7 +2078,8 @@ public void testInvalidateApiKey() throws Exception {
assertNotNull(createApiKeyResponse2.getKey());

// tag::invalidate-api-key-name-request
InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyName(createApiKeyResponse2.getName());
InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyName(createApiKeyResponse2.getName(),
false);
// end::invalidate-api-key-name-request

InvalidateApiKeyResponse invalidateApiKeyResponse = client.security().invalidateApiKey(invalidateApiKeyRequest,
Expand Down Expand Up @@ -2159,7 +2172,7 @@ public void testInvalidateApiKey() throws Exception {
assertThat(createApiKeyResponse6.getName(), equalTo("k6"));
assertNotNull(createApiKeyResponse6.getKey());

InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse6.getId());
InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse6.getId(), false);

ActionListener<InvalidateApiKeyResponse> listener;
// tag::invalidate-api-key-execute-listener
Expand Down Expand Up @@ -2195,5 +2208,29 @@ public void onFailure(Exception e) {
assertThat(invalidatedApiKeyIds, containsInAnyOrder(expectedInvalidatedApiKeyIds.toArray(Strings.EMPTY_ARRAY)));
assertThat(response.getPreviouslyInvalidatedApiKeys().size(), equalTo(0));
}

{
createApiKeyRequest = new CreateApiKeyRequest("k7", roles, expiration, refreshPolicy);
CreateApiKeyResponse createApiKeyResponse7 = client.security().createApiKey(createApiKeyRequest, RequestOptions.DEFAULT);
assertThat(createApiKeyResponse7.getName(), equalTo("k7"));
assertNotNull(createApiKeyResponse7.getKey());

// tag::invalidate-api-keys-owned-by-authenticated-user-request
InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.forOwnedApiKeys();
// end::invalidate-api-keys-owned-by-authenticated-user-request

InvalidateApiKeyResponse invalidateApiKeyResponse = client.security().invalidateApiKey(invalidateApiKeyRequest,
RequestOptions.DEFAULT);

final List<ElasticsearchException> errors = invalidateApiKeyResponse.getErrors();
final List<String> invalidatedApiKeyIds = invalidateApiKeyResponse.getInvalidatedApiKeys();
final List<String> previouslyInvalidatedApiKeyIds = invalidateApiKeyResponse.getPreviouslyInvalidatedApiKeys();

assertTrue(errors.isEmpty());
List<String> expectedInvalidatedApiKeyIds = Arrays.asList(createApiKeyResponse7.getId());
assertThat(invalidatedApiKeyIds, containsInAnyOrder(expectedInvalidatedApiKeyIds.toArray(Strings.EMPTY_ARRAY)));
assertThat(previouslyInvalidatedApiKeyIds.size(), equalTo(0));
}

}
}
Loading