Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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

  1. Application acquires Ignite connections connect 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 sideApplication need specify ApplicationAttributes. Business logic might depend on such attributes - application language, application name for audit, etc ([2], [4]).
  3. Another application re-uses this connect with own attributes values.

It's proposed to provide such the opportunity to set attributes for application. 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 The 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 the attributes must be provided for functions that are pre-created on Ignite cluster and aren't deployed by specific application. Examples:

  • CacheInterceptor saves the SecuritySubject along with data and it can be used for fine-grained access control in QuerySqlFunction.
  • Service extracts attribute from ServiceCallContext and, if absent, get default one from ApplicationAttributes.

It. Then it's proposed to introduce SessionContext API that is available from the functions and provides access to all this the attributes while processing data in hierarchical order (call, application, connection).

Requirements:

  1. The attributes ​​are explicitly set by application on only once for 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)available on all participating nodes of the application requests and queries.
  3. The attributes must be accessible in stored functions on all nodes participated in requests and queriespre-defined functions:
    1. QuerySqlFunction
    2. CacheInterceptor
    3. Service
    4. ComputeTask, ComputeJob

Ignite does not have a such API:

Attributes API that aren't part of the IEP:

  1. ClientListenerConnectionContext#attributes - it's actually how client stores UserAttribute in connection context.
  2. ComputeTaskSession#setAttribute 
  3. 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.
  4. UserAttributes - allows to set user attributes, but the attribute values ​​are fixed for the entire lifetime of the connection.
  5. ClientListenerConnectionContext - it's available only on single node which directly accepts a client connection.
  6. 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.

...

  1. Users set attributes with IgniteCache#withApplicationAttributes 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)Application attributes set to ThreadLocal<Map<String, String>>  in each thread that process operation (similar to SecurityContext#withSecurityContext() ).


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

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

 	...
}

...

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

...

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

	ClientCache<?, ?> cacheIgniteClient app = cln.cache("CACHE").withApplicationAttributes(appAttrs);	

 	...
}

...

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

...

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

Accessing

...

attributes

...

SessionContext is an entrypoint for accessing attributes on all levels and other session-level data (e.g. SecurutySubject). Ignite provides SessionContextProviderResource to access to SessionContext.

  1. Injecting the ProviderResource doesn't require new instance of CacheInterceptor or QuerySqlFunction target class for every call (every row or key).
  2. Provider implementation is responsible for extracting SessionContext from Ignite thread.
  3. Note, it proposes to make possible use non-static QuerySqlFunction to inject the resource
  4. all non-tabular data.
  5. The access requires static methods, because objects injection isn't possible for user functions (QuerySqlFunction are static, CacheInterceptor is a cache singleton).
  6. User can easily create own QuerySqlFunction  to get access to the attributes in SQL queries if needed (see example below).

Code Block
languagejava
/** ApplicationContextSessionContext interface. It's an entrypoint for all non-tabular dataattributes. */
public class ApplicationContextSessionContext {
    /** @return ApplicationAttribute attributes set for current threadby name. */
    public static @Nullable Map<String, String> getAttributes(String getAttribute(String attrName);

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

    /** @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 
		return sesCtxProv.getSessionContext().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. Application attributes 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

https:// Links to discussions on the devlist, if applicable.lists.apache.org/thread/c5j5yykr6tfrnp9zprhg9j69w63r11zx

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

...

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

Tickets

Jira
serverASF JIRA
columnIdsissuekey,summary,issuetype,assignee,reporter,priority,status,resolution
columnskey,summary,type,assignee,reporter,priority,status,resolution
maximumIssues20
jqlQuerylabels = IEP-129
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
// Links or report with relevant JIRA tickets.