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

Example App with automatic tailored service account setup #203

Merged
merged 21 commits into from
Oct 23, 2023

Conversation

gamab
Copy link
Contributor

@gamab gamab commented Sep 27, 2023

In this PR, through a new example, we show how a plugin can get a dedicated service account and a token using the externalServiceRegistration attribute in its plugin.json.

For example, to allow a plugin to create dashboards, list/update all dashboards and folders, list users, teams, team members. The registration looks like this:

  "externalServiceRegistration": {
    "permissions": [
      { "action": "dashboards:create", "scope": "folders:uid:*" },
      { "action": "dashboards:read", "scope": "folders:uid:*"},
      { "action": "dashboards:write", "scope": "folders:uid:*"},
      { "action": "folders:read", "scope": "folders:uid:*"},
      { "action": "folders:write", "scope": "folders:uid:*"},
      { "action": "org.users:read", "scope": "users:*"},
      { "action": "teams:read", "scope": "teams:*"},
      { "action": "teams.permissions:read", "scope": "teams:*"}
    ]
  }

This is still an experimental feature (behind a feature flag) but can be used starting with Grafana v10.2.0.

Since v10.2.0 is not out yet, you'd need to run the docker-compose with latest main tag to test this now:

GRAFANA_VERSION=main docker-compose up

Special note to reviewers:

I shamelessly copied the app-with-on-behalf-flow example plugin.
I'm not entirely sure that's ok or if I should have ran init functions instead.

I also have in my backlog to update the plugin docs.

Ref for context:

https://github.com/grafana/grafana-enterprise/issues/5824

Example of requests with these permissions

Create a dashboards

POST /dashboards/db

{ "dashboard": { "title": "Plugin Dashboard" } }

Search dash & folders

GET /search

Modify an existing folder

PUT /folders/uid/:uid

{ "title": "Plugin Folder", "version": 1 }

List users

GET /org/users

List teams

GET /teams/search

List team members

GET /teams/1/members

@mckn mckn requested a review from andresmgot October 2, 2023 07:42
@mckn mckn requested review from a team and sunker and removed request for a team October 2, 2023 07:43
Copy link
Contributor

@sunker sunker left a comment

Choose a reason for hiding this comment

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

@gamab not entirely sure this PR was ready for review yet, but when trying it out locally I get the following error. So doesn't seem like the externalServiceRegistration from plugin.json is registered correctly?

Screenshot from 2023-10-02 11-28-03

