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

acl_store: Return prefix matches as a view #17152

Merged
merged 4 commits into from
Mar 28, 2024

Conversation

oleiman
Copy link
Member

@oleiman oleiman commented Mar 17, 2024

This PR refactors acl_store slightly to return prefix ACL matches as a view. This saves a vector allocation on the authZ path.

Also breaks some header dependencies in an effort to isolate view templates to the specific compilation units where they are needed.

Backports Required

  • none - not a bug fix
  • none - this is a backport
  • none - issue does not exist in previous branches
  • none - papercut/not impactful enough to backport
  • v23.3.x
  • v23.2.x

Release Notes

  • none

@oleiman oleiman self-assigned this Mar 17, 2024
@oleiman oleiman mentioned this pull request Mar 17, 2024
6 tasks
@oleiman oleiman force-pushed the security/acl-store-alloc branch 3 times, most recently from 6703782 to cc8fd02 Compare March 18, 2024 18:26
@oleiman oleiman requested a review from BenPope March 18, 2024 18:26
@oleiman
Copy link
Member Author

oleiman commented Mar 18, 2024

/dt

@oleiman
Copy link
Member Author

oleiman commented Mar 18, 2024

@oleiman oleiman force-pushed the security/acl-store-alloc branch 3 times, most recently from 22b394a to 4b6ce35 Compare March 21, 2024 17:10
@oleiman oleiman marked this pull request as ready for review March 21, 2024 17:22
Comment on lines +142 to +95
template<typename RefT>
static auto get_prefix_view(
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to warn users of this interface about any invalidation foot-guns since presumably they are not only hanging on to references into entries in the container, but now also iterators?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ugh, yeah that's a great point. This usage should be safe -- call chain has exactly one consumer (authorizer::authorized) and no yield points -- but stern comments here and on acl_store::find definitely a good idea.

Copy link
Member

Choose a reason for hiding this comment

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

i figured this was probably the case most of the acl/security code is in non-futurized code paths. but holding these across co_awaits is a constant footgun we encounter.

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed. Also I had btree_map erroneously filed away as iter stable. Thankfully reminded that's not the case in core panda the other day!

src/v/security/acl_store.h Show resolved Hide resolved
return _members_store;
});
})
| std::views::filter(std::forward<decltype(pred)>(pred))
Copy link
Member

Choose a reason for hiding this comment

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

confused about this one. it looks like you want std::move(pred) here without the forwarding?

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 definitely.

Comment on lines +162 to +217
template auth_result authorizer::authorized(
const kafka::transactional_id&,
acl_operation,
const acl_principal&,
const acl_host&) const;
Copy link
Member

Choose a reason for hiding this comment

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

header ❤️

This shaves a whole allocation off of each call to `authorizer::authorized`
both with and without roles.

The major consequence of this is that `acl_store.h` is included (transitively
via `authorizer.h`) in many places, so we're bleeding range view templates
throughout the source tree. Subsequent commits seek to isolate those templates
by breaking header dependencies.

Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
And explicitly instantiate, since the set of resource types
is bounded and small.

This breaks a rather large dependency on `role_store.h` throughout
the source tree.

Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
@oleiman
Copy link
Member Author

oleiman commented Mar 21, 2024

force push some comments and correct a perfect forward to a move in role_store

@dotnwat
Copy link
Member

dotnwat commented Mar 21, 2024

changes look good

@vbotbuildovich
Copy link
Collaborator

new failures in https://buildkite.com/redpanda/redpanda/builds/46595#018e639c-c2fe-44eb-a5cf-f9966cc97ba7:

"rptest.tests.read_replica_e2e_test.TestReadReplicaService.test_identical_lwms_after_delete_records.partition_count=5.cloud_storage_type=CloudStorageType.S3"

@oleiman
Copy link
Member Author

oleiman commented Mar 22, 2024

Copy link
Member

@BenPope BenPope left a comment

Choose a reason for hiding this comment

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

Looks great

@@ -188,8 +142,103 @@ class acl_store {
}
};

absl::btree_map<resource_pattern, acl_entry_set, resource_pattern_compare>
_acls;
using container_type = absl::
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: This commit would have been easier to review it was split into two steps:

  1. Pure refactor (code movement)
  2. Behaviour change

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, I have several regrets about the structure of this PR. Sorry for time suck 😕

@@ -28,6 +28,7 @@ v_cc_library(
krb5_configurator.cc
gssapi_principal_mapper.cc
role.cc
authorizer.cc
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: I usually try to keep this list sorted.

@@ -18,6 +18,9 @@ class authorizer;
class credential_store;
class ephemeral_credential_store;
class role_store;
class role;
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: I usually try to keep this list sorted

};

/*
* A lightweight container of references to ACL entries. An instance of this
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: * A lightweight view of ACL entries.

role_name_view, /* role_name */
std::function<const members_store_type&(void)>>& e,
const security::role_member& member) {
[](const role_accessor& e, const RoleMember auto& member) {
const auto [name, get_ms] = e;
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: copy not required (I changed the std::function to an ss::noncopyable_function)

Suggested change
const auto [name, get_ms] = e;
const auto& [name, get_ms] = e;

@@ -16,9 +16,9 @@
#include "model/fundamental.h"
#include "security/acl.h"
#include "security/acl_store.h"
#include "security/fwd.h"
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: These don't seem to be required:

#include "kafka/types.h"
#include "model/fundamental.h"

#include <assert.h>       

return auth_result::opt_acl_match(
principal, host, operation, resource_name, std::nullopt);
}
const acl_host& host) const;
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: You could also move auth_result::operator<<

@BenPope BenPope mentioned this pull request Mar 28, 2024
6 tasks
@oleiman
Copy link
Member Author

oleiman commented Mar 28, 2024

@BenPope - thanks for suggestions. I'm going to defer those to a fast follow to clear the log jam here.

@oleiman oleiman merged commit bc8a617 into redpanda-data:dev Mar 28, 2024
17 checks passed
for (auto& binding : bindings) {
auto& entries = _acls[binding.pattern()];
entries.insert(binding.entry());
entries.rehash();
Copy link
Member

Choose a reason for hiding this comment

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

rehash after the loop? seems like rehashing after each insert could be an expensive thing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure. fwiw, I didn't introduce this, I think it just shows up in the diff because I ripped acl_entry_set and git is...git. But I have a stack of minor changes coming and can stick that on top.

Copy link
Member

Choose a reason for hiding this comment

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

yeh nbd, just drive by noticing things. maybe i had added this long ago?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ya, I assume it was from the OG implementation. I looked at it again and I think we'd need a container or something to keep track of which entries matched, so maybe not much to be gained anyway

@oleiman oleiman mentioned this pull request Mar 28, 2024
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants