Project

General

Profile

Actions

Task #452

closed

Groovy sandbox - bloating of authorities

Added by Filip Měšťánek almost 7 years ago. Updated almost 7 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Ondřej Kopr
Category:
Scripts
Target version:
Start date:
05/30/2017
Due date:
% Done:

100%

Estimated time:
Owner:

Description

I have a simple script which find the main contract of a user. But the script requires tons of authorities (see the image), which I don't even explicitly use. Some of them are some internal classes (possibly used by Spring?) like proxies.

import eu.bcvsolutions.idm.core.api.dto.IdmIdentityContractDto;

List<IdmIdentityContractDto> contracts = identityContractService.findAllByIdentity(identityId);

for (IdmIdentityContractDto contract : contracts) {
    if (contract.isMain()) {
        return contract;
    }
}
return null;

The other issue is, that it looks like the scripts are influencing other scripts. Because sometimes I am require to add an authority, which isn't clearly used in the script. My theory is, that if script A uses class B and calls script C, the script C needs to also include the class B in the authority (or possibly the other way). Try it with using System.out.println in the script A.\

And a small side note, the class/service labels aren't translated.


Files

skript1.png (72.4 KB) skript1.png Jan Helbich, 06/09/2017 08:03 AM
skript2.png (282 KB) skript2.png Jan Helbich, 06/09/2017 08:03 AM

Related issues

Related to IdStory Identity Manager - Task #461: Script exceptions - show script codeClosedOndřej Kopr05/30/2017

Actions
Actions #1

Updated by Filip Měšťánek almost 7 years ago

It would be also nice to add the org.codehaus.groovy.runtime.GStringImpl to the default allowed classes.

Actions #2

Updated by Filip Měšťánek almost 7 years ago

  • Priority changed from High to Urgent

I wrote a script, which was tested and working without problems many days. Suddenly, after deploying a new version, this exception is raised:

Caused by: java.lang.SecurityException: Script wants to use unauthorized class: [com.sun.proxy.$Proxy276]

The proxies are dynamic classes, which are managed by spring and its out of our hands how the spring uses them. If he decides to return a proxy instead an entity, he does it. This is not 100% tested, but it looks like he may use different kind of proxies, as sometimes it requires this 276, sometimes 236, etc...

This points to a critical flaw of the script authorization design which needs to be addressed. Therefore I am rising priority of this issue as we need to find some working solution (for example as suggested before, allow interfaces instead of concrete implementations). Please consult it with lead architect and if there is some question, write/call me.

Actions #3

Updated by Vít Švanda almost 7 years ago

  • Status changed from New to In Progress
  • Assignee changed from Vít Švanda to Filip Měšťánek
  • Target version set to Citrine (7.3.0)
Solution can be easy. We only need get "original" type of Class from proxy object. For example via Advised object.
But I cannot simulate this problem:
  • I tried example from task description.
  • I used some service (as Spring object).
  • I load IdmRole entity (as Hibernate object).
    In all these cases I didn't see any error message with "Proxy" object.

Do you have some works exmaple with Proxy problem?

Actions #4

Updated by Filip Měšťánek almost 7 years ago

  • Assignee changed from Filip Měšťánek to Vít Švanda

Here is a working example. The first script only returns contract of the user.

import eu.bcvsolutions.idm.core.api.dto.IdmIdentityContractDto;

IdmIdentityContractDto contract = scriptEvaluator.evaluate(scriptEvaluator.newBuilder()
        .setScriptCode('ldapContract')
        .addParameter('scriptEvaluator', scriptEvaluator)
        .addParameter('identityId', entity.getId())
    .build());

def workPos = contract.getWorkPosition();
def org = treeNodeService.get(workPos); // Here it returns proxy

return "CN=Tester,O=AOPK,C=CZ";

Actions #5

Updated by Filip Měšťánek almost 7 years ago

But I am still with my opinion, that methods can return any implementations or subclasses. We shouldn't be forced to know the specific implementation.

Actions #6

Updated by Vít Švanda almost 7 years ago

  • Assignee changed from Vít Švanda to Ondřej Kopr
Actions #7

Updated by Ondřej Kopr almost 7 years ago

  • Status changed from In Progress to Needs feedback
  • Assignee changed from Ondřej Kopr to Vít Švanda
  • Priority changed from Urgent to Normal
  • % Done changed from 0 to 90

Add new exception catch with script code,
add tests for script evaluate with three script with different authorities
add code for script table and filter

to documentation was added issue with return statement

update documentation: https://proj.bcvsolutions.eu/ngidm/doku.php?id=navrh:scripts#skripty

Actions #8

Updated by Ondřej Kopr almost 7 years ago

  • Related to Task #461: Script exceptions - show script code added
Actions #9

Updated by Vít Švanda almost 7 years ago

  • Status changed from Needs feedback to Resolved
  • Assignee changed from Vít Švanda to Ondřej Kopr
  • % Done changed from 90 to 100

Proxy problem solved. Name of script is in log as Ondra wrote.

Actions #10

Updated by Vít Švanda almost 7 years ago

  • Status changed from Resolved to Closed
Actions #11

Updated by Jan Helbich almost 7 years ago

I've pulled and deployed current version from Nexus.
Suddenly I can't get the script to work properly. Images of setup and stacktrace included.

