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

[Synthetics] Make core API key include read_ilm privilege in Stateful only #178897

Conversation

justinkambic
Copy link
Contributor

@justinkambic justinkambic commented Mar 18, 2024

Summary

Resolves https://github.com/elastic/synthetics-dev/issues/332.

ILM is not a concept in Serverless. As such, when the Synthetics plugin requests the read_ilm permission for its core API key during bootstrapping, it's asking for a priv that will eventually not exist on Serverless, and ES will give an explicit deny for the request, which will probably cause Synthetics to crash and not be functional.

The fix is to detect the build type at startup time and enable the server plugin to determine whether it needs to include this privilege or not, based on whether Kibana is running in stateful or serverless mode.

Testing

You can easily test this in both modes. The steps are the same.

NOTE: when testing serverless, if you include the flag -E xpack.security.authz.has_privileges.strict_request_validation.enabled=true this will simulate the manner in which Elasticsearch will explicit deny the API creation request when this is enabled in the MKI environment, and thus you should include it in your testing.

  1. Start up Kibana in serverless | stateful mode.
  2. As an admin, navigate to Synthetics and wait for the startup flow to display.
  3. Navigate to Kibana management's API key page. You should see the Synthetics API key. Click it.
  4. For stateful, you should see read_ilm included under the synthetics_writer object, shown below. For serverless, you should not see this priv in the list.

Stateful API key perms

image

Serverless API key perms

image

@justinkambic justinkambic added the Team:obs-ux-infra_services Observability Infrastructure & Services User Experience Team label Mar 18, 2024
@justinkambic justinkambic self-assigned this Mar 18, 2024
@apmmachine
Copy link
Contributor

🤖 GitHub comments

Expand to view the GitHub comments

Just comment with:

  • /oblt-deploy : Deploy a Kibana instance using the Observability test environments.
  • /oblt-deploy-serverless : Deploy a serverless Kibana instance using the Observability test environments.
  • run elasticsearch-ci/docs : Re-trigger the docs validation. (use unformatted text in the comment!)

@justinkambic justinkambic added release_note:skip Skip the PR/issue when compiling release notes v8.14.0 labels Mar 18, 2024
@justinkambic justinkambic force-pushed the 332/only-request-ilm-api-key-perms-for-non-serverless-builds branch 3 times, most recently from 2e33341 to 0f78371 Compare March 18, 2024 19:05
@justinkambic justinkambic marked this pull request as ready for review March 18, 2024 19:06
@justinkambic justinkambic requested a review from a team as a code owner March 18, 2024 19:06
@elasticmachine
Copy link
Contributor

Pinging @elastic/obs-ux-infra_services-team (Team:obs-ux-infra_services)


export const checkHasPrivileges = async (
server: SyntheticsServerSetup,
apiKey: { id: string; apiKey: string }
) => {
const { isServerless } = server;
const { indices: index, cluster } = getServiceApiKeyPrivileges(isServerless);
return await server.coreStart.elasticsearch.client
Copy link
Contributor

Choose a reason for hiding this comment

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

It's not related to your changes but this await is not necessary neither the async declaration. As the server.coreStart.elasticsearch.client returns a promise the checkHasPrivileges client is the one that needs to await the response.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally agree, wish Kibana had a rule on unneeded async/await. I have this lint rule in the recorder and it makes the code a lot cleaner IMO.

I didn't notice it as I wasn't paying attention to the code around the bits I needed to modify.

I've also updated the function below this as it suffers from the same unneeded sugar.

635854b96805f29452cabc0a7dcb2a9a5194f6dc

},
],
run_as: [],
export const getServiceApiKeyPrivileges = (isServerless?: boolean) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I reason why to accept undefined (isServerless?:) here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -57,6 +57,7 @@ export interface SyntheticsServerSetup {
uptimeEsClient: UptimeEsClient;
basePath: IBasePath;
isDev?: boolean;
isServerless?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

Also here why do we define it as possible undefined? I think this should be just true/false

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, this is fair. For flags like this that are based on config or some upstream dependency a lot of times I default to making them optional. But the code that sets this flag will always return a boolean, so it does make sense to make this field more opinionated. Just like the isDev flag above this one could also be optional.

I've also changed the assertions on this flag from general truthy/falsey to explicit boolean assertion.

8ddc360658faa4ff161b2f24829df4797ec950c2

Copy link
Contributor

@cauemarcondes cauemarcondes left a comment

Choose a reason for hiding this comment

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

LGTM

@justinkambic justinkambic requested a review from a team as a code owner March 19, 2024 16:06
@jeramysoucy jeramysoucy self-requested a review March 20, 2024 11:54
@justinkambic justinkambic force-pushed the 332/only-request-ilm-api-key-perms-for-non-serverless-builds branch from a88b48e to a26c0d1 Compare March 20, 2024 15:31
Copy link
Contributor

@jeramysoucy jeramysoucy left a comment

Choose a reason for hiding this comment

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

Kibana security changes LGTM. Just one question on serverless integration test coverage. Also, I was unable to test manually due to lack of knowledge.
In the second step "As an admin, navigate to Synthetics and wait for the startup flow to display." I am not sure what this means. When I navigate to Synthetics I see this:
Screenshot 2024-03-20 at 11 28 51 AM

I tried creating an agent policy and location, but the API keys generated did not contain the synthetics writer section. How do I generate the synthetics API key?

@@ -74,7 +74,7 @@ export default function ({ getService }: FtrProviderContext) {
],
elasticsearch: {
cluster: [privilege],
indices: serviceApiKeyPrivileges.indices,
indices: getServiceApiKeyPrivileges(false).indices,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we implement equivalent serverless api integration tests where we pass true?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I'm in the process of planning this with the Synthetics-on-Serverless team. I will likely do this in a separate PR that focuses just on implementing this. There will likely be other stuff that needs to change and it won't be a simple lift-and-shift. This will explode the delta for this change to many times its current size and require review burden from some additional folks who aren't on this PR already. Synthetics still isn't live in Prod, so nothing we do will impact existing early adopters, and we will likely include the API tests as acceptance criteria for switching on the plugin.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the second step "As an admin, navigate to Synthetics and wait for the startup flow to display." I am not sure what this means. When I navigate to Synthetics I see this:

Synthetics is designed to work with our managed SaaS testing locations by default. Locally, if you haven't run an instance of this service alongside your Kibana and configured them to talk to each other (requires Minikube and some extra setup), you'll be prompted to create your own "private" location, which involves enrolling an agent in Fleet and creating some config.

I tried creating an agent policy and location, but the API keys generated did not contain the synthetics writer section. How do I generate the synthetics API key?

To see this work locally end-to-end you'd need to also set up Fleet. The way we've done this in the past is via the elastic-package's stack up command. It's not super fun to get that working locally, however. The best way to test things end-to-end would be to deploy this PR to cloud QA. LMK if you'd like me to spin one up so you can see it working. This way you'd avoid having to set these things up manually on your local system.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do apologize, the testing steps require some knowledge of running Synthetics locally. I'll spin up a cloud instance of this patch so we can see it work in cloud.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, Justin! I don't think it's necessary to spin up a serverless instance - I trust the other reviewers have given this a thorough testing, I just wanted to understand why I wasn't seeing what I thought I should - I don't have any experience with synthetics. This makes sense to me now. I appreciate the time you took to explain.

And thank you for the follow up re:tests. Is there an open issue for this work already?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not yet, I will make the ticket before I merge this though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Issue is linked. I will probably merge later today, or tomorrow morning.

@justinkambic
Copy link
Contributor Author

/oblt-deploy

@justinkambic justinkambic force-pushed the 332/only-request-ilm-api-key-perms-for-non-serverless-builds branch from a26c0d1 to 49f356e Compare March 21, 2024 17:56
@justinkambic
Copy link
Contributor Author

@jennypavlova @cauemarcondes could you please give another review, after speaking to the Kibana team this is the way they recommend handling Elasticsearch capability-related considerations when determining if we need to adjust for Serverless or not.

server: SyntheticsServerSetup,
apiKey: { id: string; apiKey: string }
) => {
return await server.coreStart.elasticsearch.client
const { indices: index, cluster } = getServiceApiKeyPrivileges(
server.coreStart.elasticsearch.getCapabilities().serverless
Copy link
Contributor

Choose a reason for hiding this comment

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

@justinkambic could we keep exposing the isServerless in the SyntheticsServerSetup definition? this is a long chain of functions to remember to check if it serverless or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cauemarcondes the Kibana team stressed that Kibana's buildFlavor and es capabilities (which is basically Elasticsearch's build flavor) should be treated as two separate things. It's a bit pedantic but the two aren't synonymous and there's no way to know if there will be important differences in the future.

I agree that this implementation isn't great because of the lengthy call chain, and it's not DRY, so we should improve it as you suggest. I can add an isEsServerless flag to the plugin class and reference it in the server object that gets injected in place of this. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@justinkambic justinkambic force-pushed the 332/only-request-ilm-api-key-perms-for-non-serverless-builds branch from b2d9433 to 30ddac0 Compare March 22, 2024 14:25
Copy link
Contributor

@cauemarcondes cauemarcondes left a comment

Choose a reason for hiding this comment

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

LGTM

@justinkambic justinkambic enabled auto-merge (squash) March 22, 2024 15:15
@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

  • 💛 Build #198801 was flaky b2d94335df995f4171037782d9c7518e3006e9d9
  • 💚 Build #198548 succeeded a26c0d1691ac94164b4dee27a9047a4d8ba5d300
  • 💔 Build #198321 failed a88b48e8e87bf0ee4f5b876bef91768dd2d9329e
  • 💔 Build #198300 failed 8ddc360658faa4ff161b2f24829df4797ec950c2

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

cc @justinkambic

@justinkambic justinkambic merged commit 15fde36 into elastic:main Mar 22, 2024
18 checks passed
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Mar 22, 2024
@justinkambic justinkambic deleted the 332/only-request-ilm-api-key-perms-for-non-serverless-builds branch March 22, 2024 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:obs-ux-infra_services Observability Infrastructure & Services User Experience Team v8.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants