2012. 8. 16. 09:08 IT

목적 : Access Control 표준이 XACML 이란다.


경과 : 

몇가지 xacml 관련 구현체들을 찾아보았는데,

상용이 아닌 것으로 가장 활발한 곳은 jboss xacml 구현체인 picketbox 였다. 

Picketbox는  Java Security Framework의 하나인데,  Oasis XACML v2.0 에 호환되는 엔진을 제공한다. 



절차 


1. xacml library download

from http://www.jboss.org/picketbox/downloads

jbossxacml-2.0.8.Final.jar


2. add library 

WEB-INF/lib 또는 기타 classpath 상에 해당 jar 파일을 배치한다.


3. register ACL Interceptor to spring mvc context 

> context/servlet-context.xml

<mvc:interceptors>        <mvc:mapping path="/*"/>                    

                     <bean class="com.MyACLInterceptor" >

                     <property name="config" value="config/policyConfig.xml"/><!-- pdp file classpath -->

                      </bean>

</mvc:interceptor>

...

</mvc:interceptors> 

4. write PDP (Policy Decision Point)  configuration file
Caching과 관련해서는 아래 Reference 를 참조

> config/policyConfig.xml

<ns:jbosspdp xmlns:ns="urn:jboss:xacml:2.0">

           <ns:Policies>

                     <ns:PolicySet>

                                <ns:Location>config/mypolicyset.xml</ns:Location>

                     </ns:PolicySet>

           </ns:Policies>

<ns:Locators>

<ns:Locator Name="org.jboss.security.xacml.locators.JBossPolicySetLocator"/>

</ns:Locators>

</ns:jbosspdp>

5. policy set 정의

> config/mypolicyset.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<PolicySet xmlns="urn:oasis:names:tc:xacml:2.0:policy:schema:os"  PolicySetId="policyset"

  PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable">

           <Target />

           <Policy xmlns="urn:oasis:names:tc:xacml:2.0:policy:schema:os"

                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                     xsi:schemaLocation="urn:oasis:names:tc:xacml:2.0:policy:schema:os

        access_control-xacml-2.0-policy-schema-os.xsd"

                     PolicyId="my-policy"

                     RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable">

                     <Description>access control policy</Description>

                     <Target />

 <Rule RuleId="myruleid" Effect="Permit"><!— Permit / Deny  -->

           <Description>my rule</Description>

           <Target >

           <Subjects/>

           <Resources> 

                    <Resource> 

                              <ResourceMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match"> 

                                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">^/( accessuri1|accessuri2)</AttributeValue> 

                                        <ResourceAttributeDesignator 

                                        AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string"/> 

                                        </ResourceMatch> 

        </Resource> 

         </Resources> 

           </Target>

           <Condition>

                      <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">

                                <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">ACCESSIBLE_ROLE_NAME</AttributeValue>

                                <SubjectAttributeDesignator

                                          DataType="http://www.w3.org/2001/XMLSchema#string" AttributeId="urn:oasis:names:tc:xacml:2.0:subject:role" />

                     </Apply>

           </Condition>

</Rule>

. . . 

<Rule RuleId="ImplicitDeny" Effect="Deny" />

</Policy>

</PolicySet>


-   policy-combining-algorithm은 경우에 따라 적절하게 사용할 것. ( first-applicable은 첫번째 걸리는 Rule을 따른다는 의미 )

- Rule의 Effect는 Permit 아니면 Deny 를 선택할수 있음

ResourceMatch  로 대상 Resource 를 정의할 수 있음

Condition 으로 Rule의 detail을 표현할 수 있음


cf) Policy 작성 BP. ( Ref. 1 - 2.7 )

- policy와 file 이름을 동일하게.

- 룰 조합 규칙은 가능한 심플하게. first-applicable 권고

- Permit, Deny 를 섞기말고 가능한 한쪽으로 모는것이 좋음. 


6. Interceptor 작성

MyACLInterceptor.java

public class MyACLInterceptor extends HandlerInterceptorAdapter {

private String config = "";

public  String getConfig(){

return this.config;

}

public void setConfig(String config){

this.config = config;

}

public boolean preHandle(HttpServletRequest request,

HttpServletResponse response, Object handler) throws Exception {

if (!hasAccessRole(request)) {

throw new Exception("access not allowed.");

}

return true;

}

private boolean hasAccessRole(HttpServletRequest request) {
String  resourceId  = request.getRequestURI(); // URI
List<String> userRoles = getUserRoles(request); // User ROLES
ACLManager acm = ACLManager.getInstance(this.config); 
return acm.evaluate(userRoles, resourceId);
}
        List<String> getUserRoles(HttpServletRequest request){
              return "get user role from session or persistence data".....
        }
}


7. ACLManager 작성


public class ACLManager {

private static ACLManager instance;

private PolicyDecisionPoint pdp = null;

public boolean evaluate(List<String>userRoles, String resourceId) throws Exception{

RequestContext request = createXACMLRequest(userRoles, resourceId);

// try { request.marshall(System.out); } catch (IOException e) { }

ResponseContext response = this.pdp.evaluate(request);

return XACMLConstants.DECISION_PERMIT == response.getDecision();

}


public RequestContext createXACMLRequest(List<String>userRoles, String resourceId) throws Exception{

RequestContext requestCtx = RequestResponseContextFactory.createRequestCtx();

     SubjectType subject = new SubjectType();

     subject.getAttribute().add(RequestAttributeFactory.createStringAttributeType(XACMLConstants.ATTRIBUTEID_SUBJECT_ID, "myissuer", "mysubject"));

     for(String role : userRoles) {

        AttributeType attSubjectID = RequestAttributeFactory.createStringAttributeType(XACMLConstants.ATTRIBUTEID_ROLE, "myissuer", role);

        subject.getAttribute().add(attSubjectID);

     }

     ResourceType resourceType = new ResourceType();

     resourceType.getAttribute().add(RequestAttributeFactory.createStringAttributeType(XACMLConstants.ATTRIBUTEID_RESOURCE_ID, null, resourceId ));

     

     ActionType actionType = new ActionType();

     actionType.getAttribute().add(RequestAttributeFactory.createStringAttributeType("action-id", "myissuer", "read"));


     RequestType requestType = new RequestType();

     requestType.getSubject().add(subject);

     requestType.getResource().add(resourceType);

     requestType.setAction(actionType);

     requestCtx.setRequest(requestType);

return requestCtx;

}

private void setPDP(String pdpPath) throws Exception {

  InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(pdpPath);

  this.pdp = new JBossPDP(is); 

}

private ACLManager(String pdpPath) throws Exception{

setPDP(pdpPath);

}

public static synchronized ACLManager getInstance(String pdpPath) throws Exception{

if (instance == null) {

instance = new ACLManager(pdpPath);

}

return instance;

}

}



[References]

1) XACML Function List : http://fedora-commons.org/download/2.2/userdocs/server/security/XACMLPolicyGuide.htm 

XACML caching for Performance : https://community.jboss.org/wiki/XACMLCachingForPerformance


posted by smplnote