Skip to content

Conversation

@Ohasumi
Copy link

@Ohasumi Ohasumi commented Dec 5, 2024

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

  • New functionality includes testing
  • New functionality has been documented
  • Commits are signed per the DCO using --signoff

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.

@cwperks
Copy link
Member

cwperks commented Dec 6, 2024

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

codecov bot commented Dec 6, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 71.46%. Comparing base (ef72c90) to head (141797e).

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.
📢 Have feedback on the report? Share it here.

@Ohasumi
Copy link
Author

Ohasumi commented Dec 10, 2024

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?

@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.

@cwperks
Copy link
Member

cwperks commented Dec 10, 2024

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?

@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?

@Ohasumi
Copy link
Author

Ohasumi commented Dec 11, 2024

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?

@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.

Copy link
Member

@DarshitChanpura DarshitChanpura left a 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:

  1. Please open an issue describing this feature.
  2. Please update the title of this PR to be more descriptive.
  3. Please sign all your commits to pass the DCO check.

Thank you for your contribution!

Ohasumi added 8 commits March 9, 2025 20:50
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]>
@DarshitChanpura DarshitChanpura changed the title 2.18 Add Kerberos authentication feature Jun 9, 2025
}),
kerberos: schema.object({
jwt_siging_key: schema.string({
defaultValue: 'secret share between opensearch and dashboards',
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 change the default value to be empty?

Copy link
Collaborator

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

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

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: '/',
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 redirect to the url passed in nextUrl query param.

@@ -0,0 +1,120 @@
### Required environment for Kerberos authentication ###
Copy link
Member

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.

Copy link
Collaborator

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

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;
}
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 update the comment to explain why we set it to return false?

}

getCookie(request: OpenSearchDashboardsRequest, authInfo: any): SecuritySessionCookie {
return {};
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 not return cookie here?

@DarshitChanpura
Copy link
Member

@Ohasumi Would you upload a screen recording of this feature in action? Will help understand the setup much better.

Copy link
Collaborator

@RyanL1997 RyanL1997 left a 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 ###
Copy link
Collaborator

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',
Copy link
Collaborator

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({
Copy link
Collaborator

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,
Copy link
Collaborator

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}`,
Copy link
Collaborator

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

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

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?

Copy link
Collaborator

@RyanL1997 RyanL1997 left a 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.

@RyanL1997
Copy link
Collaborator

Also is this only for version 2.18.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants