Event Listener and variables passed to operation event

Hello, is it possible to access variable map, that was used as argument when executing complete task or correlate message from within an event listener? E.g. from DelegateTask object instance.

Hi @tomorrow,

If you need to access a local variable outside of the execution it was used in, you can use output variable mapping (see here https://docs.camunda.org/manual/7.10/user-guide/process-engine/variables/#input-output-variable-mapping).

Event listeners have access to the execution they are attached to, so they can access the local variables directly through the execution object. It is also possible to correlate messages through Execution/Task Listeners and Delegates. You can see one example here Use a connector in a Listener.

Best,
Nikola

Hi, I want to access specificaly the variablemap the was used when taskService.complete(ā€¦) method was called, so I could validate, if the caller did not try to pass me some variable, that I was not expecting, and that he did not violate the contract for the complete/correlate operation. If someone knew the internal implementation, he could theoreticaly do harm by storing some additional specific process variable, that I use for some logic inside the process.

Hi @tomorrow,

Sorry for the long delay. If you are using Process Variables to store this data, then it can be accessed through the execution object in an End Event Execution/Task Listener.

Cheers,
Nikola

Hi, thanks, maybe I am missing something, but arenā€™t the variables passed to complete operation always store as process variables? My main concern is, when the complete is called via rest. Is there any possibility to tell the process engine globaly, in which scope the variables passed as parameteres should be stored?

As far as your proposal is concerned, I know I can load the process variables though the execution object, but there I would get all process variables, not only the ones passed to complete operation.

Letā€™s take following scenario.

Before user task A, there is process variable clientId with value ā€˜1ā€™. Then the task is created. The user calls complete operation via REST. He should send some variable, letā€™s say completeData with some aggreed contract. E.g. following value would be ok.

{
  "clientId" : "1",
  "description" : "this client awesome"
}

In the the contract for this variable, there would be, that the clientId value inside the completeData value must be equal to the clientId stored as process variable. I would check this inside the listener and if not, throw an exception. If the user would just complete completeData variable, everyting would work fine.

Now letā€™s say, that on the other side, there is some some attacker, and he somehow knows, that I am doing check of his completeData variable against the clientId process variables. So how sends mi following map of variables

completeData: {
  "clientId" : "2",
  "description" : "Hah, I've got you."
}
clientId: 2

As all the variables passed to complete operation are stored as process variables, the clientId variable would be ovewritten by the attacker and at the time of the check for equality, the check would pass, however the attacker would succeed in compromising my process.

This is why I want to access exactly the variables passed to the complete operation to be able to check, if some potential attacker is not trying to break the contract for that specific user task.

If it would be possible to explicitly tell the process engine to store all the variables, either for complete or correlate method as local variables, and the caller would not be able to change it, it would be enough, as we take all the process variables as secret of the process, so noone can read or write them via the rest API, because weā€™re not exposing those endpoints. However I am not aware of such possibility.

Even if the previous was possible, to check the variables passed to the operation would still be better from various reasons for us.

Another possible sollution would be to override the task service inside the process engine and spring boot environment, however I have not been studying feasibility of this one yet

Hi @tomorrow,

Sorry for the delayed response,. I finally understood your problem.

As I understand now, your problem is with how to scope process variables in order for their values to be safe from changing by a user.

You can do this by using a subprocess (either an Embedded Subprocess or a Call Activity). This will provide you with a different scope for the user task variables, since they will be in the subprocess. At the beginning of the subprocess, you can map the original value of a variable to a different name (ex. ā€œoriginalClientIdā€), and at the end (or after the user task) inside the subprocess, you can validate the original against the new process variable value.

I hope this helps.

Best,
Nikola

Hi, thanks for the reply, however I am afraid that although your solution would work, it would virtually mean that we would need to place every user task in separate embedded subprocess, which would be somewhat cumbersome.

I was originally thinking, that I could use history for the check, however then I realized that it would not work, because the history is not yet written in the database at the time, when I need to do check and it is not possible to flush the camunda transaction in the middle. Also, the assumption that I can pair all the passed variables to the complete operation was probably faulty, because now I think I would be able to select only all the variables that has change.

Another solution could be using AOP, which would trigger some code. It could be done but every aspect slows the application, so weā€™re trying to have as few aspects as possible. So thatā€™s our last option.

Another solution I am thinking of is creating some sort of proxy task service, which would reject the complete/correlationMessage operation based on similar implementation as the aspect would be. This task service would then be either injected to the process engine(I am not sure it would work, I would have to POC it), or we would do our own rest implementation too, because weā€™re considering creating one even without this problem and this would be one more argument to do it.

Also, we could create some MR propose new feature, where there would be implemented ā€œlistenerā€ design pattern in directly inside the process engine api, or maybe even better inside the commands. However this could take a while, because it would definitely need deep analysis and support from your side for the MR to be accepted and I am not sure how much manpower could my company devote to this issue. Do you think something like this could be put on the camunda roadmap even?

Now you probably understand why I am asking if there is some solution out of the box, but it seems there isnā€™t. Could you please validate my ideas, if they are feasible? By any chance, donā€™t you have some similar idea yourself, that would require less work or would be cleaner as far as application design is concerned?

1 Like