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
2012. 7. 18. 09:09 IT

배경 : gradle의 pmd plugin은 rule파일을 제대로 인식하지 못하고, csv 형태의 report파일 생성을 지원하지 않음.


해결책 : ant pmd task를 호출.


// apply plugin: 'pmd'


configurations {

    pmd // for code inspection

}

dependencies {

    pmd group:'pmd', name:'pmd', version:'4.2.5'  

}


task pmd << {

def ruleFilePath =  "..... /pmd-rule.xml";

ant.mkdir(dir:project.reporting.baseDir)

def reportFile = project.reporting.baseDir.toString() + "/pmd_" + new Date().format("yyyy-MM-dd") +".csv"

def excludesFiles = "*/test/**,*/sample/**,**/*Test*.java";

def includeDir = "*/src/**";

def checkDir = "../..";


ant.taskdef(name: 'pmd', classpath:configurations.pmd.asPath, 
             classname:"net.sourceforge.pmd.ant.PMDTask" );

ant.pmd( rulesetfiles: ruleFilePath,
failonerror: false,
maxRuleViolations: 9999,
shortFilenames: true){
formatter(type: 'csv', toFile:  reportFile)
fileset(dir: checkDir, includes: includeDir, excludes: excludesFiles)
};
}

기타 : 각각 프로젝트별로 pmd report를 만들고 병합하려고 했지만... 귀찮아서 통으로 돌리고 skip. 

posted by smplnote
2012. 7. 17. 19:41 IT



httpclient 를 쓰는데 POST 로 requestbody 에 데이터 전송하는 방법을 잊지않기 위해 기록함. 



import org.apache.http.*;

import org.apache.http.client.methods.*;

import org.apache.http.entity.*;

import org.apache.http.impl.client.*;

import org.apache.http.message.*;


// json string 전달을 위해 Builder를 사용. 

JsonBuilder builder = new groovy.json.JsonBuilder();

// make json object // 주의사항. 변수명을 json key 값과 같게 주면 문제가 생길 수 있음... 

builder {

id  myid

name myname

}


HttpPost method = new HttpPost("${RestUrl}/resources");

StringEntity requestEntity = new StringEntity(builder.toString() , "utf-8");

requestEntity.setContentType(new BasicHeader("Content-Type", "application/json"));

method.setEntity(requestEntity);


// header setting... 


HttpResponse response = httpclient.execute(method);

if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

   // do something...

}

posted by smplnote
2012. 7. 4. 11:19 IT

증상 : 

Spring의 SpringJUnit4ClassRunner 클래스를 이용하여 Session Scope로 정의한 Bean을 테스트하려고 할때 

아래와 같은 에러가 발생함.


java.lang.IllegalStateException : No Scope registered for scope 'session' 


solution : session scope을 처리하는 bean을 SimpleThreadScope 으로 바꿔치기하면 됨 


test용 context.xml 에 다음을 추가. 


<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="session">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
    </property>
</bean>


reference : http://blog.solidcraft.eu/2011/04/how-to-test-spring-session-scoped-beans.html



posted by smplnote
2012. 4. 16. 08:54 IT

- WHY?


gradle의 멀티 플로젝트 설정 가이드를 따라가면 늘 최상위 경로에 settings.gradle 을 구성하게된다.

당연히 전체 프로젝트에 대해 계층적인 구조를 가져가는 것이 상식이다.

하지만 eclipse 관점에서만 볼때, 모든 프로젝트는 항상 같은 레벨에서 관리가 된다. 

때문에 상위 경로에서 멀티 프로젝트를 관리하는 개념을 도입할때 어떻게 해야 할지 고민하게 된다.

eclipse project 단위로 형상을 관리할 경우, 상위 경로에 있는 멀티프로젝트 설정파일은 버전관리 대상에서 제외 되어 버리기 때문이다. 


물론... gradle user guide에서 설명을 안했을 뿐이지, 멀티프로젝트 관리를 반드시 계층적으로 해야 하는 것은 아니다. 


다음과 같이 설정할 수 있다.


- project-emma : multi-project관리용 root project

   settings.gradle

   build.gradle

- project-navi : child project 1. Type : java library

   build.gradle

- project-bovary : child project 2. Type: web application. it depends on project-navi

   build.gradle


[$project-emma/settings.gradle]

// define projects

include 'navi', 'bovary'


// define sub-projects location

project(':navi').projectDir = new File(rootDir, '../project-navi')

project(':bovary').projectDir = new File(rootDir, '../project-bovary')

[$project-emma/build.gradle]
// define subproject configuration
subprojects{
// define plugins
apply plugin: 'java'
repositories {
mavenCentral()
}
// set compile encoding
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
}
[$project-navi/build.gradle]
jar {
destinationDir = file("dist"); // 별도 위치에 저장하고 싶을 경우에만 명시.
}
[$project-bovari/build.gradle]
apply plugin: 'war' // compile -> war -> assemble
dependencies {
compile project(':navi') // navi project에 대한 의존성을 명시.
 }

당연하지만, 멀티프로젝트 관리용으로 빈 프로젝트를 만들어야 할 필요는 없다. (navi의 하위 경로에 지정해도 가능하다는 말임) 앞으로도 유용하게 사용할 수 있을 듯 싶음. 


posted by smplnote
2012. 4. 12. 09:14 IT

[WHY] 

eclipse에서 grails plugin을 설치하지 않고도  ant  view에서 편리하게 각각의 gradle 명령을 사용하고 싶었음.


참고한 reference를 보면 gradle이 설치되어 있고 GRADLE_HOME 환경변수가 설정된 상태를 전제로 한다.


앞글에서 설명했던 gradlew 를 이용하면 미리 gradle binary들 설치하고 환경변수를 설정하지 않고도 빌드실행이 가능해진다. 




[Prerequisite]

== gradle wrapper생성을 통해 만들어진 파일들 (3)

gradlew.bat or gradlew

gradle/wrapper/gradle-wrapper.jar

gradle/wrapper/gradle-wrapper.properties


== 실제 build를 수행할 build 파일

build.gradle

// this is sample...

apply plugin: 'java'

repositories {

mavenCentral()

}

[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

jar {

destinationDir = file("dist")

}


== gradle을 수행할 ant build wrapper 

build.xml

<project name="build-gradle"  default="help"  basedir=".">

<property environment="env" />

<property name="gradle.executable" location="./gradlew.bat" /><!-- for window -->

<target name="help">

<exec executable="${gradle.executable}" dir=".">

<arg value="tasks" />

</exec>

</target>

<target name="build"> <!-- 모든 포함된 project의 build task를 실행 -->

<exec executable="${gradle.executable}" dir=".">

<arg value="build" />

</exec>

</target>

<!--

<target name="subproject-build" description=" 특정 subproject의 build task만 실행시키고 싶을때 사용">

<exec executable="${gradle.executable}" dir=".">

<arg value=":common:build" />

</exec>

</target>

-->

</project>

이제, 필요할 때마다 ant target을 추가하면된다. 



reference : https://gist.github.com/735788 

posted by smplnote
2012. 1. 13. 16:51 IT

- 준비물
JDK 1.6.X
STS  (현재버전 2.9.0 M1) 

- 설치 
1. STS 실행후 Dashboard의 Extension Tab으로 가서 Grails 와 Grails Support 를 추가로 설치.
컴파일러를 groovy 1.8로 바꾸려면 Groovy Eclipse 플러그인을 다시 추가해야한다 . (이거 dependency 걸어서 같이 받게좀 해주세요.. )
참조 :  http://grails.org/STS+Integration 

2. STS재실행후  grails 홈 설정 ( STS 실행경로 바로 상위에 grails-2.0.0 이 생김. )

3.  http://grails.org/Quick+Start   따라하면 됨.. 

cf) H2 메모리 DB를 이용해서 테스트할때 좋은건 Grails가 DB web 콘솔을 기본으로 제공한다는것 ( 2.0 소개 스크린캐스트에서 발견..) 이때 jdbc url은 conf/DataSource.groovy 파일에 있는 설정값을 이용하면 된다. 


ps. 왠지 그레일즈는 설치해서 튜토리얼 한번 해보고 뭐좀 더 해보려다가 멈추게 된다.
진중하게 좀 파고들어야 하는데...
그리고 STS는 왤케 느리냐..  
다음엔 grails의 spring security 아니면  spring-security-facebook  을 조금 건드려볼까함.. 

posted by smplnote
2011. 11. 29. 15:35 IT

SQL Inspection 을 다루다보니 필요해진게 iBatis Framework의 XML파일에서 SQL 문장을 추출하는일.

이리저리 찾아보다보니 나오더라.



import java.io.Reader;
import groovy.lang.Singleton;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.ibatis.sqlmap.client.SqlMapException
import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
import com.ibatis.sqlmap.engine.mapping.sql.Sql;
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
import com.ibatis.sqlmap.engine.scope.RequestScope;
@Singleton
class IbatisUtil {
static SqlMapClientImpl mapClient;
static RequestScope request;
static{
request = new RequestScope(); // 고정값으로 미리 생성해둔다. 
}
       // 초기화 작업 (sqlmapImpl 생성) 
public static void init(String file){
getIbatisMapClient(file);

        // ibatis의 SqlMapClientImpl을 생성한다.  
private static void getIbatisMapClient(String resource) {
Reader reader = getDynamicReader(resource);
try{
mapClient = (SqlMapClientImpl) SqlMapClientBuilder.buildSqlMapClient(reader);
}catch(Exception e){ 
// classpath 상에 VO 가 없을 경우 예외가 발생할 수 있다. 
}
}
        // 특정 ID에 대하여 sql 을 반환한다. 
public static String getSql(String id){
if(mapClient==null){
return null;
}else{
try{
MappedStatement mappedStatement = mapClient.getMappedStatement(id); 
mappedStatement.initRequest(request);
Sql sql = mappedStatement.getSql();
return sql.getSql(request,null);
}catch(Exception e){ // 동적변수의 값이 null이거나, ID가 없거나 등의 예외가 발생할 수 있다. 
return null;
}
}
}
        // 더미로 sqlMapConfig을 생성해준다. 여기서는 로컬 sqlMap 파일을 연결하므로 url=file 방식을 사용한다. 
private static Reader getDynamicReader(String resource) {
StringBuffer value = new StringBuffer();
value.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
value.append("<!DOCTYPE sqlMapConfig PUBLIC \"-//ibatis.apache.org//DTD SQL Map Config 2.0//EN\" \"http://ibatis.apache.org/dtd/sql-map-config-2.dtd\">");
value.append("<sqlMapConfig>");
println resource.replaceAll("\\\\", "/")
value.append("<sqlMap url=\"file:///" + resource.replaceAll("\\\\", "/") + "\"/>");
value.append("</sqlMapConfig>");
return new java.io.StringReader(value.toString());
}
}
posted by smplnote
2011. 10. 21. 16:30 카테고리 없음
4.1 버전부터 지원하는 기능이네요.

crossContext 속성을 true로 하면 동일한 tomcat instance 내에서 실행되는 다수의 web application 간에 세션정보를 공유할수 있습니다.

ServletContext.getContext()

http://tomcat.apache.org/tomcat-4.1-doc/config/context.html

posted by smplnote
2011. 8. 19. 11:42 카테고리 없음
CODENARC
Tool > Static Analysis
저자 : Chris Mair
홈페이지  : http://codenarc.sourceforge.net/


CodeNarc analyzes Groovy code for defects, bad practices, inconsistencies, style issues and more.

[LICENSE] Apache License V2.0  


[requirement]
groovy 1.7
java 1.5 or later
log4j 1.2.13 or later


eclipse plugin 
Supported Eclipse versions: 3.5, 3.6 and 3.7
http://codenarceclipse.sourceforge.net/ 
posted by smplnote