You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Veena Mithare (Jira)" <ji...@apache.org> on 2020/06/09 07:09:00 UTC

[jira] [Comment Edited] (IGNITE-12781) Cache_Put event generated from a remote_client user action has subject uuid of Node that executes the request sometimes.

    [ https://issues.apache.org/jira/browse/IGNITE-12781?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17127251#comment-17127251 ] 

Veena Mithare edited comment on IGNITE-12781 at 6/9/20, 7:08 AM:
-----------------------------------------------------------------

Hi Team,

To get the audit information for cache put events generated on dbeaver, I use this approach in the storagespi . Kindly confirm if you see any concerns with this :

 
 # If the cacheevent holds the subject id of the remoteclient, then fetch it using getSpiContext().authenticatedSubject(uuid ) method. ( This in turn will check the AuthenticationContext.context() and match the subjectId in of the event with the one in the AuthenticationContext.context() )
 # If it holds the subjectId of the node instead of the remoteclient( In this case, the subject returned by point 1 will be null ) -
 ## Create a cache( transactionIdToSubjectCache) that holds xid vs security subject information where xid is the id of the transaction started event. The subject Id on this event always holds the remote client id for cache put events generated on dbeaver.
 ## When a cacheput event is sent to the storage spi - match the xid as follows
 ### Get the subject from transactionIdToSubjectCache using the xid.
 ### If the above is null, get the originating xid of the event xid and get the subject using the originating xid.

 

I am able to get the subject using this approach- could you kindly verify if I am missing anything.

Here is a pseudo code :

public class AuditSpi extends IgniteSpiAdapter implements EventStorageSpi {
    private IgniteCache<IgniteUuid, SecuritySubject> transactionIdSubjectMapCache;

 

    @Override
    public void record(Event evt) throws IgniteSpiException {
        assert evt != null;
        ignite = Ignition.ignite(igniteInstanceName);
        transactionIdSubjectMapCache = ignite.cache("transactionIdSubjectMapCache");

      

        if (evt instanceof TransactionStateChangedEvent && (evt.type()
                == EventType.EVT_TX_STARTED
        )) {

            //populate the transactionIdSubjectMapCache for events generated from dbeaver. This always contains the remote_client subject id.
            if (AuthorizationContext.context() != null)
{                 transactionIdSubjectMapCache.put(((TransactionStateChangedEvent) evt).tx().xid(),                                 ((ProjectAuthorizationContext) AuthorizationContext.context()) .subject());             
            } 
            return;

        }

        if (evt instanceof CacheEvent) {

            SecuritySubject subj = getSpiContext().authenticatedSubject(((CacheEvent) evt).subjectId())l;
            IgniteUuid transactionId = null;
            if (subj == null)
           {                              
                   SecuritySubject sub = getSecuritySubjectFromTransactionMap((CacheEvent) evt,  transactionId);                
                  // more logic to store it in the audit cache here.            

           } 
        }

    }

    private SecuritySubject getSecuritySubjectFromTransactionMap(CacheEvent evt,
                                                                                   IgniteUuid transactionId) {
        SecuritySubject subj = transactionIdSubjectMapCache.get(evt.xid());
               

        if (subj == null) {

            IgniteTxManager tm = ((IgniteEx) ignite).context().cache().context().tm();

            for (IgniteInternalTx transaction : tm.activeTransactions()) {

                if (transaction.xid().equals(evt.xid())) {
                    if (transaction.nearXidVersion() != null)
{                         subj = transactionIdSubjectMapCache                                 .get(transaction.nearXidVersion().asGridUuid());                     } 
                }
            }
        }
        return subj;

    }

 

}

 

regards,

Veena.

 


was (Author: veenamithare):
Hi Team,

To get the audit information for cache put events generated on dbeaver, I use this approach in the storagespi . Kindly confirm if you see any concerns with this :

 
 # If the cacheevent holds the subject id of the remoteclient, then fetch it using getSpiContext().authenticatedSubject(uuid ) method. ( This in turn will check the AuthenticationContext.context() and match the subjectId in of the event with the one in the AuthenticationContext.context() )
 # If it holds the subjectId of the node instead of the remoteclient( In this case, the subject returned by point 1 will be null ) -
 ## Create a cache( transactionIdToSubjectCache) that holds xid vs security subject information where xid is the id of the transaction started event. The subject Id on this event always holds the remote client id for cache put events generated on dbeaver.
 ## When a cacheput event is sent to the storage spi - match the xid as follows
 ### Get the subject from transactionIdToSubjectCache using the xid.
 ### If the above is null, get the originating xid of the event xid and get the subject using the originating xid.

 

I am able to get the subject using this approach- could you kindly verify if I am missing anything.

Here is a pseudo code :

public class AuditSpi extends IgniteSpiAdapter implements EventStorageSpi {
    private IgniteCache<IgniteUuid, SecuritySubject> transactionIdSubjectMapCache;

 


    @Override
    public void record(Event evt) throws IgniteSpiException {
        assert evt != null;
        ignite = Ignition.ignite(igniteInstanceName);
        transactionIdSubjectMapCache = ignite.cache("transactionIdSubjectMapCache");

        // Filter out events.


        if (evt instanceof TransactionStateChangedEvent && (evt.type()
                == EventType.EVT_TX_STARTED
        )) {

            if (AuthorizationContext.context() != null) {

                transactionIdSubjectMapCache
                        .put(((TransactionStateChangedEvent) evt).tx().xid(),
                                ((ProphetAuthorizationContext) AuthorizationContext.context())
                                        .subject());
            }
            return;

        }

        if (evt instanceof CacheEvent) {


            SecuritySubject subj = ((CacheEvent) evt).subjectId() != null
                    ? getSpiContext().authenticatedSubject(((CacheEvent) evt).subjectId())
                    : null;
            IgniteUuid transactionId = null;
            if (subj == null) {

                //Send the transactionId field. This will be populated in the method below.
                Pair<SecuritySubject, IgniteUuid> returnPair
                        = getSecuritySubjectFromTransactionMap((CacheEvent) evt,
                        transactionId);
                // more logic to store it in the audit cache here.
            }
        }

    }

    private Pair<SecuritySubject, IgniteUuid> getSecuritySubjectFromTransactionMap(CacheEvent evt,
                                                                                   IgniteUuid transactionId) {
        SecuritySubject subj = transactionIdSubjectMapCache.get(evt.xid());
        if (subj != null) {
            transactionId = evt.xid();

        }

        if (subj == null) {

            IgniteTxManager tm = ((IgniteEx) ignite).context().cache().context().tm();

            for (IgniteInternalTx transaction : tm.activeTransactions()) {

                if (transaction.xid().equals(evt.xid())) {
                    if (transaction.nearXidVersion() != null) {
                        subj = transactionIdSubjectMapCache
                                .get(transaction.nearXidVersion().asGridUuid());
                    }
                }
            }
        }
        return Pair.of(subj, transactionId);

    }

 


}

 

regards,

Veena.

 

> Cache_Put event generated from a remote_client user action has subject uuid of Node that executes the request sometimes.
> ------------------------------------------------------------------------------------------------------------------------
>
>                 Key: IGNITE-12781
>                 URL: https://issues.apache.org/jira/browse/IGNITE-12781
>             Project: Ignite
>          Issue Type: Bug
>          Components: security
>    Affects Versions: 2.8
>            Reporter: Veena Mithare
>            Priority: Major
>              Labels: iep-41
>
> Unable to get the right audit information i.e. we are unable 
> to get the right subject for users logged in through dbeaver ( jdbc thin 
> client. ).
>  
> This is because the subjectid associated with the "CACHE_PUT" 
> event when an update is triggered by the jdbc thin client, contains the uuid 
> of the node that executed the update rather than the logged in jdbc thin 
> client user. 
> This was discussed in the 'Ignite users' group 
> [http://apache-ignite-users.70518.x6.nabble.com/JDBC-thin-client-incorrect-security-context-td31354.html]
> During the  update through jdbc client, there 
> could be 2 kinds of threads acting on it. The 'client-connector' thread and 
> the 'sys-stripe'. If the client-connector thread completes the transaction 
> and calls the record, it is able to send a 'cache_put' event with the uuid 
> of the person logged in to through the jdbc thin client . Whereas if the 
> 'sys-stripe' thread completes the transaction, it sends the 'cache_put' 
> event with the node uuid. 
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)