You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 27 Next »

IDIEP-129
Author
SponsorUnknown User (nizhikov) 
Created 10.09.2024
Status

ACTIVE


Motivation

Ignite provides a few options to set custom attributes on client side - per call (ServiceCallContext) or per connection (UserAttributes). But there is no opportunity to specify attributes on "application level". Scenario is:

  1. Ignite connections from connection pool are used by different applications.
  2. While processing data application need access to application attributes - an associative array of Strings specified on an application side. Business logic might depend on such attributes - application language, application name for audit, etc ([2], [4]).

It's proposed to provide such opportunity. Then there will be hierarchy of attributes:

  1. Call level - ServiceCallContext
  2. Application level - ApplicationAttributes
  3. Connection level - UserAttributes, SecuritySubject

User defined functions might want access to different level of attributes. For example, SecuritySubject can be used to provide fine-grained access control to cache data. For example, CacheInterceptor saves the subject id it along with data and it can be used for fine-grained access control. Then it's proposed to introduce API that provides access to all this attributes while processing data in hierarchical order.

Requirements:

  1. The attributes ​​are explicitly set by application on Ignite API entry point (Ignite, IgniteClient, JDBC).
  2. The attributes are fixed for every Ignite API call (can't be changed in the middle of the data processing).
  3. The attributes must be accessible in stored functions on all nodes participated in requests and queries:
    1. QuerySqlFunction
    2. CacheInterceptor
    3. Service
    4. ComputeTask, ComputeJob

Attributes API that aren't part of the IEP:

  1. ClientListenerConnectionContext#attributes - it's how client stores UserAttribute in connection context.
  2. ComputeTaskSession#setAttribute - this mechanism is available only within Compute API. It allows attributes to be changed during task lifetime, use-case is different - send sync/async notifications between jobs about events happened during task lifetime.

Similar mechanisms in other DBMSs:

  1. Application, Client contexts mechanisms exist in Oracle [1] and they are widely used [6].
  2. Custom session variables exist in DBMS like SQLServer [8], Snowflake [7], MySQL [9].

Description

Setting application attributes

Ignite 

  1. Users set attributes with Ignite#withApplicationAttributes. It returns Ignite instance that is aware of the attributes.
  2. Application attributes are propagated with all messages sent within operation on remote nodes (similar to GridIoSecurityAwareMessage)


// Example of usage.
try (Ignite ign = Ignition.start(ignCfg)) {
    Map<String, String> appAttrs = F.asMap("SESSION_ID", "1234");

	Ignite app = Ignite.withApplicationAttributes(appAttrs);	

 	...
}

IgniteClient (Java) 

  1. Users set attributes with IgniteClient#withApplicationAttributes.
  2. New feature is needed in the ClientBitmaskFeature protocol.


// Example of usage.
try (IgniteClient cln = Ignition.startClient(clnCfg)) {
    Map<String, String> appAttrs = F.asMap("SESSION_ID", "1234");

	IgniteClient app = cln.withApplicationAttributes(appAttrs);	

 	...
}

JDBC

The standard jdbc protocol describes the methods Connection#setClientInfo, which allow changing the values ​​of client attributes during the life of the connection [3]. Implementation features:

  1. The list of attributes that can be set using #setClientInfo is arbitrary. The documentation recommends strictly limiting the set of attributes, but this is not necessary. For example, Oracle does not have such a limitation [5]. The setClientInfo array is completely translated into the getClientAttributes array.
  2. The parameters set in setClientInfo are passed along with each JdbcRequest (this requires a new feature in JdbcThinFeature).
  3. The client must reset the set values ​​itself.


// JDBC connection to Ignite server.
try (Connection conn = DriverManager.getConnection(URL)) {
    conn.setClientInfo("SESSION_ID", "1234");
 
    ...
}

Accessing attributes

  1. SessionContext is an entrypoint for accessing attributes on all levels and other session-level data (e.g. SecurutySubject).
  2. User can easily create own QuerySqlFunction  to get access to the attributes in SQL queries if needed (see example below).

Ignite provides SessionContextProviderResource to access to SessionContext. Provider instead of direct instance of the context is used for optimization. Injecting instance requires to have new instance of CacheInterceptor or QuerySqlFunction target class. It's not optimal to create new instances for every processing key or row.

Note, it proposes to make possible use non-static QuerySqlFunction to inject the resource.

/** SessionContext interface. It's an entrypoint for all attributes. */
public class SessionContext {
    /** @return Attribute by name. */
    public @Nullable String getAttribute(String attrName);

    /** @return Current SecuritySubject. */
	public @Nullable SecuritySubject getSecuritySubject();
 }
 
/** Example, use it in QuerySqlFunction. */
public static class UserDefinedFunctions {
    /** */
    @SessionContextProviderResource
    public SessionContextProvider sesCtxProv;

     /** @return Session ID set with application attributes. */
    @QuerySqlFunction
    public @Nullable String sessionId() {             
		SessionContext sesCtx = sesCtxProv.getSessionContext();

        return sesCtx == null ? null : sesCtx.getAttribute("SESSION_ID");
    }
}

Risks and Assumptions

  1. No security checks are performed on the application attributes.
  2. Application attributes keys and values are strings, to avoid serialization problems.
  3. User should specify only few application attributes, and they should be small.
  4. UserAttributes currently fill with node attributes (~50 items on node start), and they are not transferred between nodes. This process should be changed.

Discussion Links

// Links to discussions on the devlist, if applicable.

Reference Links

[1] https://docs.oracle.com/en/database/oracle/oracle-database/19/dbseg/using-application-contexts-to-retrieve-user-information.html#GUID-51C9D5FA-6787-4F05-82EF-A5968BEDC5A0

[2] https://stackoverflow.com/questions/71067911/use-oracles-dbms-session-set-context-in-entity-framework-core

[3] https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Connection.html#setClientInfo(java.lang.String,java.lang.String)

[4] https://torofimofu.blogspot.com/2014/05/oracle.html

[5] https://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#BABDAEEC

[6] https://stackoverflow.com/search?tab=newest&q=SYS_CONTEXT

[7] https://docs.snowflake.com/en/sql-reference/session-variables#session-variable-functions

[8] https://learn.microsoft.com/en-us/sql/t-sql/functions/session-context-transact-sql?view=sql-server-ver16

[9] https://dev.mysql.com/doc/refman/8.4/en/user-variables.html

Tickets

// Links or report with relevant JIRA tickets.

  • No labels