-
Notifications
You must be signed in to change notification settings - Fork 204
Add Kerberos authentication feature #2154
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
base: 2.18
Are you sure you want to change the base?
Conversation
|
Thank you for the PR @Ohasumi. Could you please sign the commits and add some unit tests? Would it be possible to write an integration test or provide steps on how to set up testing for this so another developer can verify the change? |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## 2.18 #2154 +/- ##
=======================================
Coverage 71.46% 71.46%
=======================================
Files 97 97
Lines 2649 2649
Branches 411 403 -8
=======================================
Hits 1893 1893
Misses 641 641
Partials 115 115 ☔ View full report in Codecov by Sentry. |
@cwperks I sign the commits and add notes for environment I'm using. But I'm not sure how to add some unit test, since it required valid kerberos token passing to opensearch core to validate then using jsonwebtoken to sign the user data to be use as cookie. If anything I can helps please tell me, I will do my best. |
Can you provide a markdown document or a Github comment outlining steps used to test? |
I added setup environment note as markdown "kerberos_notes.md" in my last commit, which contained most required environment for test. For testing when access dashboard it should redirect to authentication page then browser should attached kerberos ticket with it,after passed the authentication process jsontoken with user credentials should attached as cookie. I hope this might help clarify my 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.
Hi @Ohasumi, thank you for opening this feature PR. If you intend to continue working on this:
- Please open an issue describing this feature.
- Please update the title of this PR to be more descriptive.
- Please sign all your commits to pass the DCO check.
Thank you for your contribution!
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
Signed-off-by: Thanakit Yuenyongphisit <[email protected]>
| }), | ||
| kerberos: schema.object({ | ||
| jwt_siging_key: schema.string({ | ||
| defaultValue: 'secret share between opensearch and dashboards', |
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 change the default value to be empty?
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.
+1
This is a placeholder, but defaults like this should never be hardcoded in production
| this.router.get( | ||
| { | ||
| path: KERBEROS_AUTH_LOGIN, | ||
| validate: 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.
shouldn't we validate the path, specifically the nextUrl. see saml routes setup.
| let user: User; | ||
|
|
||
| try { | ||
| user = await this.securityClient.authinfo(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.
will this force login every-time this route is hit?
| // return to root | ||
| return response.redirected({ | ||
| headers: { | ||
| location: '/', |
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 redirect to the url passed in nextUrl query param.
| @@ -0,0 +1,120 @@ | |||
| ### Required environment for Kerberos authentication ### | |||
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.
all the content from this file should be added to DEVELOPER_GUIDE.md. Also, please run it through grammar and spell-check.
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.
+1
| config: SecurityPluginConfigType, | ||
| sessionStorageFactory: SessionStorageFactory<SecuritySessionCookie>, | ||
| router: IRouter, | ||
| esClient: ILegacyClusterClient, |
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 we use IClusterClient as ILegacyClusterClient is marked as deprecated.
| request: OpenSearchDashboardsRequest<unknown, unknown, unknown, any> | ||
| ): boolean { | ||
| return 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 update the comment to explain why we set it to return false?
| } | ||
|
|
||
| getCookie(request: OpenSearchDashboardsRequest, authInfo: any): SecuritySessionCookie { | ||
| return {}; |
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 not return cookie here?
|
@Ohasumi Would you upload a screen recording of this feature in action? Will help understand the setup much better. |
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.
Hi @Ohasumi , thanks for taking this on. I just left some general comments/questions. Also we may need to consider adding some unit/integration tests.
| @@ -0,0 +1,120 @@ | |||
| ### Required environment for Kerberos authentication ### | |||
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.
+1
| }), | ||
| kerberos: schema.object({ | ||
| jwt_siging_key: schema.string({ | ||
| defaultValue: 'secret share between opensearch and dashboards', |
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.
+1
This is a placeholder, but defaults like this should never be hardcoded in production
| }, | ||
| }); | ||
| } else { | ||
| return response.unauthorized({ |
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.
In handleUnauthedRequest the WWW-Authenticate: 'Negotiate' header is only added on failure in routes. Consider adding it proactively in the handler for API requests to trigger browser negotiation.
| // clear session | ||
| this.sessionStorageFactory.asScoped(request).clear(); | ||
| const payload = { | ||
| exp: Date.now() + this.config.session.ttl, |
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.
Just being curious: do we need to a refresh mechanism for long-lived scenario?
| } catch (error) { | ||
| context.security_plugin.logger.error(`Failed authentication: ${error}`); | ||
| return response.unauthorized({ | ||
| body: `Kerberos authentication failed ${error}`, |
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.
Will this leak the stack trace when it fails? - if it has the stack trace, then we may need to intentionally blur/hide it.
| default_tenant: user.default_tenant, | ||
| }; | ||
|
|
||
| const encodedCredentials = sign(payload, this.config.kerberos.jwt_siging_key); |
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.
Consider add a error handling for sign() - wrap with a try/catch
| } | ||
|
|
||
| // clear session | ||
| this.sessionStorageFactory.asScoped(request).clear(); |
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.
this logout route clears session but doesnt invalidate the JWT. Since this JWTs are stateless, do we need a revocation for the actual token?
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.
Hi @Ohasumi , thanks for taking this on. I just left some general comments/questions. Also we may need to consider adding some unit/integration tests.
|
Also is this only for version |
Description
Add Kerberos authentication feature on opensearch-dashboard
Category
New feature
Why these changes are required?
This add version will add feature to authentication by Kerberos via SPNEGO. So user can login without need password in environment that Kerberos are existed.
What is the old behavior before changes and new behavior after changes?
This only make change to enable new authentication method
Issues Resolved
Testing
Integration testing by using google chrome setting policy to enable [AuthServerAllowlist] for dashboards server with both client and server are communicate with Kerberos server.
[Please provide details of testing done: unit testing, integration testing and manual testing]
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.