-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
[Kerberos] Rest client integration test #32070
[Kerberos] Rest client integration test #32070
Conversation
This commit adds the rest client integration test for Kerberos. This uses existing krb5kdc-fixture, which makes use of MIT Kerberos. Added support to create principals with password in krb5kdc-fixture. The rest test demonstrates the following: - Use of rest client to invoke Elasticsearch APIs authenticating using spnego mechanism, example showing what customizations we need to do to build the rest client. - test for login by keytab for user principal - test for login by username password for user principal
Pinging @elastic/es-security |
@jkakavas Can you have a look at |
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, with a few minor nits
.field("enabled", true).startObject("rules").startArray("all").startObject().startObject("field") | ||
.field("realm.name", TEST_KERBEROS_REALM_NAME).endObject().endObject().endArray() // "all" | ||
.endObject() // "rules" | ||
.endObject()); |
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 suspect you copied this from code I wrote, but can we lay this out a bit more cleanly? Like one field per line, or something.
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.
Yes, you are right, I guess it was code formatter. Thank you.
private static final String TEST_USER_WITH_KEYTAB_KEY = "test.userkt"; | ||
private static final String TEST_USER_WITH_KEYTAB_PATH_KEY = "test.userkt.keytab"; | ||
private static final String TEST_USER_WITH_PWD_KEY = "test.userpwd"; | ||
private static final String TEST_USER_WTIH_PWD_PASSWD_KEY = "test.userpwd.password"; |
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.
s/WTIH/WITH
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.
Thanks, fixed it.
@Before | ||
public void setupRoleMapping() throws IOException { | ||
final String json = Strings // top-level | ||
.toString(XContentBuilder.builder(XContentType.JSON.xContent()).startObject().array("roles", new String[] { "super_user" }) |
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.
The builtin role is superuser
, no _
.
If you're not trying to use that role, then just pick something more obvious like "kerb_test"
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 did not realize it and it did not fail for an invalid role. I have updated to use kerb_test role for testing. Thank you.
integTestCluster { | ||
setting 'xpack.license.self_generated.type', 'trial' | ||
setting 'xpack.security.enabled', 'true' | ||
setting 'xpack.security.http.ssl.enabled', 'false' |
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 do not think we need this setting
setting 'xpack.security.authc.realms.kerberos.remove_realm_name', 'false' | ||
|
||
Path krb5conf = project(':test:fixtures:krb5kdc-fixture').buildDir.toPath().resolve("conf").resolve("krb5.conf").toAbsolutePath() | ||
String jvmArgsStr = " -Djava.security.krb5.conf=${krb5conf}" + " -Dsun.security.krb5.debug=true" |
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.
why do we specify debug in the realm and in the jvm args? Is it because our debug value overrides the system property? If so, we need to change the default of the setting to be the value of the system property.
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.
There are two flags for debug level logs, -Djava.security.krb5.conf
enables debug logs at the Kerberos protocol level. The flag that we take in realm config is only for Krb5LoginModule from JAAS. I will add this information to the debugging and troubleshooting documentation. Thank you.
systemProperty 'test.userkt.keytab', "${peppaKeytab}" | ||
systemProperty 'test.userpwd', "george@${realm}" | ||
systemProperty 'test.userpwd.password', "dino" | ||
systemProperty 'tests.security.manager', 'false' |
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.
can you add a comment on why we need to run without the security manager in these tests?
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 was lazy and did want to keep the client simple. But I think it's better to run with the security manager. I have enabled it and also made some changes to make the tests run with the security manager. Thank you.
* {@link HttpAsyncClientBuilder}.<br> | ||
* It uses configured credentials either password or keytab for authentication. | ||
*/ | ||
public class CustomHttpClientConfigCallbackHandler implements HttpClientConfigCallback { |
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 think we should rename this to SpnegoClientConfigCallbackHandler
as custom
doesn't provide much meaning
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.
Yes, done. Thank you.
return httpClientBuilder; | ||
} | ||
|
||
private void setupSSLSettings(HttpAsyncClientBuilder httpClientBuilder) { |
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.
ssl is disabled in the test for http. why are we setting this up?
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 initially started to configure SSL for node but later on, decided not to as it was adding more configuration to the tests. I will remove this. Thanks.
|
||
private abstract static class AbstractJaasConf extends Configuration { | ||
private final String userPrincipalName; | ||
private final Boolean enableDebugLogs; |
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.
why is this a Boolean
and not a boolean
? This could allow someone to pass in null which we do not want
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.
True, Thank you.
private final String userPrincipalName; | ||
private final SecureString password; | ||
private final String keytabPath; | ||
private final Boolean enableDebugLogs; |
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.
do we really need a tri-state boolean here?
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.
No, we don't need it, corrected this. Thanks.
* @return {@link LoginContext} | ||
* @throws LoginException | ||
*/ | ||
public LoginContext login() throws LoginException { |
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.
can you make this synchronized? There is no concurrent caller but I don't like having a public API like this since someone could call it concurrently
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.
Done, Thank you.
} | ||
|
||
private Response execute(final RestClient restClient, final Request request) throws IOException { | ||
return restClient.performRequest(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.
do we really need this method? I think restClient.performRequest
is readable
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 think I made this change to make it work as access control context was not available but found a method to pass on current threads access control context. Thank you for noticing this.
- Enable security manager for tests and related modifications to give permissions - Rename HttpClientConfigCallbackHandler - Remove unwanted code.
Hi, @jaymode I have addressed your review comments. Please take a look when you get some time. Thank you for reviewing it. |
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 left one comment about the file permissions in the test. Otherwise LGTM
@@ -0,0 +1,5 @@ | |||
grant { | |||
permission javax.security.auth.AuthPermission "doAsPrivileged"; | |||
permission java.io.FilePermission "${test.userkt.keytab}", "read"; |
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 should be able to remove this permission if we add the keytab as a resource within gradle?
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.
Yes, it worked. I have done the changes. Thanks.
This commit adds the rest client integration test for Kerberos.
This uses existing krb5kdc-fixture, which makes use of MIT Kerberos.
Added support to create principals with password in krb5kdc-fixture.
The rest test demonstrates the following:
using spnego mechanism, example showing what customizations we
need to do to build the rest client.