The plugin uses a [Grafana service account token](https://grafana.com/docs/grafana/latest/administration/service-accounts/#service-account-tokens) to authenticate against the Grafana API. To enable it, add the section below to your `plugin.json` file.

```json
"externalServiceRegistration": {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know if this if documented somewhere? Could not find in the portal or grafana.com/docs.

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'll tackle that soon :)

@gamab
Copy link
Contributor Author

gamab commented Oct 2, 2023

Wow faster than ever 💯 No this is not up for review yet 🙏

If you want to test this out, I did a PoC branch in grafana, that I'm just now starting to split into smaller PRs to ease reviews and comments.

Here is the epic for context: https://github.com/grafana/grafana-enterprise/issues/5824 🙂

I already DMed @andresmgot but I still need to notify and talk with the plugin squad for full approval 🙂

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

For the future, it may makes sense to merge this example with the existing one (since they are very similar) and maybe through documentation explain how to use it in on-behalf-of mode or just with a service account

@gamab gamab changed the title Add a plugin example with automatic service account setup App with automatic tailored service account setup Oct 18, 2023
@gamab
Copy link
Contributor Author

gamab commented Oct 18, 2023

@andresmgot given we'd now use the CustomHeaderMiddleware, does it still make sense to merge the two examples?
How would merging go? 😄

@andresmgot
Copy link
Contributor

@andresmgot given we'd now use the BearerAuthMiddleware, does it still make sense to merge the two examples? How would merging go? 😄

yeah, I am not that convinced about that now. I guess it's better to error on the side of being more verbose and have two different examples. It will also be more convenient if both features follow a different release schedule.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are we actually meant to commit all these files? Should we git ignore them?

Copy link
Contributor

@andresmgot andresmgot Oct 19, 2023

Choose a reason for hiding this comment

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

yes, we should include them. These are needed to execute the different yarn scripts.

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

Anything else you are planning to add here? Is this ready for review?

context: ./.config
args:
# Points to an unreleased v10.1 version of Grafana
grafana_version: ${GRAFANA_VERSION:-10.0.3}
Copy link
Contributor

Choose a reason for hiding this comment

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

does this docker-compose work? we probably need to at least update the GRAFANA_VERSION

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No it does not. I need to understand and test this out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, fixed it, but since 10.2 is not out yet, I had to run on latest main :)

GRAFANA_VERSION=main docker-compose up

@gamab gamab marked this pull request as ready for review October 19, 2023 08:58
@gamab gamab requested review from andresmgot and sunker October 19, 2023 09:02
@gamab gamab changed the title App with automatic tailored service account setup App example with automatic tailored service account setup Oct 19, 2023
@gamab gamab changed the title App example with automatic tailored service account setup Example App with automatic tailored service account setup Oct 19, 2023
@andresmgot
Copy link
Contributor

Trying this with the docker-compose (using GRAFANA_VERSION=main) I am finding something weird. The default request is to /search. I have created a dashboard expecting this to return it but the response is empty:

Screenshot from 2023-10-19 12-10-55

I have modified the action to dashboards:* but still get no response. Is this a configuration issue or something else?

BTW, we should also update the other example (on-behalf-of) to adapt it to the new format. I guess there is hurry though since the new format is not released yet.

@gamab
Copy link
Contributor Author

gamab commented Oct 19, 2023

Trying this with the docker-compose (using GRAFANA_VERSION=main) I am finding something weird. The default request is to /search. I have created a dashboard expecting this to return it but the response is empty:

I did the same and it surprised me as well. It's something I wanted to discuss with my team. Service Accounts don't get Admin permissions on what they created 😢
Here is the faulty line of code: https://github.com/grafana/grafana/blob/main/pkg/services/dashboards/service/dashboard_service.go#L496

Meanwhile I guess, for this example to make more sense, we can add "action": "dashboards:read", "scope": "folders:uid:general" to the permissions.

Wdyt?

BTW, we should also update the other example (on-behalf-of) to adapt it to the new format. I guess there is hurry though since the new format is not released yet.

Yep 👍 It's at the bottom of the epic's task list. Do you want to do it?

@andresmgot
Copy link
Contributor

I did the same and it surprised me as well. It's something I wanted to discuss with my team. Service Accounts don't get Admin permissions on what they created 😢 Here is the faulty line of code: https://github.com/grafana/grafana/blob/main/pkg/services/dashboards/service/dashboard_service.go#L496

Meanwhile I guess, for this example to make more sense, we can add "action": "dashboards:read", "scope": "folders:uid:general" to the permissions.

Wdyt?

hmm, I am not sure I follow. The service account doesn't create the dashboard (I created it as an admin). I just want the service account to have permissions to list / get dashboards. I tried with { "action": "dashboards:read", "scope": "folders:uid:general"} and I am still unable to get the dashboards using /search. Also, I am not seeing any error in the logs related to that so I am not sure what's going on.

BTW, we should also update the other example (on-behalf-of) to adapt it to the new format. I guess there is hurry though since the new format is not released yet.

Yep 👍 It's at the bottom of the epic's task list. Do you want to do it?

Sorry, there was a typo in my message. I wanted to say there is no hurry, you can do that when you see fit, I just didn't want to forget.

@gamab
Copy link
Contributor Author

gamab commented Oct 20, 2023

Ah my apologies! My bad for the { "action": "dashboards:read", "scope": "folders:uid:general"} mistake. I had tested it locally but had forgotten to run yarn build so I was running with a previous test version of the permissions. 🤦

Thanks for the careful review! 💯

I investigated a bit more on why it was not working, this is an RBAC bug with the search function: https://github.com/grafana/grafana-enterprise/issues/5920

Hence I ended up granting broader permissions to the plugin. It should now work (and do more checkout the description).

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

LGTM! Tested and working fine 👍

@gamab gamab merged commit 8c8ddb5 into main Oct 23, 2023
22 checks passed
@gamab gamab deleted the gamab/appwithserviceaccount branch October 23, 2023 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

3 participants