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

OpenID Connect Realm base functionality #37009

Merged
merged 22 commits into from
Jan 18, 2019

Conversation

jkakavas
Copy link
Member

For the benefit of splitting this feature to manageable/reviewable(sic) chuncks, this commit adds

  • An OpenID Connect Realm definition
  • Necessary OpenID Connect Realm settings to support Authorization code grant and Implicit grant flows
  • Rest and Transport Action and Request/Response objects for initiating and completing the authentication flow
  • Functionality for generating OIDC Authentication Request URIs
  • Unit tests

Notably missing (to be handled in subsequent PRs):

  • The actual implementation of the authentication flows
  • Necessary JW{T,S,E} functionality

Relates: #35339

@jkakavas jkakavas added >feature v7.0.0 :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc) labels Dec 28, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security

@jkakavas
Copy link
Member Author

@elasticmachine test this please

@jkakavas
Copy link
Member Author

10:27:39   2> REPRODUCE WITH: ./gradlew :x-pack:plugin:ccr:internalClusterTest -Dtests.seed=8E411DEFD87B60B6 -Dtests.class=org.elasticsearch.xpack.ccr.LocalIndexFollowingIT -Dtests.method="testRemoveRemoteConnection" -Dtests.security.manager=true -Dtests.locale=hi -Dtests.timezone=Asia/Nicosia -Dcompiler.java=11 -Druntime.java=8

@elasticmachine run the gradle build tests 2 please

