Skip to content

[Question] Host Mapping of Create OBO Token Endpoint #3000

@RyanL1997

Description

@RyanL1997

0.0 Description

Transferring the previous conversation from the original OBO Authbackend PR to here. This is the issue to track some of the design aspects of host mapping for OBO Authentication.

1.0 Problem

If the service makes a call from a different host/IP address would current implementation of host mapping also come into the picture on that request?

2.0 Solutions

*Following example is provided by @cwperks *
Imagine the following roles_mapping

all_access:
  reserved: false
  hosts:
  - "127.0.0.1"
  description: "Maps local host requests to all_access"

read_only:
  reserved: false
  users:
  - "test-user-01"

2.1 Option 1: Host mapping is done during create token (This is the current design)

  • test-user-01 makes a request from 127.0.0.1 to create a token. Given the host mapping above, this token will be given the all_access role
  • test-user-01 gives the token to be used on their behalf
  • A service using the token makes a request from a different IP (207.64.12.198). Assuming hostmapping is done in step 1) then the request is done with all_access permissions

Pros:

  • Flexibility: Once a token is created, it can be used from any IP address or host, allowing for more flexible use-cases.
  • Predictability: The roles associated with the token remain constant, regardless of the IP address from which it's used.

Cons:

  • Less usage restriction: There's potential for misuse. For instance, if a user, who is trusted to make a request from a specific IP, shares their OBO token, any service can use that token with the roles attached to it.

2.2 Option 2: Host mapping is done when the token is utilized

  • test-user-01 makes a request from 127.0.0.1 to create a token. Host mapping is not considered here so the token will be given read_only role
  • test-user-01 gives the token to be used on their behalf
  • A service using the token makes a request from a different IP (e.g. 207.64.12.198). In this scenario the request would be done with read_only because 207.64.12.98 is not mapped to any roles

Pros:

  • Additional usage restriction: This approach restricts the effective capabilities of a token based on the location (IP) of the requester. Even if the user shares his token, a service from a non-trusted IP can't escalate its permissions.

Cons:

  • Complexity: Implementing and maintaining this kind of dynamic role checking can be more complex.
  • Unpredictability: The roles associated with a token might change based on the IP, which can be confusing for users and harder to troubleshoot.

3.0 Recommendation: Option 1 - Host mapping is done during create token

Firstly, from the usage perspective, the OBO authentication is aptly named, indicating its purpose: to be used on a user's behalf. Before invoking the endpoint to issue an OBO token, the current design mandates users to specify the particular 'service' for which this token will be utilized. Similarly, in the extension realm, the tokens have the aud as the audience claim to confine their application. Moreover, additional restrictions have been implemented to curtail the misuse of OBO tokens (original edge cases handling issue: #2891).

Secondly, considering the token's brief lifespan and its just-in-time essence, it's more logical to map roles during token creation. Continuously checking or remapping roles during token utilization becomes redundant given the token's fleeting validity period. With a default active duration of 5 minutes, extending to a maximum of 10 minutes, credentials are allocated precisely when required and only for the briefest necessary duration.

Lastly, revisiting the foundational principles, the primary objective of OBO authentication was to streamline the often complex user experience associated with configuring security permissions. Introducing option 2 brings in the unpredictability factor. If the roles tethered to a token are influenced by the IP address, it stands to confound users. They might logically expect consistent access rights, aligned with their initial token request, but could be caught off guard by alterations stemming from a changed IP. Such variability not only detracts from the intended user experience but also introduces layers of intricacy to the troubleshooting process. Discerning if disruptions originate from user missteps, system anomalies, or shifting IPs could evolve into a taxing endeavor.

In summary, OBO authentication stands as a formidable tool in our arsenal. Regardless of the particular methodology we adopt, comprehensive documentation is paramount, covering both operational guidance and potential risks linked to its activation. For further insights, please refer to the upcoming documentation issue: #3100.

4.0 Appendix

4.1 An experiment of option 1

  1. Objective:
    The primary aim of the experiment was to ascertain that the current OBO authentication's host mapping design adheres to the principle of "Host mapping being executed during token creation."
  2. Setup and Configuration:
    On Machine A, an OpenSearch cluster was established, configured to entertain external requests. This was achieved by modifying the network.host in the opensearch.yml file and ensuring port 9200's accessibility. In contrast, Machine B, distinct in its IP address, was readied to act as an external testing client.
  3. Test Execution:
    Once the cluster on Machine A was operational, an OBO token was generated using admin credentials. This token was then utilized on Machine B to send requests to the OpenSearch cluster on Machine A.
  4. Observations:
    The requests from Machine B were processed successfully. Despite the difference in IP addresses, Machine B could authenticate and operate as the admin user due to the OBO token. This outcome solidified the understanding that host mapping predominantly occurs during the token creation phase.

4.2 A potential implementation of option 2 (source code)
Since the the OnBehalfOfAuthenticator class is responsible for extracting credentials from an OBO token. We can incorporate the IP-based role determination during the token utilization within this class.

  1. Capture the Request IP Address: can use the RestRequest parameter in the extractCredentials method (source code). This IP address can then be passed to a role mapping function similar to mapRoles for current design.
    final ThreadContext threadContext = threadPool.getThreadContext();
    final TransportAddress remoteAddress = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS);
    
  2. Map Roles Based on IP Address: This role mapping function can be used to determine roles dynamically based on the requesting IP address.
  3. Update roles that was extracted in token's claim : we created a temp user and mapped host mapping, and then, we need to add this hostmapping into the extracted roles from the token's claim.
  4. Here's a conceptual change that can be made in the extractCredentials0 method (source code):
    // ... Existing Code ...
    
            final ThreadContext threadContext = threadPool.getThreadContext();
            final TransportAddress remoteAddress = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS);
    
            final boolean isTraceEnabled = log.isTraceEnabled();
            if (isTraceEnabled) {
                log.trace("Rest authentication request from {} [original: {}]", remoteAddress, request.getHttpChannel().getRemoteAddress());
            }
    
            // GET ROLES MAPPED TO HOST ADDRESS.
            User temp = new User("temp");
            Set<String> hostMappedRoles = mapRoles(temp, null);
    
            List<String> rolesFromClaims = extractSecurityRolesFromClaims(claims);
            rolesFromClaims.addAll(hostMappedRoles);
            String[] backendRoles = extractBackendRolesFromClaims(claims);
    
            final AuthCredentials ac = new AuthCredentials(subject, rolesFromClaims, backendRoles).markComplete();
    
    // ... Existing Code ...

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions