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

Compare with Current View Page History

« Previous Version 23 Next »

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

ACTIVE


Motivation

Currently user have some opportunities to set custom attributes on client side:

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

It has limitations: 

  1. ServiceCallContext helps solve similar problems, but has several limitations - available only by calls via the IgniteService API and cannot be used for primitive cache operations.
  2. UserAttributes - allows to set user attributes, but the attribute values ​​are fixed for the entire lifetime of the connection.


While processing data users want to have access to application specific non-tabular (not stored in cache structures) data: 

  1. 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]).
  2. 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.
  3. UserAttributes - an associative array of Strings specified during client connection. 

The requirements:

  1. The data ​​are explicitly set by user on application side.
  2. The data are fixed for every Ignite API call (can't be changed in the middle of the data processing).
  3. The data might be changed during the life of the connection (a connection from a connection pool can be sequentially used by different applications).
  4. The data must be accessible in stored functions on all nodes participated in requests and queries:
    1. QuerySqlFunction
    2. CacheInterceptor
    3. Service
    4. ComputeTask, ComputeJob

Ignite does not have a such API:

  1. ServiceCallContext helps solve similar problems, but has several limitations - available only by calls via the IgniteService API and cannot be used for primitive cache operations.
  2. UserAttributes - allows to set user attributes, but the attribute values ​​are fixed for the entire lifetime of the connection.
  3. ClientListenerConnectionContext - it's available only on single node which directly accepts a client connection.
  4. ComputeTaskSession - 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.

Attributes hierarchy:

There should be API to provide access for all these lleel

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].

Naming:

It's 

Description

Accessing application attributes

  1. ApplicationContext is an entrypoint for accessing all non-tabular data.
  2. The access requires static methods, because objects injection isn't possible for user functions (QuerySqlFunction are static, CacheInterceptor is a cache singleton).
  3. User can easily create own QuerySqlFunction  to get access to the attributes in SQL queries if needed (see example below).


/** ApplicationContext interface. It's an entrypoint for all non-tabular data. */
public class ApplicationContext {
    /** @return Application attributes set for current thread. */
    public static @Nullable Map<String, String> getAttributes();

    /** @return Current SecuritySubject. */
	public static @Nullable SecuritySubject getSecuritySubject();
 }
 
/** Example, use it in QuerySqlFunction. */
public static class UserDefinedFunctions {
    /** @return Session ID set with application attributes. */
    @QuerySqlFunction
    public static @Nullable String sessionId() {
        Map<String, String> appAttrs = ApplicationContext.getAttributes();
 
        return appAttrs == null ? null : appAttr.get("SESSION_ID");
    }
}

Setting application attributes

Ignite 

  1. Users set attributes with IgniteCache#withApplicationAttributes.
  2. Application attributes are propagated with all messages sent within operation on remote nodes (similar to GridIoSecurityAwareMessage)
  3. Application attributes set to ThreadLocal<Map<String, String>>  in each thread that process operation (similar to SecurityContext#withSecurityContext() ).


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

	IgniteCache<?, ?> cache = ign.cache("CACHE").withApplicationAttributes(appAttrs);	

 	...
}

IgniteClient (Java) 

  1. Users set attributes with ClientCache#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");

	ClientCache<?, ?> cache = cln.cache("CACHE").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");
 
    ...
}

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. Application attributes should be small. 

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