elastic / kibana

Your window into the Elastic Stack
https://www.elastic.co/products/kibana
Other
19.77k stars 8.17k forks source link

[Actions] Research on the different OAuth authentication flows to find the best fits for the actions API functionality. #79372

Closed YulNaumenko closed 2 years ago

YulNaumenko commented 4 years ago

A Client has requested support for OAuth authentication feature in the ServiceNow and Webhook connectors. Their security requirements do not allow the use of user credentials as a means of authentication for connectors to ServiceNow, Webhook.

Cost of delay: This is turns out to be a blocker for their adoption of ESS given we don't have a way to support OAuth.

I've investigated how it could be done for ServiceNow in the REST API: https://docs.servicenow.com/bundle/paris-platform-administration/page/administer/security/concept/c_OAuthAuthorizationCodeFlow.html

Some research on OAuth error paths that we can use to figure out how to deal with, diagnose, remediate errors: https://github.com/elastic/kibana/issues/109919

Update (11/04/2021): The resent research come up with the alternative approach to the OAuth Authorization Code Flow - OAuth JSON Web Token flow, which is better designed and fitted for our server to external server communication. The details could be found in the POC description https://github.com/elastic/kibana/pull/117469

elasticmachine commented 4 years ago

Pinging @elastic/kibana-alerting-services (Team:Alerting Services)

YulNaumenko commented 3 years ago

Usually OAuth 2.0 requires a 3 steps before a getting an access and refresh tokens. There is a question - to which part of the connector flow a retrieving of an access token should belongs to? I've tried to add a configuration option to the ServiceNow connector useOAuth which turn off a basic authorization fields and require from the user to enter a client ID:

Screen Shot 2020-12-17 at 3 16 24 PM

But what should happens after?

  1. Save the connector and then use this connector configuration info in the action execution, where first do a 3 requests to get oauth token:
    • https://myinstance.servicenow.com/oauth_auth.do?response_type=code&redirect_uri={the_redirect_url}&client_id={the_client_identifier}
    • https/http://{callbackURL}?code={the actual auth code} What URL can be a callbaclURL?
    • https://myinstance.servicenow.com/oauth_token.do?grant_type=authorization_code&code={the auth code}&redirect_uri={the_same_redirect_url}&client_id={the_same_client_identifier}&client_secret={client_secret_value} and then do a ServiceNow API call with this token : https://myinstance.service-now.com/api/now/table/incident?access_token={the_token} It seems to be not optimal oauth implementation.
  2. We can have this get access and refresh tokens as a part of the create connector flow and save then it both as a secrets. The problem here, that we should update the connector secrets if access token is expired: Screen Shot 2020-12-17 at 3 20 49 PM
  3. Maybe some generic OAuth support for all action types?

Additionally: Enterprise Search has a ConfigureOAuth component

pmuellr commented 3 years ago

Have we talked to security folks about this? They likely have some thoughts.

I'd think anything involving a callback url BACK to Kibana will end up being problematic. Might work for some deployments, but one obvious problem is Kibana instances not visible on the public internet - servicenow wouldn't be able to connect to invoke the callback url. I think right now, cloud deployments are publicly visible, however who knows - we might end up supporting some story for cloud where deployments could be exposed through a customer's VPN, which would make them not publicly visible again.

The option of using a refresh token and access token seem like they could work, but would we store the access token in the secrets? That doesn't quite seem right, since in theory ANY actionType might want to use OAUTH access.

I wonder if the access and refresh tokens would be better stored elsewhere, like where we plan to store per-action/server/whatever TLS options.

YulNaumenko commented 3 years ago

@elastic/kibana-security any thoughts or existing tools to support OAuth on the Kibana level?

azasypkin commented 3 years ago

@elastic/kibana-security any thoughts or existing tools to support OAuth on the Kibana level?

Unfortunately we don't have anything OIDC related in Kibana that you could leverage for your use case since heavy lifting and back channel communication is done on the Elasticsearch side.

Having said that I'm not sure if you really need to deal with any OAuth flows that involve browser/callbacks, it seems what you really need is Client Credentials Grant/Flow, when Kibana server sends client_id and client_secret to the Authorization server and get the access token back. Am I missing something?

YulNaumenko commented 3 years ago

ServiceNow REST OAuth support https://docs.servicenow.com/bundle/paris-application-development/page/integrate/inbound-rest/reference/r_RESTOAuthExample.html

pmuellr commented 3 years ago

Cool, that SN Rest OAuth looks like the usual refresh/access token flow, no need for a callback. I expect a lot of APIs that support "OAuth" will work this way.

I guess what we should do is add all the OAuth goodness to the SN connector first, the next connector that needs this, we can then abstract that out into a reusable set of modules.

We need to think about:

YulNaumenko commented 3 years ago

Blocked by https://github.com/elastic/kibana/issues/80120

pmuellr commented 3 years ago

I'm wondering how many other actions could be affected, besides ServiceNow and webhook. Thinking that these might also need it: Jira, IBM Resilient, PagerDuty, MS Teams. Presumably we can enable these as needed, by adding the appropriate code in the actions plugins / ui.

Do we need a management interface for this? Something to list the current OAuth grants, allow them to be "deleted / invalidated" (for security / off-boarding use cases), or to explicitly refresh them? And in general, just to see what grants are being used. I don't think we would be "creating" them here, they would get created when an action specifies it wants to auth with OAuth instead of user/pass.

If we store the grant info in a SO, presumably it would be keyed off the connector id. Which means after a connector is deleted, we should also delete the grant info SO. We could do this specifically in the connector delete logic - not sure if there's a reason why we would want to keep an old version around. What happens if a user switches from user/pass to OAuth then back to user/pass then back to OAuth - should we keep all the OAuth info around? Seems like we probably would.

YulNaumenko commented 3 years ago

No blocking on #80120 Blocked by https://github.com/elastic/kibana/issues/94768

YulNaumenko commented 2 years ago

Based on the comparison of the different OAuth flows which supports server-to-server communication (not require a user consent interaction like OAuth Authorization Code flow), without a complicated handling of the access/refresh tokens lifetime bottlenecks, meets the customers security requirements (not use OAuth password grant type) and supported by the major of the systems integrations we have in our connectors the two OAuth flow should be implemented: