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

Compare with Current View Page History

« Previous Version 8 Next »

IDIEP-38
Author
Sponsor
Created 16.10.2019
Status
DRAFT


Motivation

For now, a user-defined code that executes on a remote node can utilize all feature Java to get access to host resources.

For example, it can create/update/delete files; create sockets; read/update/delete system properties; use reflection API and so on.

That behavior leads to security lack.

To protect resources on a remote node, we should restrict the opportunities of user-defined code.

Description

To protect crucial system resources, we should use the Java Sandbox.

The Sandbox is composed of the next elements:

  • Permissions. A permission is a specific action that code is allowed to perform.
  • Code sources. Code sources are the location from which a class has been loaded along with information about who signed the class, if applicable.
  • Protection domains. A protection domain is an association of permissions with a particular code source. Every class definition can refer to only one ProtectionDomain.
  • AccessController. The AccessController class is used for access control operations and decisions.
  • AccessControlContext. An AccessControlContext is used to make system resource access decisions based on the context it encapsulates.

Java uses a stack-based access control mechanism.
The standard security check ensures that each frame (Protection Domain) in the call stack has the required permission.
That is, the current permissions in force are the intersection of the permissions of each frame in the current access control context.
If any frame does not have permission, no matter where it lies in the stack, then the current context does not have that permission.

We have the opportunity to dynamically update the Protection Domains associated with the current AccessControlContext using the DomainCombiner interface.
A DomainCombiner is passed as a parameter to the appropriate constructor for AccessControlContext.
The newly constructed context is then passed to the AccessController.doPrivileged(..., context) method to bind the provided context (and associated DomainCombiner) with the current execution Thread.
Subsequent calls to AccessController.getContext or AccessController.checkPermission cause the DomainCombiner.combine to get invoked.

That is the basis to implement the integration of the Java Sandbox with AI.

The main unit of the Ignite Sandbox is the IgniteSandbox interface, accessed through IgniteSecurity.
Users for this interface are components that can run a user-defined code. To run a user-defined code with restrictions,
they have to pass it to one of the IgniteSandbox.execute methods.

There are two conditions to run user-defined code with restrictions:

  • installed GridSecurityProcessor;
  • installed SecurityManager.

If these conditions in the place, an instance of the AccessControllerSandbox class that is the implementation of IgniteSandbox runs a user-defined code with restrictions as follow:

  1. Get sandbox permissions from a SecuritySubject of the current SecurityContext.
  2. Create AccessControlContext with IgniteDomainCombiner that constructed using permissions from step 1.
  3. Call AccessController.doPrivileged with passed a user-defined code and AccessControlContext from step 2.

IgniteDomainCombiner is responsible for updating the Protection Domains with permissions of the current SecuritySubject.


A user-defined code should have the opportunity of using the public API of Ignite on a remote node.
But he may don't have some permissions to execute this operation successfully. For example, to put a value into a cache,
it requires permissions for accessing to reflection API and reading system property IGNITE_ALLOW_ATOMIC_OPS_IN_TX.
In that case, we have to use AccessController.doPrirvelged without AccessControlContext call to exclude a user-defined code from checking of permissions.

Utils SecurityUtils.doPriveleged method does calling AccessController.doPrirvelged a more convenient way.

Phase 1.

  1. Create implementations of the IgniteSandbox interface.
  2. Extend interface IgniteSecurity to use IgniteSandbox.
  3. Extend interface SecuritySubject to get sandbox permissions.
    The default implementation of this method should return ALL_PERMISSIONS, which means - no restrictions.
    That is essential for backward compatibility with existing implementations of GridSecurityProcessor.
  4. Execution a user-defined code in the Ignite Sandbox for the following components:
    a. ComputeJob;
    b. EntryProcessor;
    c. IgniteBiPredicate;
    d. IgniteClosure;
    e. StreamReceiver.


Phase 1 covers using the Sandbox for features:

  • cache: EntryProcessor, ScanQuery, load cache;
  • compute: execute, broadcast, call, run, apply, executorService;
  • DataStreamer.

Phase 2.

  1. Restrict access a user-defined code to internal API of Ignite:
    a. Restrict internal package access;
    b. Encapsulation of IgniteKernal.
  2. Execution a user-defined code in the Ignite Sandbox for the following features:
    a. Continuous Queries;
    b. IgniteMassaging;
    c. ServiceGrid.

Risks and Assumptions

// 

Discussion Links

http://apache-ignite-developers.2346864.n4.nabble.com/Review-needed-for-IGNITE-11410-Sandbox-for-user-defined-code-td43955.html

Reference Links

https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc1.html#a18313

https://docs.oracle.com/javase/8/docs/api/java/security/AccessController.html

https://docs.oracle.com/javase/7/docs/api/java/security/AccessControlContext.html

https://docs.oracle.com/javase/7/docs/api/java/security/DomainCombiner.html

https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc6.html#a19349

Tickets

key summary type created updated due assignee reporter priority status resolution

JQL and issue key arguments for this macro require at least one Jira application link to be configured







  • No labels