-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Authz] Operator privileges #196583
[Authz] Operator privileges #196583
Conversation
9aaa7e9
to
ae17618
Compare
0caf08d
to
b4fc800
Compare
Pinging @elastic/kibana-security (Team:Security) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Core changes LGTM
packages/core/security/core-security-common/src/authentication/authenticated_user.ts
Outdated
Show resolved
Hide resolved
getCurrentUser, | ||
getClusterClient: () => | ||
startServicesPromise.then(({ elasticsearch }) => elasticsearch.client), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
I don’t think we want to include these in our public setup
or start
contracts. Do we only need them for initAPIAuthorization
? If that’s the case, and since this functionality is now exposed through Core, can we pass these two services directly to AuthorizationService.setup without exposing them elsewhere?
const coreStartServices = core.getStartServices().then(([{ elasticsearch, security }]) => ({
elasticsearch,
security,
}));
this.authorizationSetup = this.authorizationService.setup({
coreStartServices, // or split into `getCurrentUser` and `getClusterClient\getSecurity`
....
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed this, those methods are no longer exposed in our public contracts
x-pack/plugins/security/server/authorization/api_authorization.ts
Outdated
Show resolved
Hide resolved
} | ||
|
||
const esClient = await getClusterClient(); | ||
const operatorPrivilegesConfig = await esClient.asInternalUser.transport.request<{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note
It's probably fine for now, but this is a hot path and if ever need to a high-performance endpoint to require operator privilege we might need to cache this response for some time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this call is too expensive to put in a hot path such as this. I think we should look into a way to cache this during startup. I recall SDHs where our frequent use of this endpoint elsewhere has caused performance issues on the cluster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit concerned that if we determine this only once during startup, admins will have to restart Kibana whenever this functionality is enabled or disabled in Elasticsearch. If we want to avoid that risk, we could either cache the result near the invocation point or implement a periodic background job to handle it (which is probably too much comparing to simple cache). Do you think requiring a Kibana restart along with Elasticsearch would be a reasonable approach (similar to how it works for ES, although for the config that doesn't belong to Kibana)?
Alternatively, we can require explicit operator flag/config for Kibana as well, that we can compare with the response from ES at startup time and bail if they don't match... Not sure if I like this option though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd share your concerns if this was a different ES setting. Operator Privileges are only used by our orchestrated offerings, and are configured via files that reside on each node. I do not expect the same cluster to switch modes at runtime, and we explicitly do not support direct usage of this feature:
https://www.elastic.co/guide/en/elasticsearch/reference/current/operator-privileges.html
Since we are in control over the configuration of Operator Privileges, it seems like it'd be sufficient to check this once on startup, and require a restart in the event the cluster somehow switched between using Operator Privileges and not using Operator Privileges.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We make a call to operator privileges config only on startup now
``` | ||
Operator privileges check is enforced only if operator privileges are enabled in the Elasticsearch configuration. | ||
For more information on operator privileges, refer to the [Operator privileges documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/operator-privileges.html). | ||
If operator privileges are disabled, we fall back to the superuser privileges check. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If operator privileges are disabled, we fall back to the superuser privileges check.
I know we discussed this here: #196271 (comment), but it seems we didn’t reach an agreement. This behavior deviates slightly from Elasticsearch’s approach, making it harder to reason about operator privileges across the Elastic project as a whole. This isn’t necessarily a bad thing, but we should explicitly state the benefits if we decide not to align with Elasticsearch’s treatment of operator privilege requirements.
Is there a reason we can’t or don't want to require developers to explicitly list additional privileges (beyond operator privileges) when exposing a Kibana endpoint to operator users? This would ensure privilege the same checks occur even if the operator user functionality is not enabled. The additional privilege could be superuser, but it could also be a role with fewer privileges if superuser access isn’t strictly necessary. This would discourage admins from granting superuser privileges to operator users unnecessarily.
The only potential issue I see with requiring additional privileges is if there’s a use case where no extra privilege check is needed at the API level because the handler solely relies on user-scoped Saved Objects or Elasticsearch services. If such a use case arises, we could explore solutions to handle it appropriately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we can’t or don't want to require developers to explicitly list additional privileges
I was for implementing it in the beginning and then thought to make it more feasible in terms of DX. That was a bit premature 😄
The additional privilege could be superuser, but it could also be a role with fewer privileges if superuser access isn’t strictly necessary. This would discourage admins from granting superuser privileges to operator users unnecessarily.
Agree, that makes sense
If there’s a use case where no extra privilege check is needed at the API level because the handler solely relies on user-scoped Saved Objects
Don't think such case has come up yet, but we can explore it when there is the need
Thanks for the feedback, will address the PR accordingly 👍
@elasticmachine merge upstream |
@elasticmachine merge upstream |
ACK: will review today |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, tested locally and everything works as expected, thanks! Just left a few nits, comments, and questions.
packages/core/http/core-http-router-server-internal/src/security_route_config_validator.ts
Outdated
Show resolved
Hide resolved
packages/core/http/core-http-router-server-internal/src/security_route_config_validator.ts
Show resolved
Hide resolved
@@ -138,6 +146,8 @@ export class AuthorizationService { | |||
checkPrivilegesWithRequest, | |||
getSpacesService | |||
), | |||
getCurrentUser, | |||
getSecurityConfig: () => esSecurityConfig, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: It feels like adding getSecurityConfig
and getCurrentUser
to authz
just to later pass it to the internal initAPIAuthorization
makes things slightly more complex, as we need to update types in multiple places, mocks, and ensure it doesn’t leak into our contracts. Is there any reason we can’t just pass these two properties directly to initAPIAuthorization
as additional arguments (and as the result I guess we won't need any changes in x-pack/packages/security/plugin_types_server
at all?)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed in 062ce7a 👍
@@ -52,8 +54,55 @@ export function initAPIAuthorization( | |||
} | |||
|
|||
const authz = security.authz as AuthzEnabled; | |||
const normalizeRequiredPrivileges = async ( | |||
privileges: AuthzEnabled['requiredPrivileges'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional nit: maybe we need to expose\export Privileges
from the Core, but I'm fine with what you have already.
type Privileges = Array<Privilege | PrivilegeSet>;
export interface AuthzEnabled {
requiredPrivileges: Privileges;
}
? { | ||
anyRequired: privilege.anyRequired, | ||
// @ts-ignore wrong types for `toSpliced` | ||
allRequired: privilege.allRequired?.toSpliced(operatorPrivilegeIndex, 1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL: toSpliced
is so handy!
x-pack/plugins/security/server/authorization/api_authorization.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/server/authorization/api_authorization.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/server/authorization/api_authorization.ts
Outdated
Show resolved
Hide resolved
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Unknown metric groupsAPI count
History
|
Starting backport for target branches: 8.x |
## Summary This PR adds support for explicit indication whether endpoint is restricted to operator only users. ### Context 1. If user has [all operator privileges](https://github.com/elastic/elasticsearch/blob/main/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/DefaultOperatorOnlyRegistry.java#L35-#L53) granted, but is not listed as operator in `operator_users.yml`, ES would throw an unauthorized error. 2. If user is listed as operator in `operator_users.yml`, but doesn't have necessary privileges granted, ES would throw an unauthorized error. 3. It’s not possible to determine if a user is operator via any ES API, i.e. `_has_privileges`. 4. If operator privileges are disabled we skip the the check for it, that's why we require to explicitly specify additional privileges to ensure that the route is protected even when operator privileges are disabled. ### Checklist - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios __Relates: https://github.com/elastic/kibana/issues/196271__ ### How to test 1. Add your user to the operators list https://github.com/elastic/kibana/blob/1bd81449242a1ab57e82c211808753e82f25c92c/packages/kbn-es/src/serverless_resources/operator_users.yml#L4 or use existing user from the list to log in. 2. Run ES and Kibana serverless 3. Change any endpoint or create a new one with the following security config ``` security: { authz: { requiredPrivileges: [ReservedPrivilegesSet.operator], }, }, ``` 4. Check with enabled and disabled operator privileges (set `xpack.security.operator_privileges.enabled`) ## Release Note Added support for explicit indication whether endpoint is restricted to operator only users at the route definition level. --------- Co-authored-by: Elastic Machine <[email protected]> (cherry picked from commit 52dd7e1)
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
# Backport This will backport the following commits from `main` to `8.x`: - [[Authz] Operator privileges (#196583)](#196583) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Elena Shostak","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-12-12T22:55:04Z","message":"[Authz] Operator privileges (#196583)\n\n## Summary\r\n\r\nThis PR adds support for explicit indication whether endpoint is\r\nrestricted to operator only users.\r\n\r\n### Context\r\n1. If user has [all operator\r\nprivileges](https://github.com/elastic/elasticsearch/blob/main/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/DefaultOperatorOnlyRegistry.java#L35-#L53)\r\ngranted, but is not listed as operator in `operator_users.yml`, ES would\r\nthrow an unauthorized error.\r\n2. If user is listed as operator in `operator_users.yml`, but doesn't\r\nhave necessary privileges granted, ES would throw an unauthorized error.\r\n3. It’s not possible to determine if a user is operator via any ES API,\r\ni.e. `_has_privileges`.\r\n4. If operator privileges are disabled we skip the the check for it,\r\nthat's why we require to explicitly specify additional privileges to\r\nensure that the route is protected even when operator privileges are\r\ndisabled.\r\n\r\n### Checklist\r\n\r\n- [x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n__Relates: https://github.com/elastic/kibana/issues/196271__\r\n\r\n### How to test\r\n\r\n1. Add your user to the operators list\r\nhttps://github.com/elastic/kibana/blob/1bd81449242a1ab57e82c211808753e82f25c92c/packages/kbn-es/src/serverless_resources/operator_users.yml#L4\r\nor use existing user from the list to log in.\r\n2. Run ES and Kibana serverless\r\n3. Change any endpoint or create a new one with the following security\r\nconfig\r\n```\r\n security: {\r\n authz: {\r\n requiredPrivileges: [ReservedPrivilegesSet.operator],\r\n },\r\n },\r\n```\r\n4. Check with enabled and disabled operator privileges (set\r\n`xpack.security.operator_privileges.enabled`)\r\n\r\n## Release Note\r\nAdded support for explicit indication whether endpoint is restricted to\r\noperator only users at the route definition level.\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <[email protected]>","sha":"52dd7e17c4ee1bcada352b142532ca534002e8d5","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:Security","Feature:Security/Authorization","v9.0.0","backport:prev-minor"],"title":"[Authz] Operator privileges","number":196583,"url":"https://github.com/elastic/kibana/pull/196583","mergeCommit":{"message":"[Authz] Operator privileges (#196583)\n\n## Summary\r\n\r\nThis PR adds support for explicit indication whether endpoint is\r\nrestricted to operator only users.\r\n\r\n### Context\r\n1. If user has [all operator\r\nprivileges](https://github.com/elastic/elasticsearch/blob/main/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/DefaultOperatorOnlyRegistry.java#L35-#L53)\r\ngranted, but is not listed as operator in `operator_users.yml`, ES would\r\nthrow an unauthorized error.\r\n2. If user is listed as operator in `operator_users.yml`, but doesn't\r\nhave necessary privileges granted, ES would throw an unauthorized error.\r\n3. It’s not possible to determine if a user is operator via any ES API,\r\ni.e. `_has_privileges`.\r\n4. If operator privileges are disabled we skip the the check for it,\r\nthat's why we require to explicitly specify additional privileges to\r\nensure that the route is protected even when operator privileges are\r\ndisabled.\r\n\r\n### Checklist\r\n\r\n- [x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n__Relates: https://github.com/elastic/kibana/issues/196271__\r\n\r\n### How to test\r\n\r\n1. Add your user to the operators list\r\nhttps://github.com/elastic/kibana/blob/1bd81449242a1ab57e82c211808753e82f25c92c/packages/kbn-es/src/serverless_resources/operator_users.yml#L4\r\nor use existing user from the list to log in.\r\n2. Run ES and Kibana serverless\r\n3. Change any endpoint or create a new one with the following security\r\nconfig\r\n```\r\n security: {\r\n authz: {\r\n requiredPrivileges: [ReservedPrivilegesSet.operator],\r\n },\r\n },\r\n```\r\n4. Check with enabled and disabled operator privileges (set\r\n`xpack.security.operator_privileges.enabled`)\r\n\r\n## Release Note\r\nAdded support for explicit indication whether endpoint is restricted to\r\noperator only users at the route definition level.\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <[email protected]>","sha":"52dd7e17c4ee1bcada352b142532ca534002e8d5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/196583","number":196583,"mergeCommit":{"message":"[Authz] Operator privileges (#196583)\n\n## Summary\r\n\r\nThis PR adds support for explicit indication whether endpoint is\r\nrestricted to operator only users.\r\n\r\n### Context\r\n1. If user has [all operator\r\nprivileges](https://github.com/elastic/elasticsearch/blob/main/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/DefaultOperatorOnlyRegistry.java#L35-#L53)\r\ngranted, but is not listed as operator in `operator_users.yml`, ES would\r\nthrow an unauthorized error.\r\n2. If user is listed as operator in `operator_users.yml`, but doesn't\r\nhave necessary privileges granted, ES would throw an unauthorized error.\r\n3. It’s not possible to determine if a user is operator via any ES API,\r\ni.e. `_has_privileges`.\r\n4. If operator privileges are disabled we skip the the check for it,\r\nthat's why we require to explicitly specify additional privileges to\r\nensure that the route is protected even when operator privileges are\r\ndisabled.\r\n\r\n### Checklist\r\n\r\n- [x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n__Relates: https://github.com/elastic/kibana/issues/196271__\r\n\r\n### How to test\r\n\r\n1. Add your user to the operators list\r\nhttps://github.com/elastic/kibana/blob/1bd81449242a1ab57e82c211808753e82f25c92c/packages/kbn-es/src/serverless_resources/operator_users.yml#L4\r\nor use existing user from the list to log in.\r\n2. Run ES and Kibana serverless\r\n3. Change any endpoint or create a new one with the following security\r\nconfig\r\n```\r\n security: {\r\n authz: {\r\n requiredPrivileges: [ReservedPrivilegesSet.operator],\r\n },\r\n },\r\n```\r\n4. Check with enabled and disabled operator privileges (set\r\n`xpack.security.operator_privileges.enabled`)\r\n\r\n## Release Note\r\nAdded support for explicit indication whether endpoint is restricted to\r\noperator only users at the route definition level.\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <[email protected]>","sha":"52dd7e17c4ee1bcada352b142532ca534002e8d5"}}]}] BACKPORT--> Co-authored-by: Elena Shostak <[email protected]>
Summary
This PR adds support for explicit indication whether endpoint is restricted to operator only users.
Context
operator_users.yml
, ES would throw an unauthorized error.operator_users.yml
, but doesn't have necessary privileges granted, ES would throw an unauthorized error._has_privileges
.Checklist
Relates: #196271
How to test
kibana/packages/kbn-es/src/serverless_resources/operator_users.yml
Line 4 in 1bd8144
xpack.security.operator_privileges.enabled
)Release Note
Added support for explicit indication whether endpoint is restricted to operator only users at the route definition level.