5 Replies Latest reply: Nov 4, 2011 7:20 AM by 758447 RSS

    Best way to restrict data (per consumer-based) in a generic data service

    758447
      Hi again!

      In our project, we have a big database and our data services expose data from them. So far, so good.

      However, because of the company's security business process, any consumer needs to approve all the fields they want to use before consuming the data services and also the scope of the query, and not all consumers have the same permissions.

      For example, suppose we have a big table called EMPLOYEES with the following fields (please note that in this fake"table" I am not considering joins and FK's, for the sake of simplicity):

      h3. EMPLOYEES (XML schema element employee)
      ID (not mapped in XML schema)
      NAME (element name)
      LOGIN (element login)
      SUBSIDIARY (element subsidiary)
      DEPARTMENT (element department)
      JOB (element job)
      SALARY (element salary)
      ADDRESS (element address)
      SOCIAL_SECURITY_NUMBER (element socialSecNumber)

      Suppose we have a generic public operation called getEmployeeByLogin($login as xs:string), published in the corporative oracle service bus, that retrieve an employee. Any and every consumer must have their own bus login/password and, based in it, we configure ODSI which elements each consumer will get in the response. So:

      . . . . Consumer1: restricted to see only elements name, login, department, subsidiary
      . . . . Consumer2: restricted to see only elements name, login, department, job, subsidiary

      And so on. Again, so far, so good.

      Our problem: some consumers are allowed to see elements from a specific subsidiary and/or department. Example:

      . . . . Consumer3: restricted to see only elements name, login, department, job, salary ONLY FROM subsidiary "ABC" and department "dept 2"
      . . . . Consumer4: restricted to see only elements name, login, department, job ONLY FROM subsidiaries "ABC", "DEF", "GHI"
      . . . . Consumer5: restricted to see only elements name, login, department, job, salary ONLY FROM subsidiary "MNO", departments "dept 11", "dept 12"

      What would be the best way to attend to these restrictions while using the most generic and reusable solution?

      One answer would be create an operation for each consumer, but I don't want to use this approach unless I have no other alternative.

      I was thinking in creating an abstract level of operations to apply business rules, but I do not know if this is possible or if it is the best solution, because this is kind of hardcoding the solution. Example of this solution:

      . . . . Generic public operation: getEmployeeByLogin($login as xs:string)
      . . . . Specific public operation: getEmployeeByLogin_Consumer3($login as xs:string)
      . . . . Specific public operation: getEmployeeByLogin_Consumer4($login as xs:string)
      . . . . Specific public operation: getEmployeeByLogin_Consumer5($login as xs:string)

      . . . . All public operations above would call the generic private operation: getEmployeeByLogin($login as xs:string, $restrictions as xs:string?):
      . . . . getEmployeeByLogin would call this private operation, passing $restrictions as null.
      . . . . getEmployeeByLogin_Consumer3 would call this private operation, passing $restrictions to read only data from subsidiary "ABC" and department "dept 2".
      . . . . getEmployeeByLogin_Consumer4 would call this private operation, passing $restrictions to read only data from subsidiaries "ABC", "DEF", "GHI".
      . . . . getEmployeeByLogin_Consumer5 would call this private operation, passing $restrictions to read only data from subsidiary "MNO", departments "dept 11", "dept 12"

      What do you think about this scenario? Any idea will be highly appreciated!

      Thank you very much!
        • 1. Re: Best way to restrict data (per consumer-based) in a generic data service
          mikereiche
          You don't need to create consumer-specific functions. Simply secure the desired data elements in the physical data service.

          "To secure Oracle Data Service Integrator artifacts you can create runtime security policies. Oracle Data Service Integrator artifacts or resources include dataspaces, services, operations, library procedures, and data elements."

          Your requirement is to secure data elements. An element can be a simple element, such as CREDIT_CARD_NUMBER, or a complex element, such as CUSTOMER_ADDRESS.

          First you need your data services (the elements to be secured must be "optional" (i.e. minOccurs="0"), so the resulting xml still passes validation if they are redacted).
          Then you need users (weblogic users).
          Then you need to create runtime security policies.
          Then enable security on your dataspace, and there you go.


          Here's the ODSI security documentation :

          http://download.oracle.com/docs/cd/E13162_01/odsi/docs10gr3/admin/security.html

          Start at the top, when you get to figure 5-5, you should have data element security working.
          • 2. Re: Best way to restrict data (per consumer-based) in a generic data service
            758447
            Thanks, I will study it!
            Have a nice weekend!
            • 3. Re: Best way to restrict data (per consumer-based) in a generic data service
              758447
              Hi again.

              I am having some difficult trying to build my own XQuery Functions for Security.

              Hitherto, I learnt how to grant permission based in username. Now, I need to implement conditions, like "if username = 'abc', do not show results from department XPTO" and so on, but I am getting erros when I try to reference my xml schema inside the XQuery Functions for Security.

              Could you please tell me where can I get the source project used in the documentation example? I think I can try to find my way if I can study the entire source project. Page 7 of the link you sent me:

              -----
              import schema namespace t1 = 'ld:DataServices/CUSTOMER_ORDER' at 'ld:DataServices/Schema/CUSTOMER_ORDER.xsd';
              declare namespace f1 = "ld:CUSTOMER_ORDER";

              declare function f1:secureOrders($order as element(f1:CUSTOMER_ORDER)) as xs:boolean {
                   if (fn-bea:is-access-allowed("CUSTOMER_ORDER/LimitAccess", "ld:CUSTOMER_ORDER.ds")) then
                        fn:true()
                   else if ($order/TotalOrderAmount lt (fn-bea:get-property("total_order_amount", "1000000") cast as xs:decimal)) then
                        fn:true()
                   else
                        fn:false()
              };
              -----

              Thank you again!
              • 4. Re: Best way to restrict data (per consumer-based) in a generic data service
                mikereiche
                There is a sample retail application that comes with the product. When you install ODSI, check "Samples" in the installer (or samples or whatever it's called). It has a CUSTOMER_ORDER data service.

                After installing, start workshop, then File -> New -> Examples -> Oracle Data Service Integrator Samples - Retail DataSpace Sample

                If that's not what you're looking for, you'll have to be more precise than "the source project used in the documentation example"
                • 5. Re: Best way to restrict data (per consumer-based) in a generic data service
                  758447
                  Exactly what I wanted, the complete source code of the example.
                  Thank you!