Situation:
I have a transformation TO system mapping, which calls "IsAccountInProtection" skript (code below). This script calls "GetIdentityAccAccount", which returns AccAccountDto. Suddenly the security check fails on missing eu.bcvsolutions.idm.acc.dto.AccIdentityAccountDto class. However the class is present, as "skript1.png" shows.

Did I make a mistake somewhere? I can't get this working :(

Furthermore the stacktrace now calls Object.toString() when showing info about the object that did not pass the security inspection - I personally think this is not right, because #toString is easily overridable (and should be overrided) and then no info about missing class is provided. For example missing org.springframework.data.domain.PageImpl prints: "Script wants to use unauthorized class: [Page 1 of 1 containing eu.bcvsolutions.idm.acc.dto.AccIdentityAccountDto instances]" which is fairly useless.

IsAccountInProtectionCode:

package eu.bcvsolutions.idm.scripts.rules

import eu.bcvsolutions.idm.acc.entity.AccAccount

/**
 * code: IsAccountInProtection
 * name: IsAccountInProtection
 * desc:
 * Returns if identity's account is in protection.
 * Input:
 *   entity - IdmIdentity
 *   system - SysSystem
 * Output:
 *   boolean inProtection - account is in protection
 *
 * authorities:
 * - eu.bcvsolutions.idm.acc.entity.AccAccount
 *
 * @author Jan Helbich
 */
// IdmIdentity entity
// SysSystem system
//
AccAccount account = scriptEvaluator.evaluate(scriptEvaluator.newBuilder()
        .setScriptCode('GetIdentityAccAccount')
        .addParameter('scriptEvaluator', scriptEvaluator)
        .addParameter('entity', entity)
        .addParameter('system', system)
        .build())
//
return account == null ? false : account.inProtection

GetIdenittyAccAccount:

package eu.bcvsolutions.idm.scripts.rules

import eu.bcvsolutions.idm.acc.dto.filter.EntityAccountFilter
import eu.bcvsolutions.idm.acc.dto.filter.IdentityAccountFilter

/**
 * code: GetIdentityAccAccount
 * name: GetIdentityAccAccount
 * desc:
 * Returns AccAccount for provided identity and system.
 * Input:
 *   entity - IdmIdentity
 *   system - SysSystem
 * Output:
 *   AccAccount account - entity's account
 *
 * authorities:
 * - org.springframework.data.domain.PageImpl
 * - eu.bcvsolutions.idm.acc.domain.AccountType
 * - eu.bcvsolutions.idm.acc.dto.AccIdentityAccountDto
 * - eu.bcvsolutions.idm.acc.dto.EntityAccountDto
 * - eu.bcvsolutions.idm.acc.dto.filter.EntityAccountFilter
 * - eu.bcvsolutions.idm.acc.dto.filter.IdentityAccountFilter
 * - eu.bcvsolutions.idm.acc.entity.AccAccount
 * - eu.bcvsolutions.idm.acc.entity.SysSystem
 * - eu.bcvsolutions.idm.core.model.entity.IdmIdentity
 * - SERVICE accIdentityAccountService
 * - SERVICE accAccountService
 *
 * @author Jan Helbich
 */
//
//
//IdmIdentity entity
//SysSystem system
//AccIdentityAccountService accIdentityAccountService
//AccAccountService accAccountService
//
EntityAccountFilter entityAccountFilter = new IdentityAccountFilter()
entityAccountFilter.setEntityId(entity.id)
entityAccountFilter.setSystemId(system.id)
entityAccountFilter.setOwnership(Boolean.TRUE)
def entityAccounts = accIdentityAccountService.find(entityAccountFilter, null).getContent()
if (entityAccounts.isEmpty()) {
    return null
} else {
    // We assume that all entity accounts
    // (mark as ownership) have same account!
    def entityAccountDto = accIdentityAccountService.get(entityAccounts.get(0).account)
    if (entityAccountDto == null || entityAccountDto.account == null) {
        return null
    }
    return accAccountService.get(entityAccountDto.account)
}

Actions #12

Updated by Jan Helbich almost 7 years ago

  • % Done changed from 100 to 90

I've debugged the script call. The result is that the error is not on missing eu.bcvsolutions.idm.acc.dto.AccIdentityAccountDto, but unconfigured Collections$UnmodifiableRandomAccessList (or smth like that), which is returned by Page.getContent()...

Can you pretty please make the error message print the class which is missing again?
diff:

--- a/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/domain/GroovySandboxFilter.java
+++ b/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/domain/GroovySandboxFilter.java
@@ -96,7 +96,7 @@ public class GroovySandboxFilter extends GroovyValueFilter {
                if (o instanceof Script || o instanceof Closure) {
                        return o; // access to properties of compiled groovy script
                }
-               throw new SecurityException(MessageFormat.format("Script wants to use unauthorized class: [{0}] ", o));
+               throw new SecurityException(MessageFormat.format("Script wants to use unauthorized class: [{0}] ", o.getClass()));
        }

 }

Actions #13

Updated by Jan Helbich almost 7 years ago

  • % Done changed from 90 to 100

Thanks for the fix, Ondra, its OK now :)

Actions

Also available in: Atom PDF