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

Migrate the rest of the API endpoints to the New Platform plugin #50695

Merged
merged 4 commits into from
Dec 11, 2019

Conversation

azasypkin
Copy link
Member

@azasypkin azasypkin commented Nov 14, 2019

In this PR, I'm moving the rest of the API endpoints to the New Platform:

  • api keys (done)
  • indices routes (done)
  • users routes (done)
  • authentication routes (done)

NOTE: It'd be much easier to review PR commit by commit.

Fixes: #43258


"Release note: /api/security/v1/me endpoint is deprecated and will be completely replaced with internal-use-only endpoint in the next major version."

"Release note: /api/security/v1/logout endpoint is deprecated in favor of /api/security/logout and will be removed completely in the next major version. Please make sure to switch any Single sign-on providers you use with Kibana to /api/security/logout instead."

"Release note: /api/security/v1/oidc/implicit endpoint is deprecated in favor of /api/security/implicit and will be removed completely in the next major version. Please make sure to switch Elasticsearch and any OpenID Connect providers you use with Kibana to /api/security/implicit instead."

"Release note: support of Third-Party Initiated login via /api/security/v1/oidc endpoint is deprecated and will be removed completely in the next major version. Please make sure to switch OpenID Connect providers you use with Kibana for Third-Party Initiated login to /api/security/initiate_login instead."

@azasypkin azasypkin added Team:Security Team focused on: Auth, Users, Roles, Spaces, Audit Logging, and more! Feature:NP Migration labels Nov 14, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-security (Team:Security)

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@@ -5,8 +5,7 @@
*/

import { kfetch } from 'ui/kfetch';
import { ApiKey, ApiKeyToInvalidate } from '../../common/model/api_key';
import { INTERNAL_API_BASE_PATH } from '../../common/constants';
Copy link
Member Author

Choose a reason for hiding this comment

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

note: tbh I don't see much value in INTERNAL_API_BASE_PATH constant and it makes it harder to copy-paste URL to find where it's defined. But let me know if you prefer to have it.

Copy link
Member

Choose a reason for hiding this comment

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

I'm in favor of removing this as well. I enjoy being able to search on full API paths in code

@@ -39,7 +39,7 @@ const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD';
/**
* The Kibana server endpoint used for authentication
*/
const LOGIN_API_ENDPOINT = '/api/security/v1/login';
const LOGIN_API_ENDPOINT = '/internal/security/login';
Copy link
Member Author

@azasypkin azasypkin Nov 27, 2019

Choose a reason for hiding this comment

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

question: @andrew-goldstein, this code looks a bit suspicious to me, I'd love to hear what it's doing and why? Or is it just test only code?

P.S. I don't see that anyone owns this plugin in .github/CODEOWNERS.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@azasypkin azasypkin marked this pull request as ready for review November 27, 2019 18:35
@azasypkin azasypkin requested a review from a team as a code owner November 27, 2019 18:35
@@ -4,576 +4,573 @@
* you may not use this file except in compliance with the Elastic License.
*/

(function (root, factory) {
Copy link
Member Author

Choose a reason for hiding this comment

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

note: just removed this part and run the rest of the file through prettier.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

getLegacyAPI,
basePath,
}: RouteDefinitionParams) {
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
Copy link
Member Author

@azasypkin azasypkin Nov 29, 2019

Choose a reason for hiding this comment

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

note: lots of BWC tricks in this file, but while I'm here I wanted to clean it up.....

createLicensedRouteHandler(async (context, request, response) => {
const serverBasePath = basePath.serverBasePath;
if (path === '/api/security/v1/logout') {
logger.warn(
Copy link
Member

@legrego legrego Dec 9, 2019

Choose a reason for hiding this comment

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

What do you think about integrating this with the upgrade assistant in a followup PR? I think it'd be helpful for folks when upgrading to the next major version if we make it known that something in their environment is relying on this deprecated endpoint.

To say this another way, I'd personally be annoyed if I ran the upgrade assistant, and it didn't warn me that this would stop working if I was relying on it 😄

Comment applies to the other deprecated endpoints as well

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a great idea! I'll try to figure how hard/easy it would be. I tried it once in the distant past and UA wasn't ready for things like this back then, but I believe it's much more advanced now.

Copy link
Member

@legrego legrego left a comment

Choose a reason for hiding this comment

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

Looks great overall. Just a couple minor questions/nits on my end so far

validate: { query: schema.object({}, { allowUnknowns: true }) },
options: { authRequired: false },
},
createLicensedRouteHandler(async (context, request, response) => {
Copy link
Member

Choose a reason for hiding this comment

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

The LP implementation for login/logout endpoints did not perform license checks. I think it makes sense to add it for our login routes, but what do you think about removing the check for the logout endpoints? It's an edge-case for sure, but I worry about blocking logout if there is a hiccup with Kibana's view of the current license.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that's a good point, thanks! I'll remove license check from here.

{ path: '/internal/security/me', validate: false },
createLicensedRouteHandler(async (context, request, response) => {
try {
return response.ok({ body: (await authc.getCurrentUser(request)) as any });
Copy link
Member

Choose a reason for hiding this comment

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

note: authc.getCurrentUser performs an additional round-trip to ES to retrieve the user details. The previous implementation did not have to do this, likely because of the intimate relationship it had with Hapi.

I don't think anything has to change here, but as we move the client-side security plugin to. the NP, we should evaluate all the places we are calling this endpoint. I recall seeing several calls as the page loads which we can likely trim down.

Copy link
Member Author

Choose a reason for hiding this comment

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

authc.getCurrentUser performs an additional round-trip to ES to retrieve the user details. The previous implementation did not have to do this, likely because of the intimate relationship it had with Hapi.

Yep, that's correct.

I don't think anything has to change here, but as we move the client-side security plugin to. the NP, we should evaluate all the places we are calling this endpoint. I recall seeing several calls as the page loads which we can likely trim down.

If it becomes a perf problem for us, we'll ask platform to expose existing auth information to plugins: security plugin returns user info to core, core stores it in the internal cache, but just doesn't expose it for now.

validate: {
query: schema.object(
{
authenticationResponseURI: schema.maybe(schema.string({ minLength: 1 })),
Copy link
Member

Choose a reason for hiding this comment

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

question: is there a reason authenticationResponseURI can't be validated via schema.uri() like error_uri is below?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, I don't think there is a reason, just an oversight 🙈 Will fix.

target_link_uri: schema.maybe(schema.uri()),
state: schema.maybe(schema.string()),
},
{ allowUnknowns: true }
Copy link
Member

Choose a reason for hiding this comment

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

nit: unrelated to the migration, but can we add a comment explaining why we want to allow unknown object properties here? We're trying to reduce the number of places this is required in code, so documenting legitimate uses will be helpful going forward.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, added comments in all 3 places in this file.

loginAttempt: ProviderLoginAttempt
) {
try {
// We handle the fact that the user might get redirected to Kibana while already having an session
Copy link
Member

Choose a reason for hiding this comment

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

super-nit

Suggested change
// We handle the fact that the user might get redirected to Kibana while already having an session
// We handle the fact that the user might get redirected to Kibana while already having a session

if (authenticationResult.succeeded()) {
return response.forbidden({
body:
'Sorry, you already have an active Kibana session. ' +
Copy link
Member

Choose a reason for hiding this comment

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

This can be done in a followup since it also existed in LP, but we should internationalize this message.

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 was hesitating to translate error messages as users usually copy-paste-google for similar cases. But this one is clear enough and actionable by itself, so agree we can translate it. Will fix in this PR.

}

router.get(
{ path: '/internal/security/me', 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.

How do you feel about also keeping /api/security/v1/me around for the remainder of 7.x? Although it's not part of our public API, we have instructed both users and customers about this endpoint for quite some time, and I fear we'll break a lot of "custom" configurations by removing this endpoint.

Copy link
Member Author

@azasypkin azasypkin Dec 10, 2019

Choose a reason for hiding this comment

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

Hmm, interesting, didn't know that. I can definitely keep it in 7.x. Also what was the use case for customers/users? Would it justify having this as a public API?

Copy link
Member

Choose a reason for hiding this comment

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

Also what was the use case for customers/users? Would it justify having this as a public API?

I believe there are some custom/third-party plugins which use this endpoint. At the very least, we've put it out there in the public:

export function defineCreateOrUpdateUserRoutes({ router, clusterClient }: RouteDefinitionParams) {
router.post(
{
path: '/internal/security/users/{username}',
Copy link
Member

Choose a reason for hiding this comment

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

It looks like we have a couple references to the old endpoint here

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, good catch, it's a brand new script! Will fix.

…ep `/api/security/v1/me` in 7.x, validate OIDC `authenticationResponseURI` as a proper URI, explain the need for `allowUnknowns` in OIDC routes validation, localize error message, update APM dev script with new `users` internal routes.
@azasypkin azasypkin requested a review from a team as a code owner December 10, 2019 11:40
{ path, validate: false },
createLicensedRouteHandler(async (context, request, response) => {
if (path === '/api/security/v1/me') {
logger.warn(
Copy link
Member Author

Choose a reason for hiding this comment

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

note: Assuming we make this route internal I don't mention the name of the internal route as we don't provide any guarantees regarding it.

@azasypkin
Copy link
Member Author

@legrego thanks for the review! PR is ready for another pass.

Copy link
Member

@sorenlouv sorenlouv left a comment

Choose a reason for hiding this comment

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

APM changes LGTM

Copy link
Member

@legrego legrego left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the changes! I only tested basic and token auth providers locally -- let me know if you'd like me to test any additional auth providers

@azasypkin
Copy link
Member Author

I only tested basic and token auth providers locally -- let me know if you'd like me to test any additional auth providers

Thanks for review and testing! I believe we're good, I tested OIDC and SAML locally as well and we have a good number of integration tests I believe. If we figure out that I broke something, then I'll add even more integration tests. Testing everything manually is hard and tedious and if we can't rely enough on the test coverage we built it's not going to scale anyway 🙈

@azasypkin
Copy link
Member Author

7.x/7.6.0: bb8e383

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@chrisronline
Copy link
Contributor

It looks like this moved the shield plugin. Is it possible to still use this within the old platform?

@azasypkin
Copy link
Member Author

It looks like this moved the shield plugin. Is it possible to still use this within the old platform?

@chrisronline Technically you can still import x-pack/plugins/security/server/elasticsearch_client_plugin.ts directly, but I'd like to understand what you need this for and whether Security plugin can expose necessary functionality through its contracts?

P.S. The latest version of elasticsearch.js has a different extension/plugin model anyway, so you may need to migrate once again when Kibana switches to it.

@chrisronline
Copy link
Contributor

Good question.

I spoke with @kobelb about some other code and he mentioned we shouldn't use transport.request, and that the alternative is using this shield plugin. But looking at the elasticsearch.js apis, we can just use https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#_security_hasprivileges, right @kobelb?

@kobelb
Copy link
Contributor

kobelb commented Dec 18, 2019

Are we using the non-legacy Elasticsearch client already?

@azasypkin
Copy link
Member Author

Are we using the non-legacy Elasticsearch client already?

You mean @elastic/elasticsearch? If so, then not yet, I see we only have @elastic/elasticsearch as a dev dependency and #27051 stalled as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backported Feature:NP Migration release_note:deprecation Team:Security Team focused on: Auth, Users, Roles, Spaces, Audit Logging, and more! v7.6.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle 3rd party initiated login in OIDC in a different endpoint
6 participants