3 Replies Latest reply on Sep 4, 2010 4:43 PM by njrich28

    Difficulty granting permission on component

    daxxy

      I am trying to conditionally render a link




      <a4j:commandLink id="acl1" rendered="#{s:hasPermission('device_delete', 'access')}">
          <h:graphicImage value="/img/icons/delete.png"/>
      </a4j:commandLink>




      Here is my rule:



      rule "device_delete"
          no-loop
      when
          perm: PermissionCheck(target == "device_delete", action == "access", granted == false)
          Principal(
              name matches ".*?OTSO IAC DNE OND ADVANCED"
          )
          principle: Principal()
      then
          System.out.println("Granted device delete permission to " + principle.getName());
          perm.grant();
      end



      I expect to tsee this in the logfile




      10:19:13,738 INFO  [STDOUT] Granted device delete permission to 865980




      Instead I see a Granted device delete logging message for every AD group I belong to.




      10:19:13,740 INFO  [STDOUT] Granted device delete permission to #OTSO IAC DNE NMB NMST NCC
      10:19:13,740 INFO  [STDOUT] Granted device delete permission to #DCS OTSO DNE CISCO CONFIGS
      10:19:13,740 INFO  [STDOUT] Granted device delete permission to #OND Change Request
      10:19:13,741 INFO  [STDOUT] Granted device delete permission to OTSO.DITM.DARINVENTORY
      10:19:13,741 INFO  [STDOUT] Granted device delete permission to #OTSO CMDB




      etc etc


      Any idea why?


      Please let me know if I should include more information. I wasn't really sure how to describe this problem.


      Tanya

        • 1. Re: Difficulty granting permission on component
          njrich28

          Have you tried:



          rule "device_delete"
              no-loop
          when
              perm: PermissionCheck(target == "device_delete", action == "access", granted == false)
              principle: Principal(
                  name matches ".*?OTSO IAC DNE OND ADVANCED"
              )
          then
              System.out.println("Granted device delete permission to " + principle.getName());
              perm.grant();
          end



          Having principle: Principal() will make the rule match all Principals in working memory. Which would explain why it's outputing a line for all AD groups.


          However, I'm not sure why you would be expecting it to output


          10:19:13,738 INFO  [STDOUT] Granted device delete permission to 865980



          though because 865980 doesn't match ".*?OTSO IAC DNE OND ADVANCED" unless I'm missing something?


          • 2. Re: Difficulty granting permission on component
            daxxy

            Sorry about that. The part you are not getting is that my personal ID is 865980.  Since 865980 is a member of AD group 'OTSO IAC DNE OND ADVANCED', 865980 should be allowed to delete devices. That's why I would expect to see permission granted to my ID.


            I don't understand this syntax (yes have read the docs, but I still feel clueless).  I don't understand this process.


            When I tried your suggestion, I got this error




            javax.el.ELException: org.jboss.seam.InstantiationException: Could not instantiate Seam component: org.jboss.seam.security.ruleBasedPermissionResolver



            etc. etc.  here is the real cause




            Caused by: org.drools.rule.InvalidRulePackage: Rule Compilation error : [Rule name='device_delete']
                 Permissions/Rule_device_delete_0.java (7:574) : principle cannot be resolved





            I don't get it.

            • 3. Re: Difficulty granting permission on component
              njrich28

              In terms of the error above: 'principle cannot be resolved', check the spelling of principal throughout. In your original post you use both principle and principal, in my reply I also used the two different spellings. The code snippet below uses only one spelling. Some people also like to prefix assigned variable names with a $ (a legal java variable name) in Drools to distinguish them from attribute names in rules. I've done that in all examples below.



              rule "device_delete"
                  no-loop
              when
                  $perm: PermissionCheck(target == "device_delete", action == "access", granted == false)
                  $principal: Principal(
                      name matches ".*?OTSO IAC DNE OND ADVANCED"
                  )
              then
                  System.out.println("Granted device delete permission to " + $principal.getName());
                  $perm.grant();
              end



              In reply to




              I don't get it.

              Think about Drools in the same way you think about CSS. When styling a web page, the browser will look at an HTML element (the 'fact') it is applying style to and it will look through the CSS 'rules' in your stylesheet and try to match the rules against it. For example the following CSS 'rule' will match any HTML element that is a span which is an ancestor of a div element which has the someClass class set on it. Any 'rules' that match will have the styling applied to the element. You may have many CSS rules that match an idividual element and all the styles contained in those rules are applied to the element.


              div.someClass span {
                font-weight: bold;
              }
              
              span {
                color: red;
              }



              Drools has a 'working memory' into which Seam security injects certain 'facts'. In Seam the facts are not an HTML element but things like a PermissionCheck object (which contains information about the permission being checked: target, action, etc.), a Principal representing the currently logged-in user and org.jboss.seam.security.Role objects for every role that the currently logged-in user has. Once Seam has put all these things in the working memory it instructs Drools to 'fire all rules' during which Drools attempts to match all the rules in its rulebase against the objects in the working memory. Any rule which matches the objects in the working memory will then execute the java code in the 'then' part of the rule.


              Breaking down the rule above into English:


              when
                  $perm: PermissionCheck(target == "device_delete", action == "access", granted == false)
              



              the rule will be fired when


              there exists an object in the working memory that is of type 'org.jboss.seam.security.permission.PermissionCheck' with a target attribute equal to 'device_delete', an action attribute equal to 'access' and a granted attribute equal to false (the matching object will also be assigned to the variable name $perm)



                  $principal: Principal(
                      name matches ".*?OTSO IAC DNE OND ADVANCED"
                  )
              



              and there also exists an object in working memory of type java.security.Principal which has a name that ends in 'OTSO IAC DNE OND ADVANCED' (the matching object will also be assigned to the variable name $principal)




              According to your spec this rule will match correcty because org.jboss.seam.security.Role implements java.security.Principal so a Role object will match Principal(name matches ...) but I would expect it to output


              10:19:13,738 INFO  [STDOUT] Granted device delete permission to OTSO IAC DNE OND ADVANCED



              because the Principal object that matched will be the Role and not the Principal that that is the logged-in user (confusing I know).


              If you want to make the rule more readable try


              import ( existing imports here );
              import org.jboss.seam.security.Role;
              
              rule "device_delete"
                  no-loop
              when
                  $perm: PermissionCheck(target == "device_delete", action == "access", granted == false)
                  $role: Role(
                      name matches ".*?OTSO IAC DNE OND ADVANCED"
                  )
              then
                  System.out.println("Granted device delete permission to " + $role.getName());
                  $perm.grant();
              end
              



              I hope this helps.