Skip to content

Commit c2fff29

Browse files
jaymodeYogesh Gaikwad
authored and
Yogesh Gaikwad
committed
Use hostname instead of IP with SPNEGO test (#32514)
This change updates KerberosAuthenticationIT to resolve the host used to connect to the test cluster. This is needed because the host could be an IP address but SPNEGO requires a hostname to work properly. This is done by adding a hook in ESRestTestCase for building the HttpHost from the host and port. Additionally, the project now specifies the IPv4 loopback address as the http host. This is done because we need to be able to resolve the address used for the HTTP transport before the node starts up, but the http.ports file is not written until the node is started. Closes #32498
1 parent 6d47ae8 commit c2fff29

File tree

3 files changed

+60
-25
lines changed

3 files changed

+60
-25
lines changed

test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public void initClient() throws IOException {
148148
}
149149
String host = stringUrl.substring(0, portSeparator);
150150
int port = Integer.valueOf(stringUrl.substring(portSeparator + 1));
151-
hosts.add(new HttpHost(host, port, getProtocol()));
151+
hosts.add(buildHttpHost(host, port));
152152
}
153153
clusterHosts = unmodifiableList(hosts);
154154
logger.info("initializing REST clients against {}", clusterHosts);
@@ -160,6 +160,13 @@ public void initClient() throws IOException {
160160
assert clusterHosts != null;
161161
}
162162

163+
/**
164+
* Construct a HttpHost from the given host and port
165+
*/
166+
protected HttpHost buildHttpHost(String host, int port) {
167+
return new HttpHost(host, port, getProtocol());
168+
}
169+
163170
/**
164171
* Clean up after the test case.
165172
*/

x-pack/qa/kerberos-tests/build.gradle

+37-22
Original file line numberDiff line numberDiff line change
@@ -36,32 +36,43 @@ task krb5kdcFixture(type: org.elasticsearch.gradle.test.VagrantFixture) {
3636
dependsOn krb5kdcUpdate
3737
}
3838

39-
task krb5AddPrincipals { dependsOn krb5kdcFixture }
39+
// lazily resolve to avoid any slowdowns from DNS lookups prior to when we need this value
40+
Object httpPrincipal = new Object() {
41+
@Override
42+
String toString() {
43+
InetAddress resolvedAddress = InetAddress.getByName('127.0.0.1')
44+
return "HTTP/" + resolvedAddress.getHostName()
45+
}
46+
}
4047

41-
List<String> principals = [
42-
"HTTP/localhost",
43-
"peppa",
44-
"george~dino"
45-
]
4648
String realm = "BUILD.ELASTIC.CO"
4749

48-
for (String principal : principals) {
49-
String[] princPwdPair = principal.split('~');
50-
String princName = princPwdPair[0];
51-
String password = "";
52-
if (princPwdPair.length > 1) {
53-
password = princPwdPair[1];
54-
}
55-
Task create = project.tasks.create("addPrincipal#${principal}".replace('/', '_'), org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
56-
command 'ssh'
57-
args '--command', "sudo bash /vagrant/src/main/resources/provision/addprinc.sh $princName $password"
58-
boxName box
59-
environmentVars vagrantEnvVars
60-
dependsOn krb5kdcFixture
61-
}
62-
krb5AddPrincipals.dependsOn(create)
50+
task 'addPrincipal#peppa'(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
51+
command 'ssh'
52+
args '--command', "sudo bash /vagrant/src/main/resources/provision/addprinc.sh peppa "
53+
boxName box
54+
environmentVars vagrantEnvVars
55+
dependsOn krb5kdcFixture
56+
}
57+
58+
task 'addPrincipal#george'(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
59+
command 'ssh'
60+
args '--command', "sudo bash /vagrant/src/main/resources/provision/addprinc.sh george dino"
61+
boxName box
62+
environmentVars vagrantEnvVars
63+
dependsOn krb5kdcFixture
64+
}
65+
66+
task 'addPrincipal#HTTP'(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
67+
command 'ssh'
68+
args '--command', "sudo bash /vagrant/src/main/resources/provision/addprinc.sh $httpPrincipal"
69+
boxName box
70+
environmentVars vagrantEnvVars
71+
dependsOn krb5kdcFixture
6372
}
6473

74+
task krb5AddPrincipals { dependsOn krb5kdcFixture, 'addPrincipal#peppa', 'addPrincipal#george', 'addPrincipal#HTTP' }
75+
6576
def generatedResources = "$buildDir/generated-resources/keytabs"
6677
task copyKeytabToGeneratedResources(type: Copy) {
6778
Path peppaKeytab = project(':test:fixtures:krb5kdc-fixture').buildDir.toPath().resolve("keytabs").resolve("peppa.keytab").toAbsolutePath()
@@ -71,6 +82,9 @@ task copyKeytabToGeneratedResources(type: Copy) {
7182
}
7283

7384
integTestCluster {
85+
// force localhost IPv4 otherwise it is a chicken and egg problem where we need the keytab for the hostname when starting the cluster
86+
// but do not know the exact address that is first in the http ports file
87+
setting 'http.host', '127.0.0.1'
7488
setting 'xpack.license.self_generated.type', 'trial'
7589
setting 'xpack.security.enabled', 'true'
7690
setting 'xpack.security.authc.realms.file.type', 'file'
@@ -87,7 +101,8 @@ integTestCluster {
87101
Path krb5conf = project(':test:fixtures:krb5kdc-fixture').buildDir.toPath().resolve("conf").resolve("krb5.conf").toAbsolutePath()
88102
String jvmArgsStr = " -Djava.security.krb5.conf=${krb5conf}" + " -Dsun.security.krb5.debug=true"
89103
jvmArgs jvmArgsStr
90-
Path esKeytab = project(':test:fixtures:krb5kdc-fixture').buildDir.toPath().resolve("keytabs").resolve("HTTP_localhost.keytab").toAbsolutePath()
104+
Path esKeytab = project(':test:fixtures:krb5kdc-fixture').buildDir.toPath().resolve("keytabs")
105+
.resolve("$httpPrincipal".replace('/', '_') + ".keytab").toAbsolutePath()
91106
extraConfigFile("es.keytab", "${esKeytab}")
92107

93108
setupCommand 'setupTestAdmin',

x-pack/qa/kerberos-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosAuthenticationIT.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.client.RestClient;
1414
import org.elasticsearch.client.RestClientBuilder;
1515
import org.elasticsearch.common.Strings;
16+
import org.elasticsearch.common.SuppressForbidden;
1617
import org.elasticsearch.common.settings.SecureString;
1718
import org.elasticsearch.common.settings.Settings;
1819
import org.elasticsearch.common.unit.TimeValue;
@@ -23,6 +24,8 @@
2324
import org.junit.Before;
2425

2526
import java.io.IOException;
27+
import java.net.InetAddress;
28+
import java.net.UnknownHostException;
2629
import java.security.AccessControlContext;
2730
import java.security.AccessController;
2831
import java.security.PrivilegedActionException;
@@ -82,7 +85,6 @@ public void setupRoleMapping() throws IOException {
8285
assertOK(response);
8386
}
8487

85-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32498")
8688
public void testLoginByKeytab() throws IOException, PrivilegedActionException {
8789
final String userPrincipalName = System.getProperty(TEST_USER_WITH_KEYTAB_KEY);
8890
final String keytabPath = System.getProperty(TEST_USER_WITH_KEYTAB_PATH_KEY);
@@ -92,7 +94,6 @@ public void testLoginByKeytab() throws IOException, PrivilegedActionException {
9294
executeRequestAndVerifyResponse(userPrincipalName, callbackHandler);
9395
}
9496

95-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32498")
9697
public void testLoginByUsernamePassword() throws IOException, PrivilegedActionException {
9798
final String userPrincipalName = System.getProperty(TEST_USER_WITH_PWD_KEY);
9899
final String password = System.getProperty(TEST_USER_WITH_PWD_PASSWD_KEY);
@@ -106,6 +107,18 @@ public void testSoDoesNotFailWithNoTests() {
106107
// intentionally empty - this is just needed to ensure the build does not fail because we mute its only test.
107108
}
108109

110+
@Override
111+
@SuppressForbidden(reason = "SPNEGO relies on hostnames and we need to ensure host isn't a IP address")
112+
protected HttpHost buildHttpHost(String host, int port) {
113+
try {
114+
InetAddress inetAddress = InetAddress.getByName(host);
115+
return super.buildHttpHost(inetAddress.getHostName(), port);
116+
} catch (UnknownHostException e) {
117+
assumeNoException("failed to resolve host [" + host + "]", e);
118+
}
119+
throw new IllegalStateException("DNS not resolved and assume did not trip");
120+
}
121+
109122
private void executeRequestAndVerifyResponse(final String userPrincipalName,
110123
final SpnegoHttpClientConfigCallbackHandler callbackHandler) throws PrivilegedActionException, IOException {
111124
final Request request = new Request("GET", "/_xpack/security/_authenticate");

0 commit comments

Comments
 (0)