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

[Kerberos] Rest client integration test #32070

Merged
merged 9 commits into from
Jul 18, 2018

Conversation

bizybot
Copy link
Contributor

@bizybot bizybot commented Jul 16, 2018

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

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
@bizybot bizybot added >feature :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc) labels Jul 16, 2018
@bizybot bizybot requested review from tvernum and jaymode July 16, 2018 03:09
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security

@tvernum
Copy link
Contributor

tvernum commented Jul 16, 2018

@jkakavas Can you have a look at CustomHttpClientConfigCallbackHandler with respect to FIPS.
Do we want/expect Krb to work on a FIPS JVM, or could we skip this test?

Copy link
Contributor

@tvernum tvernum left a 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());
Copy link
Contributor

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.

Copy link
Contributor Author

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";
Copy link
Contributor

Choose a reason for hiding this comment

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

s/WTIH/WITH

Copy link
Contributor Author

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" })
Copy link
Contributor

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"

Copy link
Contributor Author

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'
Copy link
Member

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"
Copy link
Member

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.

Copy link
Contributor Author

@bizybot bizybot Jul 17, 2018

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'
Copy link
Member

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?

Copy link
Contributor Author

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 {
Copy link
Member

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

Copy link
Contributor Author

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) {
Copy link
Member

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?

Copy link
Contributor Author

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;
Copy link
Member

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

Copy link
Contributor Author

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;
Copy link
Member

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?

Copy link
Contributor Author

@bizybot bizybot Jul 17, 2018

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 {
Copy link
Member

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

Copy link
Contributor Author

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);
Copy link
Member

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

Copy link
Contributor Author

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.

Yogesh Gaikwad added 2 commits July 17, 2018 15:12
- Enable security manager for tests and related modifications
  to give permissions
- Rename HttpClientConfigCallbackHandler
- Remove unwanted code.
@bizybot
Copy link
Contributor Author

bizybot commented Jul 17, 2018

Hi, @jaymode I have addressed your review comments. Please take a look when you get some time. Thank you for reviewing it.

Copy link
Member

@jaymode jaymode left a 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";
Copy link
Member

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?

Copy link
Contributor Author

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.

@bizybot bizybot merged commit dd7cdfd into elastic:feature/kerberos Jul 18, 2018
@bizybot bizybot deleted the kerberos/qakerberos branch July 18, 2018 06:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>feature :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants