Skip to content

Commit 90285ee

Browse files
Deprecate timeout.tcp_read AD/LDAP realm setting (#47305)
The timeout.tcp_read AD/LDAP realm setting, despite the low-level allusion, controls the time interval the realms wait for a response for a query (search or bind). If the connection to the server is synchronous (un-pooled) the response timeout is analogous to the tcp read timeout. But the tcp read timeout is irrelevant in the common case of a pooled connection (when a Bind DN is specified). The timeout.tcp_read qualifier is hereby deprecated in favor of timeout.response. In addition, the default value for both timeout.tcp_read and timeout.response is that of timeout.ldap_search, instead of the 5s (but the default for timeout.ldap_search is still 5s). The timeout.ldap_search defines the server-controlled timeout of a search request. There is no practical use case to have a smaller tcp_read timeout compared to ldap_search (in this case the request would time-out on the client but continue to be processed on the server). The proposed change aims to simplify configuration so that the more common configuration change, adjusting timeout.ldap_search up, has the expected result (no timeout during searches) without any additional modifications. Closes #46028
1 parent ba3051a commit 90285ee

File tree

6 files changed

+105
-15
lines changed

6 files changed

+105
-15
lines changed

docs/reference/settings/security-settings.asciidoc

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,19 @@ An `s` at the end indicates seconds, or `ms` indicates milliseconds.
442442
Defaults to `5s` (5 seconds ).
443443

444444
`timeout.tcp_read`::
445-
The TCP read timeout period after establishing an LDAP connection.
446-
An `s` at the end indicates seconds, or `ms` indicates milliseconds.
447-
Defaults to `5s` (5 seconds ).
445+
deprecated[7.7] The TCP read timeout period after establishing an LDAP
446+
connection. This is equivalent to and is deprecated in favor of
447+
`timeout.response` and they cannot be used simultaneously. An `s` at the end
448+
indicates seconds, or `ms` indicates milliseconds.
449+
450+
`timeout.response`::
451+
The time interval to wait for the response from the LDAP server. An `s` at the
452+
end indicates seconds, or `ms` indicates milliseconds. Defaults to the value of
453+
`timeout.ldap_search`.
448454

449455
`timeout.ldap_search`::
450-
The LDAP Server enforced timeout period for an LDAP search.
456+
The timeout period for an LDAP search. The value is specified in the request
457+
and is enforced by the receiving LDAP Server.
451458
An `s` at the end indicates seconds, or `ms` indicates milliseconds.
452459
Defaults to `5s` (5 seconds ).
453460

@@ -691,12 +698,20 @@ An `s` at the end indicates seconds, or `ms` indicates milliseconds.
691698
Defaults to `5s` (5 seconds ).
692699

693700
`timeout.tcp_read`::
694-
The TCP read timeout period after establishing an LDAP connection.
695-
An `s` at the end indicates seconds, or `ms` indicates milliseconds.
696-
Defaults to `5s` (5 seconds ).
701+
deprecated[7.7] The TCP read timeout period after establishing an LDAP
702+
connection. This is equivalent to and is deprecated in favor of
703+
`timeout.response` and they cannot be used simultaneously. An `s` at the end
704+
indicates seconds, or `ms` indicates milliseconds. Defaults to the value of
705+
`timeout.ldap_search`.
706+
707+
`timeout.response`::
708+
The time interval to wait for the response from the AD server. An `s` at the
709+
end indicates seconds, or `ms` indicates milliseconds. Defaults to the value of
710+
`timeout.ldap_search`.
697711

698712
`timeout.ldap_search`::
699-
The LDAP Server enforced timeout period for an LDAP search.
713+
The timeout period for an LDAP search. The value is specified in the request
714+
and is enforced by the receiving LDAP Server.
700715
An `s` at the end indicates seconds, or `ms` indicates milliseconds.
701716
Defaults to `5s` (5 seconds ).
702717

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/ldap/support/SessionFactorySettings.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ public final class SessionFactorySettings {
2525
public static final Function<String, Setting.AffixSetting<TimeValue>> TIMEOUT_TCP_CONNECTION_SETTING = RealmSettings.affixSetting(
2626
"timeout.tcp_connect", key -> Setting.timeSetting(key, TIMEOUT_DEFAULT, Setting.Property.NodeScope));
2727

28-
public static final Function<String, Setting.AffixSetting<TimeValue>> TIMEOUT_TCP_READ_SETTING = RealmSettings.affixSetting(
29-
"timeout.tcp_read", key -> Setting.timeSetting(key, TIMEOUT_DEFAULT, Setting.Property.NodeScope));
30-
3128
public static final Function<String, Setting.AffixSetting<TimeValue>> TIMEOUT_LDAP_SETTING = RealmSettings.affixSetting(
3229
"timeout.ldap_search", key -> Setting.timeSetting(key, TIMEOUT_DEFAULT, Setting.Property.NodeScope));
3330

31+
public static final Function<String, Setting.AffixSetting<TimeValue>> TIMEOUT_TCP_READ_SETTING = RealmSettings.affixSetting(
32+
"timeout.tcp_read", key -> Setting.timeSetting(key, TimeValue.MINUS_ONE, Setting.Property.NodeScope,
33+
Setting.Property.Deprecated));
34+
35+
public static final Function<String, Setting.AffixSetting<TimeValue>> TIMEOUT_RESPONSE_SETTING = RealmSettings.affixSetting(
36+
"timeout.response", key -> Setting.timeSetting(key, TimeValue.MINUS_ONE, Setting.Property.NodeScope));
37+
3438
public static final Function<String, Setting.AffixSetting<Boolean>> HOSTNAME_VERIFICATION_SETTING = RealmSettings.affixSetting(
3539
"hostname_verification", key -> Setting.boolSetting(key, true, Setting.Property.NodeScope, Setting.Property.Filtered));
3640

@@ -49,6 +53,7 @@ public static Set<Setting.AffixSetting<?>> getSettings(String realmType) {
4953
settings.add(URLS_SETTING.apply(realmType));
5054
settings.add(TIMEOUT_TCP_CONNECTION_SETTING.apply(realmType));
5155
settings.add(TIMEOUT_TCP_READ_SETTING.apply(realmType));
56+
settings.add(TIMEOUT_RESPONSE_SETTING.apply(realmType));
5257
settings.add(TIMEOUT_LDAP_SETTING.apply(realmType));
5358
settings.add(HOSTNAME_VERIFICATION_SETTING.apply(realmType));
5459
settings.add(FOLLOW_REFERRALS_SETTING.apply(realmType));

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactory.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,22 @@ protected static LDAPConnectionOptions connectionOptions(RealmConfig config,
121121
LDAPConnectionOptions options = new LDAPConnectionOptions();
122122
options.setConnectTimeoutMillis(Math.toIntExact(config.getSetting(SessionFactorySettings.TIMEOUT_TCP_CONNECTION_SETTING).millis()));
123123
options.setFollowReferrals(config.getSetting(SessionFactorySettings.FOLLOW_REFERRALS_SETTING));
124-
options.setResponseTimeoutMillis(config.getSetting(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING).millis());
124+
final long responseTimeoutMillis;
125+
if (config.hasSetting(SessionFactorySettings.TIMEOUT_RESPONSE_SETTING)) {
126+
if (config.hasSetting(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING)) {
127+
throw new IllegalArgumentException("[" + RealmSettings.getFullSettingKey(config,
128+
SessionFactorySettings.TIMEOUT_TCP_READ_SETTING) + "] and [" + RealmSettings.getFullSettingKey(config,
129+
SessionFactorySettings.TIMEOUT_RESPONSE_SETTING) + "] may not be used at the same time");
130+
}
131+
responseTimeoutMillis = config.getSetting(SessionFactorySettings.TIMEOUT_RESPONSE_SETTING).millis();
132+
} else {
133+
if (config.hasSetting(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING)) {
134+
responseTimeoutMillis = config.getSetting(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING).millis();
135+
} else {
136+
responseTimeoutMillis = config.getSetting(SessionFactorySettings.TIMEOUT_LDAP_SETTING).millis();
137+
}
138+
}
139+
options.setResponseTimeoutMillis(responseTimeoutMillis);
125140
options.setAllowConcurrentSocketFactoryUse(true);
126141

127142
final boolean verificationModeExists = config.hasSetting(SSLConfigurationSettings.VERIFICATION_MODE_SETTING_REALM);

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/RealmSettingsTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ private Settings.Builder commonLdapSettings(String type, boolean configureSSL) {
184184
.put("unmapped_groups_as_roles", randomBoolean())
185185
.put("files.role_mapping", "x-pack/" + randomAlphaOfLength(8) + ".yml")
186186
.put("timeout.tcp_connect", randomPositiveTimeValue())
187-
.put("timeout.tcp_read", randomPositiveTimeValue())
187+
.put("timeout.response", randomPositiveTimeValue())
188188
.put("timeout.ldap_search", randomPositiveTimeValue());
189189
if (configureSSL) {
190190
configureSsl("ssl.", builder, randomBoolean(), randomBoolean());

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public void testBindWithReadTimeout() throws Exception {
9292
Settings settings = Settings.builder()
9393
.put(globalSettings)
9494
.put(buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, LdapSearchScope.SUB_TREE))
95-
.put(RealmSettings.getFullSettingKey(REALM_IDENTIFIER, SessionFactorySettings.TIMEOUT_TCP_READ_SETTING), "1ms")
95+
.put(RealmSettings.getFullSettingKey(REALM_IDENTIFIER, SessionFactorySettings.TIMEOUT_RESPONSE_SETTING), "1ms")
9696
.put("path.home", createTempDir())
9797
.build();
9898

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryTests.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.elasticsearch.action.ActionListener;
1212
import org.elasticsearch.action.support.PlainActionFuture;
1313
import org.elasticsearch.common.settings.SecureString;
14+
import org.elasticsearch.common.settings.Setting;
1415
import org.elasticsearch.common.settings.Settings;
1516
import org.elasticsearch.common.util.concurrent.ThreadContext;
1617
import org.elasticsearch.env.Environment;
@@ -62,13 +63,67 @@ public void testConnectionFactoryReturnsCorrectLDAPConnectionOptionsWithDefaultS
6263
assertThat(options.getSSLSocketVerifier(), is(instanceOf(HostNameSSLSocketVerifier.class)));
6364
}
6465

66+
public void testSessionFactoryWithResponseTimeout() throws Exception {
67+
final RealmConfig.RealmIdentifier realmId = new RealmConfig.RealmIdentifier("ldap", "response_settings");
68+
final Path pathHome = createTempDir();
69+
{
70+
Settings settings = Settings.builder()
71+
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_RESPONSE_SETTING), "10s")
72+
.put("path.home", pathHome)
73+
.build();
74+
75+
final Environment environment = TestEnvironment.newEnvironment(settings);
76+
RealmConfig realmConfig = new RealmConfig(realmId, settings, environment, new ThreadContext(settings));
77+
LDAPConnectionOptions options = SessionFactory.connectionOptions(realmConfig, new SSLService(settings, environment), logger);
78+
assertThat(options.getResponseTimeoutMillis(), is(equalTo(10000L)));
79+
}
80+
{
81+
Settings settings = Settings.builder()
82+
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_TCP_READ_SETTING), "7s")
83+
.put("path.home", pathHome)
84+
.build();
85+
86+
final Environment environment = TestEnvironment.newEnvironment(settings);
87+
RealmConfig realmConfig = new RealmConfig(realmId, settings, environment, new ThreadContext(settings));
88+
LDAPConnectionOptions options = SessionFactory.connectionOptions(realmConfig, new SSLService(settings, environment), logger);
89+
assertThat(options.getResponseTimeoutMillis(), is(equalTo(7000L)));
90+
assertSettingDeprecationsAndWarnings(new Setting<?>[]{SessionFactorySettings.TIMEOUT_TCP_READ_SETTING.apply("ldap")
91+
.getConcreteSettingForNamespace("response_settings")});
92+
}
93+
{
94+
Settings settings = Settings.builder()
95+
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_RESPONSE_SETTING), "11s")
96+
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_TCP_READ_SETTING), "6s")
97+
.put("path.home", pathHome)
98+
.build();
99+
100+
final Environment environment = TestEnvironment.newEnvironment(settings);
101+
RealmConfig realmConfig = new RealmConfig(realmId, settings, environment, new ThreadContext(settings));
102+
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> SessionFactory.connectionOptions(realmConfig
103+
, new SSLService(settings, environment), logger));
104+
assertThat(ex.getMessage(), is("[xpack.security.authc.realms.ldap.response_settings.timeout.tcp_read] and [xpack.security" +
105+
".authc.realms.ldap.response_settings.timeout.response] may not be used at the same time"));
106+
}
107+
{
108+
Settings settings = Settings.builder()
109+
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_LDAP_SETTING), "750ms")
110+
.put("path.home", pathHome)
111+
.build();
112+
113+
final Environment environment = TestEnvironment.newEnvironment(settings);
114+
RealmConfig realmConfig = new RealmConfig(realmId, settings, environment, new ThreadContext(settings));
115+
LDAPConnectionOptions options = SessionFactory.connectionOptions(realmConfig, new SSLService(settings, environment), logger);
116+
assertThat(options.getResponseTimeoutMillis(), is(equalTo(750L)));
117+
}
118+
}
119+
65120
public void testConnectionFactoryReturnsCorrectLDAPConnectionOptions() throws Exception {
66121
final RealmConfig.RealmIdentifier realmId = new RealmConfig.RealmIdentifier("ldap", "conn_settings");
67122
final Path pathHome = createTempDir();
68123
Settings settings = getSettingsBuilder()
69124
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_TCP_CONNECTION_SETTING), "10ms")
70125
.put(getFullSettingKey(realmId, SessionFactorySettings.HOSTNAME_VERIFICATION_SETTING), "false")
71-
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_TCP_READ_SETTING), "20ms")
126+
.put(getFullSettingKey(realmId, SessionFactorySettings.TIMEOUT_RESPONSE_SETTING), "20ms")
72127
.put(getFullSettingKey(realmId, SessionFactorySettings.FOLLOW_REFERRALS_SETTING), "false")
73128
.put("path.home", pathHome)
74129
.build();

0 commit comments

Comments
 (0)