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

Uses refresh=false for creating, updating, and invalidating user sessions #151800

Merged

Conversation

jeramysoucy
Copy link
Contributor

@jeramysoucy jeramysoucy commented Feb 21, 2023

closes #149338

Summary

Sets refresh parameter to false in session create, update, and invalidate. Previously refresh was set to 'wait_for' (or 'true' in the case of invalidating by query).

Tests

Several unit tests and functional tests have been updated to reflect the change in test snapshots and to manually refresh the session index in order to complete testing. The bulk of the test changes reside in the concurrent session limit suite.

Flaky Test Runner for relevant test suites: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1984

Documentation

Adds a note to the session-management ascii doc to document a known limitation of enforcing the concurrent sessions limit...

NOTE: Due to the rate at which session information is refreshed, there might be a few seconds where the concurrent session limit is not enforced.
This is something to consider for use cases where it is common to create multiple sessions simultaneously.

…Adds delays in tests to compensate for removing refresh wait_for.
@jeramysoucy jeramysoucy added Team:Security Team focused on: Auth, Users, Roles, Spaces, Audit Logging, and more! Feature:Security/Session Management Platform Security - Session Management v8.8.0 release_note:skip Skip the PR/issue when compiling release notes labels Feb 21, 2023
@@ -217,6 +223,9 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'xxx')
.set('Cookie', basicSessionCookie.cookieString());
statusCodes.push(statusCode);
await setTimeoutAsync(1000);
await es.indices.refresh({ index: '.kibana_security_session*' });
await setTimeoutAsync(2000);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@azasypkin This was the only spot where just the index refresh was not enough. I had to put the static delays back in. Curious if you have any ideas on why the refresh wouldn't work here as it does elsewhere.

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm, I have no idea to be honest, but let me think a bit.

Copy link
Member

Choose a reason for hiding this comment

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

By the way shouldn't you call this refresh before this for loop, right after you created sessions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right...that was a bit silly of me. I had moved the delays around previously and sort of lost the plot on this one. In the right spot it works 😅 . Thanks!

@jeramysoucy
Copy link
Contributor Author

jeramysoucy commented Feb 21, 2023

EDIT: not sure what happened to the link, but I fixed it.

@azasypkin We also use 'refresh: wait_for' (and 'refresh: true') in the invalidate method. Should we look at these cases as well?

// We don't specify primary term and sequence number as delete should always take precedence
// over any updates that could happen in the meantime.
const { statusCode } = await this.options.elasticsearchClient.delete(
  { id: filter.sid, index: this.aliasName, refresh: 'wait_for' },
  { ignore: [404], meta: true }
);

...

const response = await this.options.elasticsearchClient.deleteByQuery({
  index: this.aliasName,
  refresh: true,
  body: { query: deleteQuery }
});

@azasypkin
Copy link
Member

azasypkin commented Feb 22, 2023

@azasypkin We also use 'refresh: wait_for' (and 'refresh: true') in the invalidate method. Should we look at these cases as well?

Good point! These aren't in the hot path, but I think it'd still make sense to look at these as well.

@@ -208,6 +213,8 @@ export default function ({ getService }: FtrProviderContext) {
Array.from({ length: 10 }).map(() => loginWithBasic(testUser))
);

await es.indices.refresh({ index: '.kibana_security_session*' });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The index needs to be refreshed in order for the session limit to be enforced. If we don't use 'wait_for', it is unclear that we can properly enforce session limits for concurrent sessions that are created at the same time. Is this a real use case? Do we want to support it?

Copy link
Member

Choose a reason for hiding this comment

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

The index needs to be refreshed in order for the session limit to be enforced. If we don't use 'wait_for', it is unclear that we can properly enforce session limits for concurrent sessions that are created at the same time

That's correct, but we have a 1s refresh interval configured for the index. That means that in the majority of the cases there will be just a small window (up to a few seconds) where the limit could be bypassed. Even though the problem might be more apparent for highly loaded clusters, I'd still say it's an acceptable tradeoff, at least for the initial release.

On the other hand, it's a relatively small and low-risk change to use refresh=wait_for only when concurrent session limit is configured, but I'm wondering if it'd make sense to make it only when/if we learn that it's not what our customers and users are comfortable with. What do you think @jeramysoucy @legrego @arisonl?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we know of significant real life use cases where this will be a problem, then I would say let's default to using wait_for if concurrent session limits are configured. Otherwise, I like moving forward with refresh=false for now and potentially making wait_for a future option for flexibility should the need arise.

Copy link
Member

Choose a reason for hiding this comment

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

If we know of significant real life use cases where this will be a problem, then I would say let's default to using wait_for if concurrent session limits are configured. Otherwise, I like moving forward with refresh=false for now and potentially making wait_for a future option for flexibility should the need arise.

I'm comfortable with this, but I think we should call this out as a limitation in our docs for this feature. Otherwise, a security researcher could reasonably assert that this control is not working as intended.

Copy link
Contributor

@arisonl arisonl Feb 22, 2023

Choose a reason for hiding this comment

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

I would like to better understand the details of the underlying technical issue (we'll discuss offline), but in principle I agree that a small (a few seconds) deviation from the expected behavior is not an issue for this use case, if documented. However, there is this reference: "in the majority of the cases there will be just a small window" which worries me a bit. Is there a chance that we our off by more than just a few seconds?

Copy link
Member

Choose a reason for hiding this comment

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

Just so I fully understand the problem. If we use refresh=wait_for, we are essentially synchronizing the response from the request Persist session in the diagram below, correct?

Yeah, it's close! The only difference is that we don't search for other sessions during login, but whenever the session is retrieved in the subsequent requests to make sure the session limitation isn't bypassed with tons of concurrent logins. But the idea is the same.

AFAIK, ES is looking at ways to make the data available for search even before the refresh interval has kicked in. Once that's complete, we may be able to completely migrate to refresh=wait_for. partying_face

Oh, that would be great, thanks for sharing! Is it something ES team has on the near-term roadmap (before Oct 2023)?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not entirely sure about ES priorities in this regard.

@kobelb, @lukeelmers, Are you aware of an approx ETA for the Search after Write initiative?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure of their current status on this, however the internal issue (ES-4076) seems to indicate May 2023.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Regarding augmenting our documentation to cover the known limitations of this change, do we want to make the note where we document the concurrent limit configuration option? https://www.elastic.co/guide/en/kibana/master/xpack-security-session-management.html#session-max-sessions

Copy link
Member

Choose a reason for hiding this comment

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

Regarding augmenting our documentation to cover the known limitations of this change, do we want to make the note where we document the concurrent limit configuration option?

Yeah, it's worth mentioning there.

@jeramysoucy
Copy link
Contributor Author

@azasypkin We also use 'refresh: wait_for' (and 'refresh: true') in the invalidate method. Should we look at these cases as well?

Good point! These aren't in the hot path, but I think it'd still make sense to look at these as well.

I updated the invalidate method to use refresh=false as well, but had to move the manual index refresh in the concurrent session limit test suite. The call to get within the loop internally calls invalidate, so the index needed to be refreshed after each call.

@jeramysoucy jeramysoucy marked this pull request as ready for review February 23, 2023 16:12
@jeramysoucy jeramysoucy requested a review from a team as a code owner February 23, 2023 16:12
@elasticmachine
Copy link
Contributor

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

@jeramysoucy jeramysoucy changed the title Uses refresh=false for creating and updating user sessions Uses refresh=false for creating, updating, and invalidating user sessions Feb 23, 2023
@jeramysoucy jeramysoucy requested a review from gchaps March 7, 2023 17:06
@jeramysoucy
Copy link
Contributor Author

I've added a note to the session management docs. I think this is now ready for a final approval review @elastic/kibana-security.

Copy link
Contributor

@gchaps gchaps left a comment

Choose a reason for hiding this comment

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

Approved with a small suggestion for the first sentence.

@jeramysoucy jeramysoucy requested a review from azasypkin March 8, 2023 21:41
@azasypkin
Copy link
Member

ACK: Will review later today or tomorrow.

Copy link
Member

@azasypkin azasypkin 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, thank you!

--
[source,yaml]
--------------------------------------------------------------------------------
xpack.security.session.сoncurrentSessions:
xpack.security.session.concurrentSessions:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

replaced cyrillic 'c' with latin 'c'

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Unknown metric groups

ESLint disabled line counts

id before after diff
securitySolution 434 437 +3

Total ESLint disabled count

id before after diff
securitySolution 514 517 +3

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@jeramysoucy jeramysoucy merged commit ba6058c into elastic:main Mar 10, 2023
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Mar 10, 2023
@jeramysoucy jeramysoucy deleted the use-refresh-false-for-user-sessions branch March 10, 2023 18:18
bmorelli25 pushed a commit to bmorelli25/kibana that referenced this pull request Mar 10, 2023
…ions (elastic#151800)

closes elastic#149338

## Summary
Sets refresh parameter to false in session create, update, and
invalidate. Previously refresh was set to 'wait_for' (or 'true' in the
case of invalidating by query).

### Tests
Several unit tests and functional tests have been updated to reflect the
change in test snapshots and to manually refresh the session index in
order to complete testing. The bulk of the test changes reside in the
[concurrent session limit
suite](https://github.com/elastic/kibana/blob/66a43be28ca653809996b53198fc6fae2ee726f8/x-pack/test/security_api_integration/tests/session_concurrent_limit/global_limit.ts).

Flaky Test Runner for relevant test suites:
https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1984

### Documentation
Adds a note to the session-management ascii doc to document a known
limitation of enforcing the concurrent sessions limit...
```
NOTE: Due to the rate at which session information is refreshed, there might be a few seconds where the concurrent session limit is not enforced.
This is something to consider for use cases where it is common to create multiple sessions simultaneously.
```

---------

Co-authored-by: gchaps <[email protected]>
kc13greiner added a commit that referenced this pull request Aug 21, 2023
## Summary

Specifying a `refresh_interval` below 5s is no longer allowed with es
serverless. This PR removes the explicit `refresh_interval` from the
session index.

Work done in #151800 makes
specifying a `refresh_interval` unnecessary.

## Flaky Test Runner
[Session Tests x50
ea](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2932)
🟢

Co-authored-by: Kibana Machine <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Security/Session Management Platform Security - Session Management release_note:skip Skip the PR/issue when compiling release notes Team:Security Team focused on: Auth, Users, Roles, Spaces, Audit Logging, and more! v8.8.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use ?refresh=false while creating and updating user sessions
10 participants