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

[Question] Service Account Specifications #2597

Closed
5 tasks done
Tracked by #2586
stephen-crawford opened this issue Mar 28, 2023 · 9 comments
Closed
5 tasks done
Tracked by #2586

[Question] Service Account Specifications #2597

stephen-crawford opened this issue Mar 28, 2023 · 9 comments
Assignees
Labels
triaged Issues labeled as 'Triaged' have been reviewed and are deemed actionable.

Comments

@stephen-crawford
Copy link
Contributor

stephen-crawford commented Mar 28, 2023

Problem Statement

This issue tracks specific design questions about Service Accounts.

$\textcolor{orange}{\textsf{Orange text is a header for a decision that is not made }}$
$\textcolor{teal}{\textsf{Teal text is a header for a decision that is made }}$
$\textcolor{violet}{\textsf{Violet text is the recommended option }}$
$\textcolor{lime}{\textsf{Lime text is the chosen option }}$

What type of REST requests are intended for extensions?
How does the Security Plugin interact with REST requests?
What is the current method of signifying things?

Action items decided on this issue:

  • How is extension registration tied to service accounts?
  • How is a service account represented inside of the Security Plugin?
  • Is a service account limited/different from normal internal account?
  • How can an extension use its service account?
  • Can an extension have more than one service account?

$\textcolor{teal}{\textsf{How is extension registration tied to service accounts?}}$

In order to make extension registration tied to service accounts, the obvious choice appears to be forcing the extension to check in with the Security Plugin.

Using this method, we can force an extension to request a service account from the Security Plugin during registration and make the extension responsible for tracking its account credentials.

On service startup, all extenesions are loaded, and scopes are validated.

For every extensions they make a call to enable or disable service accounts:

  1. If Enabled, create or return existing service account with 'Enabled: true'
  2. If Disabled, create or update existing service account with 'Enabled: false', do not return the account to OpenSearch core.

$\textcolor{teal}{\textsf{How is a service account represented inside of the Security Plugin?}}$

The current design implements service accounts in a similar manner to a standard internal user account. This extends to the storage of service accounts which places the service accounts inside the configuration index of the Security Plugin.

$\textcolor{teal}{\textsf{Is a service account limited/different from normal internal account?}}$

There are two main options for whether service accounts should be different from normal internal user accounts.

  1. $\textcolor{lime}{\textsf{Service accounts are basically the same as any other account}}$ The first option is for service accounts to be the same as any other account. Based on this option, service accounts would have the same attributes as any other account. They may possibly have an additional attribute mapped to them i.e. "service":"true" but otherwise there should be no specifications as to the types of properties a service account should have.
Pros Cons
Easy to implement May not need all of the normal properties
More flexibility for what accounts can do
Puts more responsibility on extension authors
  1. The second option is to restrict the properties associated with a service account. For example:

    • Service accounts are passwordless - you cannot login to OSD using a service account
    • Service accounts are mapped to at most 1 role
    • Service accounts cannot be assigned backend roles

This option adds specific requirements to service accounts and enforces rules based on an account's status. This option may still require the addition of new attributes such as the above mentioned service field.

Pros Cons
Least privileges Not clear why we need to restrict these
Less areas for a rouge extension to exploit

$\textcolor{teal}{\textsf{How can an extension use its service account?}}$

The current plan is for an extension to use its service account for:

  1. Authorization and authentication of requests the extension is performing on its own behalf
  2. Making configuration changes to the security settings associated with the extension
  3. Specifying the permissions of the extension

$\textcolor{teal}{\textsf{Can an extension have more than one service account?}}$

There are two main options for whether an extension should be able to have more than one service account.

  1. $\textcolor{lime}{\textsf{Extensions can only have one service account}}$ The first option is extensions to only be able to have a single service account. This option restricts extensions from having more than one service account and as a result makes it easier to track the roles associated with each extension. Because an extension cannot have multiple accounts, the Security Plugin will only have to deal with a single mapping of the extension id to the corresponding account.
Pros Cons
Only have to resolve a single service account May restrict things?
Easier to track roles and scopes Requires modification of the existing service account for changes to occur
  1. The second option is to allow an extension to have multiple accounts. This option complicates scenarios for registering an extension since the unique extension id could not automatically be used for a service account name. It also makes permissions management more complicated since multiple service accounts with multiple roles may need to be resolved for each extension request.
Pros Cons
Do not need to change existing service accounts Complicated permission resolution
Does not require enforcement of the service account creation process No clear use case

Flow Diagrams

  1. Extension Requests its Service Account (same as registration process)
flowchart TD
    A[Extension_1] -->|Install| B(Core ServiceAccountManager)
    B --> |getOrCreate ServiceAccount|C{Security Plugin}
    C -->| Check ServiceAccount| D[InternalUsers]
    D --> | ServiceAccount Exists | E(Response)
    D --> | ServiceAccount does not exist | F[Create ServiceAccount]
    F --> | Store ServiceAccount | D
    E --> | Return ServiceAccount Info | B
Loading
  1. Cluster administrator requests a list of all service accounts
flowchart TD
    A[Admin_1] -->|REST GET localhost:9200/_extensions/accounts/list| B(Core RestHandler)
    B --> |Forward to Security Plugin|C{Security Plugin}
    C -->| Authorize request| C
    C -->| Access internalUser Storage| D[InternalUsers]
    D --> | Iterate over accounts | D
    D --> | Build response list of all with 'Service' : 'true' | E[ResponseObject]
    E --> | Return ServiceAccount List | B
Loading
  1. Extension tries to execute a request
flowchart TD
    A[Extension_1] -->|Operation Request| B(Core)
    B --> | Redirect to ServiceAccountManager | C(Core ServiceAccountManager)
    C --> |getOrCreate ServiceAccount|D{Security Plugin}
    D -->| Check ServiceAccount| E[InternalUsers]
    E --> | ServiceAccount Exists | F(Response)
    F --> | Return ServiceAccount Info | D
    D --> | Authorize ServiceAccount | D
    D --> | Return Authorization | C
    C --> | Give 200 | B
    B --> | Execute Request | B
Loading
@stephen-crawford stephen-crawford self-assigned this Mar 28, 2023
@stephen-crawford stephen-crawford converted this from a draft issue Mar 28, 2023
@stephen-crawford stephen-crawford added the triaged Issues labeled as 'Triaged' have been reviewed and are deemed actionable. label Mar 28, 2023
@github-actions github-actions bot added the untriaged Require the attention of the repository maintainers and may need to be prioritized label Mar 28, 2023
@stephen-crawford stephen-crawford removed the untriaged Require the attention of the repository maintainers and may need to be prioritized label Mar 28, 2023
@cwperks
Copy link
Member

cwperks commented Mar 29, 2023

x-posting comment from PR: #2594 (comment)

  1. Service accounts are designated by a special property service on a user. If this property exists and is set to true than it is a service account.
  2. Service accounts can only be mapped to at most one role - that role will dictate how a service account token can interact with the cluster. This can be used to implement system indices - i.e. service account tokens scoped to a system index pattern can create, delete and modify the index.
  3. Service accounts cannot be mapped to backend roles
  4. Service accounts are passwordless and only become useful once a token is generated for the account
  5. internaluser APIs should account for service accounts
    • List internalusers should not include service accounts
    • Create internaluser prohibits creation of account
    • Delete internaluser prohibits deletion of account - once they are created programmatically on registration of extension they will exist and be useless until a token is created
    • Patch user/users prohibits patching the account
  6. There should be a convention in naming the role that can be associated with a service account. If by convention we have a service account named <extension/extensionId> then maybe a role can exist with the same name for quick retrieval?

Once the concept of the service account is introduced, an API to list service accounts should be created and we can also start linking it to the extensions use-case like you are doing here to create one on extension registration.

@stephen-crawford
Copy link
Contributor Author

Hi @cwperks, thank you for taking the time to cross post this. I think some of these we can leave till after the initial POC demonstrates the functionality of Service Accounts.

Right now, I am planning on the initial POC demonstrating:

  • Your point 1: I agree that having a flagging attribute for service accounts seems to be the most straightforward approach for handling them. It also allows us to store service accounts with normal user accounts at the expense of look up.
  • Your point 4: I am planning on the getOrCreateServiceAccount call from core returning an authentication header to the service account which core can then hand to the extension. This will not be clearly visible in the initial security PR but is still part of the plan.
  • Your point 6: I agree that having a convention for service accounts is necessary. For now, I plan to make use of the extensionUniqueId that each extension has as shown in core. I intend to use this as the "username" for the service account. I will also be using the same name as the role for a service account when it is created.

To your other points, I don't have any immediate implementations of them. I am not sure I understand the benefit of restricting service accounts to a single role or not allowing backend roles. What is the concern about allowing either?

Modifying the internalUsers API to not show Service Accounts sounds like a good idea (though a change that can come at a later date). Aside from from that why can't we allow for the other functionality? An extension could always request a new account if its account were deleted so I am not sure why we would prevent an administrator for interacting with service accounts.

@cwperks
Copy link
Member

cwperks commented Mar 29, 2023

@scrawfor99 Sounds good, for plugins requesting to create a system index do you think we can create a token as part of the bootstrap process (assuming the cluster admin grants installation of the extension) that extensions go through on startup? In addition to the extensionUniqueId, we could also consider namespacing the account like extensions/{extensionUniqueId} to make it clear from the username that its a service account. Thank you for considering cases where the service account token needs to be rotated. Since we are targeting AD as the first plugin to be converted to an extension, do you think we should focus on the AD use-case of writing to a system index? Are there examples of other plugins stashing the thread context to interact with a cluster outside of writing to their system index?

@stephen-crawford
Copy link
Contributor Author

Hi @cwperks, I think that your suggestion for the bootstrapping token process sounds like a good option. I will need to think about it a little more to hash out the specifics but I can prioritize it as the next aspect of the POC after initial implementation. I agree that we should prioritize AD use cases since that is the first scenario. I just wanted to take the opportunity to document some of the situations that had impacted design decisions thus far.

As far as cases of an extension stashing the thread context, my hope is that we can treat these scenarios identically to any other extension-originated request. I know it is a specialized case but my goal would be to abstract the handling in such a way that the actual operation the extension performs is largely irrelevant to the code. I will need to look more into AD soon to understand how it works better but for the time being, I am going off the assumption that we can treat all extensions interchangeably from the Security Plugin's POV.

@stephen-crawford
Copy link
Contributor Author

Hi @opensearch-project/security, I am going to make some executive decisions to try to drive these questions to a resolution. For each of the points below, I will be moving forward unless I hear objections by Monday 4/3.

  • How is extension registration tied to service accounts?: Extensions request a service account be created for them immediately on registration.
  • How is a service account represented inside of the Security Plugin?: Exactly like a user account except with the attribute "service: true".
  • Is a service account limited/different from normal internal account?: For now, I think service accounts can be the same as other internal accounts. If this proves to be an issue we can adjust as required.
  • How can an extension use its service account?: The service account will be what is authorized and authenticated against. It can be used in the same way as a normal user account.
  • Can an extension have more than one service account?: No. For the time being, this will be prevented since core will be requesting the service accounts for the extensions. Core will create service accounts based off of extensionUniqueIds and unless an extension were to have 2+ unique IDs--(it should not)--then an extension would never end up with more than service account.

@peternied
Copy link
Member

@scrawfor99 I think these are good starting points.

Q1: As users can be created via REST API. Can service accounts be created in this same way?

  • Seems like YES, I think this is great and we can circle back if we need to to restrict this more.

Q2: Are there new customer facing REST APIs that will need to be created?

  • Doesn't sound like it, seems like there will be interfaces inside of security to provide the tokens, but nothing additional is needed.

Q3: RE: Can an extension have more than one service account?

  • Sounds like we are implicitly forcing this by the nature of the generated name of the account - I think this is fine for our initial release. Lets make sure this name scheme and number limitation doesn't impact other designs, e.g. when we send back service account

@cwperks
Copy link
Member

cwperks commented Mar 30, 2023

@scrawfor99 See responses below. In general, I like the idea of introducing the concept of a service account that can be extended more generally outside of extensions alone, and for the extensions use-case I think we can create one automatically for extensions requesting reserved (system) indices - indices with special protections.

  1. Yes, though I'm not certain if all extensions will need them. Regardless, service accounts don't do anything until a token is issued for them so I don't see harm in creating for all extensions but not every extension will need one - maybe just the indices reserving indices.

  2. Yes and with certain restrictions that should be enforced, see prior comment: [Question] Service Account Specifications #2597 (comment) - I think a single role will make it clearer the scope of the service account token, but if you think that restriction isn't required then it should be sufficient. I'd like to hear your thoughts on use-cases for multiple roles for the service account.

  3. No service accounts != internal users. Refer to comment above.

  4. An extension uses a service account token that has permissions associated with it that allow it to specially interact with its reserved indices.

  5. No - single service account per extension, multiple tokens is allowed

@peternied
Copy link
Member

service accounts != internal users

@cwperks Service accounts are a new concept we are adding to support extensions requests that do not use on-behalf-of tokens, such as calling system indexes. As long as the extension can make a request with the account and the administrator can control the accounts permissions I think those are the requirements.

Are there requirements that are missing?

I think we could expand / alter the implementation after the initial release that could support different restrictions as you've mentioned.

@cwperks
Copy link
Member

cwperks commented Mar 30, 2023

@peternied That works for me. I agree that we should first target getting a token to an extension and showing the token utilizing the token to interact with its system index. I think there will need to be a way to identify that the token being utilized is from a service account so that https://github.com/opensearch-project/security/blob/main/src/main/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluator.java#L124-L128 can be modified to permit the request coming from a service account that owns the index.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triaged Issues labeled as 'Triaged' have been reviewed and are deemed actionable.
Projects
Status: Done
Development

No branches or pull requests

3 participants