public class OpenIdConnectAuthenticateRequest extends ActionRequest {

/**
* The URI were the OP redirected the browser after the authentication attempt. This is passed as is from the
Copy link
Member

Choose a reason for hiding this comment

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

s/were/where

}

@Override
public void readFrom(StreamInput in) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

I'd love to see us start using Writeable for everything new. That would make this throw a UnsupportedOperationException.

@jaymode
Copy link
Member

jaymode commented Jan 11, 2019

@jkakavas when targeting a feature branch, its best to ensure you keep it up to date if you merge master into your PR otherwise it looks like the change you're merging is a lot bigger. I went ahead and updated feature-oidc-realm to be in sync with current master. This changed the PR diff from 8000 lines to 1400 lines.

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.

LGTM

public static final Setting.AffixSetting<String> OP_TOKEN_ENDPOINT
= RealmSettings.simpleString(TYPE, "op.token_endpoint", Setting.Property.NodeScope);
public static final Setting.AffixSetting<String> OP_USERINFO_ENDPOINT
= RealmSettings.simpleString(TYPE, "op.userinfo_endpoint", Setting.Property.NodeScope);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't we get by without the the user_info endpoint. I sense this can be added latter if there are integrations that absolutely require it? Just a thought....

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll leave it in as it is not a required setting ( so it won't produce any errors/warnings if not configured) and I plan to have the ability to query the user_info endpoint as a configurable part of the authentication flow from the beginning.

public static final Setting.AffixSetting<String> RP_REDIRECT_URI
= RealmSettings.simpleString(TYPE, "rp.redirect_uri", Setting.Property.NodeScope);
public static final Setting.AffixSetting<String> RP_RESPONSE_TYPE
= RealmSettings.simpleString(TYPE, "rp.response_type", Setting.Property.NodeScope);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can infer this? Keep it to code or id_token?

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right that it doesn't make much sense now with the allowed values being code and implicit. The original thought was to infer "id_token" from the value implicit, but as also proven by me not adding it, this is probably an unnecessary optimization for the user. I will change implicit to id_token to be in line with the specification


private String realmName;
private String state;
private String nonce;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's easier to reason if we generate the state and nonce. OIDC allows for too much flexibility already....

Copy link
Member Author

Choose a reason for hiding this comment

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

I went back and forth on this for some time. Agreed, there is no strong argument against allowing Kibana (or any other facilitator ) to determine the nonce and state. I will address this

- Remove the possibility for the facilitator to request a specific
nonce or state value and instead generate them always in ES.
- Fix the response_type allowed values
@jkakavas
Copy link
Member Author

As a though, I think it's better if have specific OP implementation to cater for.

If I'm reading this correctly , I plan on adding support for a subset of the Dynamic Discovery specification (at least the part of consuming the OP metadata

@jkakavas
Copy link
Member Author

10:16:34 > Could not resolve all files for configuration ':x-pack:plugin:security:runtime'.
10:16:34    > Could not download xmlsec.jar (org.apache.santuario:xmlsec:2.0.8)
10:16:34       > Could not get resource 'https://jcenter.bintray.com/org/apache/santuario/xmlsec/2.0.8/xmlsec-2.0.8.jar'.
10:16:34          > Connection reset
10:16:34    > Could not download guava.jar (com.google.guava:guava:19.0)
10:16:34       > Could not get resource 'https://jcenter.bintray.com/com/google/guava/guava/19.0/guava-19.0.jar'.
10:16:34          > Connection reset

and

10:16:42 * What went wrong:
10:16:42 Execution failed for task ':client:test:checkstyleMain'.
10:16:42 > Could not resolve all files for configuration ':client:test:checkstyle'.
10:16:42    > Could not download guava.jar (com.google.guava:guava:25.1-jre)
10:16:42       > Could not get resource 'https://jcenter.bintray.com/com/google/guava/guava/25.1-jre/guava-25.1-jre.jar'.
10:16:42          > Could not GET 'https://d29vzk4ow07wi7.cloudfront.net/6db0c3a244c397429c2e362ea2837c3622d5b68bb95105d37c21c36e5bc70abf?response-content-disposition=attachment%3Bfilename%3D%22guava-25.1-jre.jar%22&Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHAqOi8vZDI5dnprNG93MDd3aTcuY2xvdWRmcm9udC5uZXQvNmRiMGMzYTI0NGMzOTc0MjljMmUzNjJlYTI4MzdjMzYyMmQ1YjY4YmI5NTEwNWQzN2MyMWMzNmU1YmM3MGFiZj9yZXNwb25zZS1jb250ZW50LWRpc3Bvc2l0aW9uPWF0dGFjaG1lbnQlM0JmaWxlbmFtZSUzRCUyMmd1YXZhLTI1LjEtanJlLmphciUyMiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTU0NzU0MDUyMH0sIklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIwLjAuMC4wLzAifX19XX0_&Signature=Wv5jd2Pqv5oaDdrjCzDaiyvIWVua0a7BOBipWdT29tP2ER3-tJN-10H39d0Tt6uOamzsLfHPC5r1qt7UyBpa9lNMAFpZaJ-7pvTCxGHyncEAb4uCAWLqMBo2hSDo0Cwr~kIrJUIwo-EVlbo1xrfzKrJi1cjpxHIS46SxWOpSnFod3DxIaNz5pNwbapbTbR8FK7W9qp8w2HyoshOhSTk5OZAvYuvKguvzymFjpZeYm9Vphk1HH~mCLyZB-DEh9XMwgKfEwZMzLIhHj7el3wr5L6f9FLEYf9j47t8nCTQs1mdWIt8QIqRW8HMak9NIqox5mRHyW2Mobc-EcXJUJArrjw__&Key-Pair-Id=APKAIFKFWOMXM2UMTSFA'.
10:16:42 :docs:buildRestTests (Thread[Execution worker for ':' Thread 6,5,main]) completed. Took 10.089 secs.
10:16:42             > Connection reset
10:16:42 

@elasticmachine I will try and ask you to run the gradle build tests 1 and then also run the gradle build tests 2 if you may

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.

Given the approvals from others, I didn't read everything, but I left some comments.
Feel free to address them in a followup if you'd like to get this one merged.

*/
public class RestOpenIdConnectPrepareAuthenticationAction extends OpenIdConnectBaseRestHandler {

static final ObjectParser<OpenIdConnectPrepareAuthenticationRequest, Void> PARSER = new ObjectParser<>("oidc_prepare_auithentication",
Copy link
Contributor

Choose a reason for hiding this comment

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

s/auith/auth/


/**
* The state value that either we or the facilitator generated for this specific flow and that was stored at the user's session with
* the facilitator
Copy link
Contributor

Choose a reason for hiding this comment

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

These java docs ("the faciliator generated") are no longer true.

.filter(r -> r instanceof OpenIdConnectRealm)
.map(r -> (OpenIdConnectRealm) r)
.filter(r -> r.name().equals(request.getRealmName()))
.collect(Collectors.toList());
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just call Realms.realm(String) ?

private String nonce;

/**
* @param redirectUri The URI were the OP redirected the browser after the authentication event at the OP. This is passed as is from the
Copy link
Contributor

Choose a reason for hiding this comment

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

s/were/where/


@Override
public String principal() {
return "<unauthenticated-oidc-user>";
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on the confusion that users have around unauthenticated-saml-user we used a different pattern on just "<Kerberos Token>" for Kerberos.
My gut feel is to do something similar here "<OIDC Token>" ?

this.clientId = Objects.requireNonNull(clientId, "RP Client ID must be provided");
this.redirectUri = Objects.requireNonNull(redirectUri, "RP Redirect URI must be provided");
if (Strings.hasText(responseType) == false) {
throw new IllegalArgumentException("Response type must be provided");
Copy link
Contributor

Choose a reason for hiding this comment

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

I think these error messages need to be clear about the Setting that was incorrect.
Ideally we'd do validation in the Setting itself, but if not, then I think the validation ought to be done in the context of the Realm so that it can reference the setting key.
Otherwise we'll get lots of questions from users about "I got an error saying Response type must be provided but I don't know where to configure it."

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense Tim, I'll address that. I'll do it in the Realm (this is what we do in other realms too I think) but I can move this to the Setting with a validator if need be !

@jkakavas
Copy link
Member Author

Thanks for the valuable feedback Tim, I'll go ahead and address this now before merging

@jkakavas
Copy link
Member Author

run the gradle build tests 2

@jkakavas
Copy link
Member Author

run the gradle build tests 2 and also run the gradle build tests 1

@jkakavas
Copy link
Member Author

jkakavas commented Jan 17, 2019

08:10:54 > Task :x-pack:plugin:ml:cpp-snapshot:downloadMachineLearningSnapshot FAILED
08:10:54 :x-pack:plugin:ml:cpp-snapshot:downloadMachineLearningSnapshot (Thread[Execution worker for ':' Thread 14,5,main]) completed. Took 2 mins 10.741 secs.

@jkakavas
Copy link
Member Author

run the gradle build tests 2

@jkakavas
Copy link
Member Author

run the gradle build tests 1

@jkakavas
Copy link
Member Author

run the gradle build tests 1

1 similar comment
@jkakavas
Copy link
Member Author

run the gradle build tests 1

@jkakavas
Copy link
Member Author

10:10:34 > Task :server:integTest
10:10:34 Tests with failures:
10:10:34   - org.elasticsearch.discovery.MasterDisruptionIT.testFailWithMinimumMasterNodesConfigured
10:10:34   - org.elasticsearch.discovery.zen.ZenDiscoveryIT.testNoShardRelocationsOccurWhenElectedMasterNodeFails

:sigh:

run the gradle build tests 1

@jkakavas
Copy link
Member Author

run the gradle build tests 1 just in case we get lucky

@jkakavas
Copy link
Member Author

20th time is the charm as an old Greek proverb says, run the gradle build tests 1

@jkakavas jkakavas merged commit 8d54639 into elastic:feature-oidc-realm Jan 18, 2019
@jkakavas jkakavas deleted the oidc-realm-base branch January 18, 2019 17:09
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Jan 20, 2019
This commit adds

* An OpenID Connect Realm definition
* Necessary OpenID Connect Realm settings to support Authorization code
 grant and Implicit grant flows
* Rest and Transport Action and Request/Response objects for initiating and
 completing the authentication flow
* Functionality for generating OIDC Authentication Request URIs Unit tests

Notably missing (to be handled in subsequent PRs):
* The actual implementation of the authentication flows
* Necessary JW{T,S,E} functionality

Relates: elastic#35339
jkakavas added a commit that referenced this pull request Apr 4, 2019
This commit adds an OpenID Connect authentication realm to
elasticsearch. Elasticsearch (with the assistance of kibana or
another web component) acts as an OpenID Connect Relying
Party and supports the Authorization Code Grant and Implicit
flows as described in http://ela.st/oidc-spec. It adds support
for consuming and verifying signed ID Tokens, both RP
initiated and 3rd party initiated Single Sign on and RP
initiated signle logout.
It also adds an OpenID Connect Provider in the idp-fixture to
be used for the associated integration tests.

The code in this commit has been tracked in a feature branch
and has been previously reviewed and approved in :

#37009
#37787
#38474
#38475
#40262
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Apr 14, 2019
This commit adds an OpenID Connect authentication realm to
elasticsearch. Elasticsearch (with the assistance of kibana or
another web component) acts as an OpenID Connect Relying
Party and supports the Authorization Code Grant and Implicit
flows as described in http://ela.st/oidc-spec. It adds support
for consuming and verifying signed ID Tokens, both RP
initiated and 3rd party initiated Single Sign on and RP
initiated signle logout.
It also adds an OpenID Connect Provider in the idp-fixture to
be used for the associated integration tests.

The code in this commit has been tracked in a feature branch
and has been previously reviewed and approved in :

elastic#37009
elastic#37787
elastic#38474
elastic#38475
elastic#40262
gurkankaymak pushed a commit to gurkankaymak/elasticsearch that referenced this pull request May 27, 2019
This commit adds an OpenID Connect authentication realm to
elasticsearch. Elasticsearch (with the assistance of kibana or
another web component) acts as an OpenID Connect Relying
Party and supports the Authorization Code Grant and Implicit
flows as described in http://ela.st/oidc-spec. It adds support
for consuming and verifying signed ID Tokens, both RP
initiated and 3rd party initiated Single Sign on and RP
initiated signle logout.
It also adds an OpenID Connect Provider in the idp-fixture to
be used for the associated integration tests.

The code in this commit has been tracked in a feature branch
and has been previously reviewed and approved in :

elastic#37009
elastic#37787
elastic#38474
elastic#38475
elastic#40262
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) v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants