Skip to content

Add a new API to update RCS specific API keys #96085

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

Merged
merged 9 commits into from
May 22, 2023

Conversation

ywangd
Copy link
Member

@ywangd ywangd commented May 15, 2023

This PR adds a new endpoint to update RCS specific API keys. It works similarly to the existing UpdateApiKey API except:

  • It requires manage_security permission
  • It does not permit empty request body because it does not use limited-by model
  • It takes the simplified "access" payload as the CreateCrossClusterApiKey API

Relates: #95714

Comment on lines +30 to +32
public final class TransportUpdateCrossClusterApiKeyAction extends TransportBaseUpdateApiKeyAction<
UpdateCrossClusterApiKeyRequest,
UpdateApiKeyResponse> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is technically possible to have a bulk version of this transport action and use it for the single update REST action as well. But doing so could make auditing message look a bit weird because we differentiate beteween single and bulk update in audit events for REST API keys. So I chose to have a dedicate single update transport action and leave out bulk update transport action since we don't need it for now.

Comment on lines +72 to +77
new BaseBulkUpdateApiKeyRequest(List.of(request.getId()), request.getRoleDescriptors(), request.getMetadata()) {
@Override
public ApiKey.Type getType() {
return ApiKey.Type.CROSS_CLUSTER;
}
},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use anonymous class here to have one less class file.

Comment on lines +438 to +443
// Cross-cluster API keys can be created by an API key as long as it has manage_security
final boolean createWithUser = randomBoolean();
if (createWithUser) {
client().execute(CreateCrossClusterApiKeyAction.INSTANCE, request, future);
} else {
final CreateApiKeyResponse createAdminKeyResponse = new CreateApiKeyRequestBuilder(client()).setName("admin-key")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a randomisation here which should have been part of #95714.

@ywangd ywangd marked this pull request as ready for review May 16, 2023 02:14
@ywangd ywangd requested a review from n1v0lg May 16, 2023 02:14
@ywangd ywangd added >non-issue :Security/Security Security issues without another label labels May 16, 2023
@elasticsearchmachine elasticsearchmachine added the Team:Security Meta label for security team label May 16, 2023
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-security (Team:Security)

Copy link
Contributor

@n1v0lg n1v0lg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through the production code (still need to review tests) and I'm on board with the changes, except one behavior which we have to tweak:

Currently, if an API key creates a cross cluster API key, it becomes impossible to update it. The API key can't update it because we prevent this in the ApiKeyService. The owner of the original API key can't update it either because the realm doesn't match anymore (it's set to _es_api_key on the cross cluster key on creation).

I think the simplest way to address this is to simply skip supporting derived cross cluster API keys for now (since there wasn't a strong ask for these in the first place), but wanted to also see your thoughts. Apologies for not catching this in the review of the create API! And apologies if I'm missing something and this isn't actually an issue.

@@ -194,7 +199,8 @@ public class Constants {
"cluster:admin/xpack/security/api_key/update",
"cluster:admin/xpack/security/api_key/bulk_update",
"cluster:admin/xpack/security/cache/clear",
"cluster:admin/xpack/security/cross_cluster/api_key/create",
TcpTransport.isUntrustedRemoteClusterEnabled() ? "cluster:admin/xpack/security/cross_cluster/api_key/create" : null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

}

@Override
void resolveUserRoleDescriptors(Authentication authentication, ActionListener<Set<RoleDescriptor>> listener) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think we could collapse the two abstract methods into one, since they are only called together. Something like:

abstract void doExecuteUpdate(
    Task task,
    Request request,
    Authentication authentication,
    ActionListener<Response> listener
);

The fact that we are resolving role descriptors is arguably an implementation detail of the regular update actions; for cross cluster, we don't really resolve.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah one abstract method looks better. I have updated accordingly e62022c

@ywangd
Copy link
Member Author

ywangd commented May 16, 2023

For the derived key issue, I commented on the PR of create API here #95714 (comment)

I personally think it's a separate issue since it's a known bug. Other than not updatable, it otherwise works just fine. My preference would be moving forward as is and fork a separate issue to agree on API key's identity and ownership. But please let me know if you think otherwise.

The other issue that I realised today is that we should have license check for both APIs. I'll have it as a separate PR to keep the size in control.

@n1v0lg
Copy link
Contributor

n1v0lg commented May 16, 2023

For the derived key issue, I commented on the PR of create API here #95714 (comment)

Ah apologies, I missed this!

My preference would be moving forward as is and fork a separate issue to agree on API key's identity and ownership.

Since the API key does end up broken (in a surprising way), I think it would be good to either fix the bug or keep derived API keys out of scope. Totally fair to handle this outside of this PR though, and fork a separate issue 👍

The other issue that I realised today is that we should have license check for both APIs. I'll have it as a separate PR to keep the size in control.

Sounds good!

@ywangd ywangd requested a review from n1v0lg May 17, 2023 11:24
Copy link
Contributor

@n1v0lg n1v0lg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Sorry for the delay. Just a few smaller things and nits around tests.

final CreateCrossClusterApiKeyRequest request = CreateCrossClusterApiKeyRequest.withNameAndAccess(
randomAlphaOfLengthBetween(3, 8),
"""
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: there is a bunch of extra whitespace here; lets nuke it


public void testUpdateHasTypeOfCrossCluster() throws Exception {
final String id = randomAlphaOfLength(10);
final String access = randomFrom(ACCESS_CANDIDATES);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally optional but a randomCrossClusterApiKeyAccessField() or something like that could be a nice wrapper

Copy link
Member Author

@ywangd ywangd May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add suggested method to CreateCrossClusterApiKeyRequestTests and replace all occurences like this one with the new method.

@ywangd
Copy link
Member Author

ywangd commented May 22, 2023

Thanks a lot for the thorough review and nice catches!

@ywangd ywangd added the auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) label May 22, 2023
@elasticsearchmachine elasticsearchmachine merged commit 471b3f5 into elastic:main May 22, 2023
@ywangd ywangd deleted the rcs-update-special-api-keys branch May 22, 2023 23:42
ywangd added a commit that referenced this pull request May 25, 2023
Enforce the same license level as the advanced remote cluster security
feature for these APIs.

Relates: #95714, #96085
ywangd added a commit to ywangd/elasticsearch that referenced this pull request May 25, 2023
This PR adds REST spec files and YAML tests for the new create and
update cross-cluster API key APIs.

Relates: elastic#95714, elastic#96085
elasticsearchmachine pushed a commit that referenced this pull request May 26, 2023
This PR adds REST spec files and YAML tests for the new create and
update cross-cluster API key APIs.

Relates: #95714, #96085
ywangd added a commit to ywangd/elasticsearch that referenced this pull request May 30, 2023
This PR adds API doc pages for the new create and update cross-cluster
API key APIs.

Relates: elastic#95714, elastic#96085
ywangd added a commit that referenced this pull request Jun 8, 2023
This PR adds API doc pages for the new create and update cross-cluster API key APIs.

Relates: #95714, #96085

Co-authored-by: Arianna Laudazzi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) >non-issue :Security/Security Security issues without another label Team:Security Meta label for security team v8.9.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants