Skip to content

Commit

Permalink
Provide sensible defaults for `xpack.security.session.{lifespan|idleT…
Browse files Browse the repository at this point in the history
…imeout}`.
  • Loading branch information
azasypkin committed Jul 19, 2021
1 parent e9988b1 commit 5eaf472
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 59 deletions.
6 changes: 3 additions & 3 deletions docs/settings/security-settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ You can configure the following settings in the `kibana.yml` file.

|[[xpack-session-idleTimeout]] `xpack.security.session.idleTimeout` {ess-icon}
| Ensures that user sessions will expire after a period of inactivity. This and <<xpack-session-lifespan,`xpack.security.session.lifespan`>> are both
highly recommended. You can also specify this setting for <<xpack-security-provider-session-idleTimeout, every provider separately>>. If this is _not_ set or set to `0`, then sessions will never expire due to inactivity. By default, this setting is not set.
highly recommended. You can also specify this setting for <<xpack-security-provider-session-idleTimeout, every provider separately>>. If this is set to `0`, then sessions will never expire due to inactivity. By default, this value is 1 hour.

2+a|
[TIP]
Expand All @@ -281,8 +281,8 @@ Use a string of `<count>[ms\|s\|m\|h\|d\|w\|M\|Y]` (e.g. '20m', '24h', '7d', '1w

|[[xpack-session-lifespan]] `xpack.security.session.lifespan` {ess-icon}
| Ensures that user sessions will expire after the defined time period. This behavior is also known as an "absolute timeout". If
this is _not_ set or set to `0`, user sessions could stay active indefinitely. This and <<xpack-session-idleTimeout, `xpack.security.session.idleTimeout`>> are both highly
recommended. You can also specify this setting for <<xpack-security-provider-session-lifespan, every provider separately>>. By default, this setting is not set.
this is set to `0`, user sessions could stay active indefinitely. This and <<xpack-session-idleTimeout, `xpack.security.session.idleTimeout`>> are both highly
recommended. You can also specify this setting for <<xpack-security-provider-session-lifespan, every provider separately>>. By default, this value is 30 days.

2+a|
[TIP]
Expand Down
8 changes: 4 additions & 4 deletions docs/user/security/session-management.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ To manage user sessions programmatically, {kib} exposes <<session-management-api
==== Session idle timeout

You can use `xpack.security.session.idleTimeout` to expire sessions after a period of inactivity. This and `xpack.security.session.lifespan` are both highly recommended.
By default, sessions don't expire because of inactivity. To define a sliding session expiration, set the property in the `kibana.yml` configuration file. The idle timeout is formatted as a duration of `<count>[ms|s|m|h|d|w|M|Y]` (e.g. '20m', '24h', '7d', '1w'). For example, set the idle timeout to expire sessions after 1 hour of inactivity:
By default, sessions expire after 1 hour of inactivity. To define another value for a sliding session expiration, set the property in the `kibana.yml` configuration file. The idle timeout is formatted as a duration of `<count>[ms|s|m|h|d|w|M|Y]` (e.g. '20m', '24h', '7d', '1w'). For example, set the idle timeout to expire sessions after 30 minutes of inactivity:

--
[source,yaml]
--------------------------------------------------------------------------------
xpack.security.session.idleTimeout: "1h"
xpack.security.session.idleTimeout: "30m"
--------------------------------------------------------------------------------
--

[[session-lifespan]]
==== Session lifespan

You can use `xpack.security.session.lifespan` to configure the maximum session duration or "lifespan" -- also known as the "absolute timeout". This and `xpack.security.session.idleTimeout` are both highly recommended. By default, sessions don't have a fixed lifespan, and if an idle timeout is defined, a session can still be extended indefinitely. To define a maximum session lifespan, set the property in the `kibana.yml` configuration file. The lifespan is formatted as a duration of `<count>[ms|s|m|h|d|w|M|Y]` (e.g. '20m', '24h', '7d', '1w'). For example, set the lifespan to expire sessions after 30 days:
You can use `xpack.security.session.lifespan` to configure the maximum session duration or "lifespan" -- also known as the "absolute timeout". This and `xpack.security.session.idleTimeout` are both highly recommended. By default, a maximum session lifespan is 30 days. To define another lifespan, set the property in the `kibana.yml` configuration file. The lifespan is formatted as a duration of `<count>[ms|s|m|h|d|w|M|Y]` (e.g. '20m', '24h', '7d', '1w'). For example, set the lifespan to expire sessions after 7 days:

--
[source,yaml]
--------------------------------------------------------------------------------
xpack.security.session.lifespan: "30d"
xpack.security.session.lifespan: "7d"
--------------------------------------------------------------------------------
--

Expand Down
54 changes: 30 additions & 24 deletions x-pack/plugins/security/server/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ describe('config schema', () => {
"secureCookies": false,
"session": Object {
"cleanupInterval": "PT1H",
"idleTimeout": "PT1H",
"lifespan": "P30D",
},
}
`);
Expand Down Expand Up @@ -110,6 +112,8 @@ describe('config schema', () => {
"secureCookies": false,
"session": Object {
"cleanupInterval": "PT1H",
"idleTimeout": "PT1H",
"lifespan": "P30D",
},
}
`);
Expand Down Expand Up @@ -158,6 +162,8 @@ describe('config schema', () => {
"secureCookies": false,
"session": Object {
"cleanupInterval": "PT1H",
"idleTimeout": "PT1H",
"lifespan": "P30D",
},
}
`);
Expand Down Expand Up @@ -1615,11 +1621,11 @@ describe('createConfig()', () => {
it('returns default values if neither global nor provider specific settings are set', async () => {
expect(createMockConfig().session.getExpirationTimeouts({ type: 'basic', name: 'basic1' }))
.toMatchInlineSnapshot(`
Object {
"idleTimeout": null,
"lifespan": null,
}
`);
Object {
"idleTimeout": "PT1H",
"lifespan": "P30D",
}
`);
});

it('correctly handles explicitly disabled global settings', async () => {
Expand Down Expand Up @@ -1653,23 +1659,23 @@ describe('createConfig()', () => {
name: 'basic1',
})
).toMatchInlineSnapshot(`
Object {
"idleTimeout": "PT0.123S",
"lifespan": null,
}
`);
Object {
"idleTimeout": "PT0.123S",
"lifespan": "P30D",
}
`);

expect(
createMockConfig({ session: { lifespan: 456 } }).session.getExpirationTimeouts({
type: 'basic',
name: 'basic1',
})
).toMatchInlineSnapshot(`
Object {
"idleTimeout": null,
"lifespan": "PT0.456S",
}
`);
Object {
"idleTimeout": "PT1H",
"lifespan": "PT0.456S",
}
`);

expect(
createMockConfig({
Expand All @@ -1692,7 +1698,7 @@ describe('createConfig()', () => {
).toMatchInlineSnapshot(`
Object {
"idleTimeout": "PT0.123S",
"lifespan": null,
"lifespan": "P30D",
}
`);

Expand All @@ -1703,7 +1709,7 @@ describe('createConfig()', () => {
})
).toMatchInlineSnapshot(`
Object {
"idleTimeout": null,
"idleTimeout": "PT1H",
"lifespan": "PT0.456S",
}
`);
Expand Down Expand Up @@ -1734,14 +1740,14 @@ describe('createConfig()', () => {
.toMatchInlineSnapshot(`
Object {
"idleTimeout": "PT0.321S",
"lifespan": null,
"lifespan": "P30D",
}
`);
expect(configWithoutGlobal.session.getExpirationTimeouts({ type: 'saml', name: 'saml1' }))
.toMatchInlineSnapshot(`
Object {
"idleTimeout": "PT5M32.211S",
"lifespan": null,
"lifespan": "P30D",
}
`);

Expand All @@ -1758,14 +1764,14 @@ describe('createConfig()', () => {
.toMatchInlineSnapshot(`
Object {
"idleTimeout": "PT0.321S",
"lifespan": null,
"lifespan": "P30D",
}
`);
expect(configWithGlobal.session.getExpirationTimeouts({ type: 'saml', name: 'saml1' }))
.toMatchInlineSnapshot(`
Object {
"idleTimeout": "PT5M32.211S",
"lifespan": null,
"lifespan": "P30D",
}
`);
});
Expand All @@ -1783,14 +1789,14 @@ describe('createConfig()', () => {
expect(configWithoutGlobal.session.getExpirationTimeouts({ type: 'basic', name: 'basic1' }))
.toMatchInlineSnapshot(`
Object {
"idleTimeout": null,
"idleTimeout": "PT1H",
"lifespan": "PT0.654S",
}
`);
expect(configWithoutGlobal.session.getExpirationTimeouts({ type: 'saml', name: 'saml1' }))
.toMatchInlineSnapshot(`
Object {
"idleTimeout": null,
"idleTimeout": "PT1H",
"lifespan": "PT11M5.544S",
}
`);
Expand All @@ -1807,7 +1813,7 @@ describe('createConfig()', () => {
expect(configWithGlobal.session.getExpirationTimeouts({ type: 'basic', name: 'basic1' }))
.toMatchInlineSnapshot(`
Object {
"idleTimeout": null,
"idleTimeout": "PT1H",
"lifespan": "PT0.654S",
}
`);
Expand Down
23 changes: 7 additions & 16 deletions x-pack/plugins/security/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,12 @@ export const ConfigSchema = schema.object({
schema.string({ minLength: 32, defaultValue: 'a'.repeat(32) })
),
session: schema.object({
idleTimeout: schema.maybe(schema.oneOf([schema.duration(), schema.literal(null)])),
lifespan: schema.maybe(schema.oneOf([schema.duration(), schema.literal(null)])),
idleTimeout: schema.oneOf([schema.duration(), schema.literal(null)], {
defaultValue: schema.duration().validate('1h'),
}),
lifespan: schema.oneOf([schema.duration(), schema.literal(null)], {
defaultValue: schema.duration().validate('30d'),
}),
cleanupInterval: schema.duration({
defaultValue: '1h',
validate(value) {
Expand Down Expand Up @@ -385,29 +389,16 @@ export function createConfig(
}

function getSessionConfig(session: RawConfigType['session'], providers: ProvidersConfigType) {
const defaultAnonymousSessionLifespan = schema.duration().validate('30d');
return {
cleanupInterval: session.cleanupInterval,
getExpirationTimeouts({ type, name }: AuthenticationProvider) {
// Both idle timeout and lifespan from the provider specific session config can have three
// possible types of values: `Duration`, `null` and `undefined`. The `undefined` type means that
// provider doesn't override session config and we should fall back to the global one instead.
const providerSessionConfig = providers[type as keyof ProvidersConfigType]?.[name]?.session;

// We treat anonymous sessions differently since users can create them without realizing it. This may lead to a
// non controllable amount of sessions stored in the session index. To reduce the impact we set a 30 days lifespan
// for the anonymous sessions in case neither global nor provider specific lifespan is configured explicitly.
// We can remove this code once https://github.com/elastic/kibana/issues/68885 is resolved.
const providerLifespan =
type === 'anonymous' &&
providerSessionConfig?.lifespan === undefined &&
session.lifespan === undefined
? defaultAnonymousSessionLifespan
: providerSessionConfig?.lifespan;

const [idleTimeout, lifespan] = [
[session.idleTimeout, providerSessionConfig?.idleTimeout],
[session.lifespan, providerLifespan],
[session.lifespan, providerSessionConfig?.lifespan],
].map(([globalTimeout, providerTimeout]) => {
const timeout = providerTimeout === undefined ? globalTimeout ?? null : providerTimeout;
return timeout && timeout.asMilliseconds() > 0 ? timeout : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ describe('Session', () => {
session = new Session({
logger: loggingSystemMock.createLogger(),
config: createConfig(
ConfigSchema.validate({ session: { idleTimeout: 123 } }),
ConfigSchema.validate({ session: { idleTimeout: 123, lifespan: null } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
Expand Down Expand Up @@ -398,7 +398,7 @@ describe('Session', () => {
session = new Session({
logger: loggingSystemMock.createLogger(),
config: createConfig(
ConfigSchema.validate({ session: { lifespan } }),
ConfigSchema.validate({ session: { idleTimeout: null, lifespan } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
Expand Down Expand Up @@ -472,9 +472,11 @@ describe('Session', () => {

session = new Session({
logger: loggingSystemMock.createLogger(),
config: createConfig(ConfigSchema.validate({}), loggingSystemMock.createLogger(), {
isTLSEnabled: false,
}),
config: createConfig(
ConfigSchema.validate({ session: { idleTimeout: null, lifespan: null } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
sessionCookie: mockSessionCookie,
sessionIndex: mockSessionIndex,
});
Expand Down Expand Up @@ -527,7 +529,7 @@ describe('Session', () => {
session = new Session({
logger: loggingSystemMock.createLogger(),
config: createConfig(
ConfigSchema.validate({ session: { idleTimeout: 123 } }),
ConfigSchema.validate({ session: { idleTimeout: 123, lifespan: null } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
Expand Down Expand Up @@ -718,7 +720,7 @@ describe('Session', () => {
session = new Session({
logger: loggingSystemMock.createLogger(),
config: createConfig(
ConfigSchema.validate({ session: { lifespan } }),
ConfigSchema.validate({ session: { idleTimeout: null, lifespan } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ describe('Session index', () => {
const sessionIndexOptions = {
logger: loggingSystemMock.createLogger(),
kibanaIndexName: '.kibana_some_tenant',
config: createConfig(ConfigSchema.validate({}), loggingSystemMock.createLogger(), {
isTLSEnabled: false,
}),
config: createConfig(
ConfigSchema.validate({ session: { idleTimeout: null, lifespan: null } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
elasticsearchClient: mockElasticsearchClient,
};

Expand Down Expand Up @@ -239,7 +241,7 @@ describe('Session index', () => {
logger: loggingSystemMock.createLogger(),
kibanaIndexName: '.kibana_some_tenant',
config: createConfig(
ConfigSchema.validate({ session: { lifespan: 456 } }),
ConfigSchema.validate({ session: { idleTimeout: null, lifespan: 456 } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
Expand Down Expand Up @@ -315,7 +317,7 @@ describe('Session index', () => {
logger: loggingSystemMock.createLogger(),
kibanaIndexName: '.kibana_some_tenant',
config: createConfig(
ConfigSchema.validate({ session: { idleTimeout } }),
ConfigSchema.validate({ session: { idleTimeout, lifespan: null } }),
loggingSystemMock.createLogger(),
{ isTLSEnabled: false }
),
Expand Down

0 comments on commit 5eaf472

Please sign in to comment.