Programming/Dot.NET

IE에서 닷넷 스마트 클라이언트 개발3-스마트 클라이언트 배포하기3

bcheul 2008. 2. 25. 13:56

출처 블로그 .. 맨 땅에 헤딩~

IE에서 닷넷 스마트 클라이언트 개발3-스마트 클라이언트 배포하기3


스마트 클라이언트 배포하기 - 3
  저 자 : 정성태

  첫 회에서 살펴 본 것처럼 ‘Microsoft .NET Framework 1.1 구성’ MMC 콘솔에 보면, ‘내 컴퓨터/런타임 보안 정책’ 하위에 세 가지 보안 정책 유형이 있는 것을 볼 수 있다. 보안 정책 내에서 변경된 내용들은 앞에 소개된 CONFIG 파일에 저장된다. 즉 우리가 만들었던 ‘SmartClientSet’과 ‘InternetSmartClient_Zone’에 대한 설정은 ‘Security.config’ 파일에서 찾아 볼 수 있다. 왜 이것이 필요하게 되는지는 잠시 후에 살펴보겠다.

① Caspol.exe를 이용한 방법을 살펴 보자. 현재로서는 액티브X로 보안 설정을 할 수 있는 유일한 방법이다.

Caspol.exe는 단순히 System.Security에 있는 클래스를 이용한 하나의 EXE 실행 파일에 지나지 않는다. 따라서 깊게 살펴 볼 사항은 없지만 필요한 사용법과 이 프로그램을 이용해서 어떻게 보안 설정을 하는지에 대한 설명을 하겠다. 우선 ‘SmartClientSet’ 권한 집합과 ‘InternetSmartClient_Zone’ 코드 그룹을 차례대로 다뤄 보자. 권한 집합을 추가하기 위한 Caspol.exe의 사용법은 다음과 같다.

caspol { -enterprise|-machine|-user } -ap
caspol { -enterprise|-machine|-user } -addpset

SmartClientSet의 경우 ‘컴퓨터’ 하위의 권한 집합에 추가될 것이므로, 첫 번째 인자는 -machine임을 알 수 있다. 문제는 인데, 해당 권한 집합을 표현하는 XML 구성을 수작업으로 하는 것은 너무 번거롭다. 그렇기 때문에 앞에 소개한 .config 파일들을 잘 이용하면 이런 경우 손쉽게 처리할 수 있다. ‘Microsoft .NET Framework 1.1 구성’ MMC 콘솔에서 새로운 권한 집합을 생성하고 그것에 원하는 권한들을 추가한 다음 저장하면 해당 권한 내용을 담은 XML 노드가 지정된 정책 설정 파일에 담겨지게 된다. 첫 회에서 소개했던 ‘SmartClientSet’ 권한 집합의 경우에는 ‘security.config’ 파일에 있으니, 메모장으로 열어 보면 다음과 같은 XML 노드를 발견할 수 있다.

<PermissionSet class=”NamedPermissionSet” version=”1”
Name=”SmartClientSet” Description=”Default rights given to internet applications”>
<IPermission class=”FileDialogPermission” version=”1”
Access=”Open”/>
<IPermission class=”IsolatedStorageFilePermission” version=”1”
Allowed=”DomainIsolationByUser” UserQuota=”10240”/>
<IPermission class=”SecurityPermission” version=”1”
Flags=”UnmanagedCode, Execution”/>
<IPermission class=”UIPermission” version=”1”
Window=”SafeTopLevelWindows” Clipboard=”OwnClipboard”/>
<IPermission class=”PrintingPermission” version=”1”
Level=”SafePrinting”/>
</PermissionSet>

아쉽게도 앞의 내용만으로는 부족하다. 권한을 나타내는 IPermission에서 클래스에 대해 완전한 어셈블리 명을 지정해 줘야 한다. 예를 들어, FileDialogPermission에 대해서는 ‘System. Security.Permissions.FileDialogPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken= b77a5c561934e089’라고 설정해 줘야 한다. 물론 이 부분에 대해서도 security.config 파일에 보면 SecurityClass 노드 셋 안에서 각각의 권한에 대한 어셈블리 명을 구할 수 있다.
일일이 모두 찾아서 치환하는 것이 귀찮을 것 같은데, 그런 독자를위해 좀 더 편한 방법을 설명해 보겠다. Caspol.exe의 경우 정책 수준을 지정하면 모든 코드 그룹을 표시해 주는 기능이 있으므로 그것을 이용하면 좀 더 쉽게 SmartClientSet 권한 집합에 대한 완전한 XML을 추출할 수 있다. 다음과 같이 명령행에서 실행해 권한 집합 내역이 담긴 텍스트 파일을 생성하자.

caspol -machine -listpset >> machinesecurity.txt

생성된 MacineSecurity.txt 파일에서 SmartClientSet만을 추출해 XML 파일(예를 들어, SmartClientSet.xml)로 별도로 저장해 두면 이후 Caspol.exe에 의해 사용될 수 있는 완전한 형식의 권한 집합 XML로 재사용될 수 있다. 이제 다른 컴퓨터에서 해당 권한 집합을 생성해 보자.

caspol -machine -addpset SmartClientSet.xml

앞의 명령을 실행 후 적용된 것을 확인하려면 반드시 ‘Microsoft .NET Framework 1.1 구성’ MMC 콘솔을 재시작해야 된다. 기존 실행되어 있는 MMC 콘솔에서는 ‘새로 고침’을 해도 나타나지 않는다.
권한 집합에 대한 추가 방법은 이걸로 끝이고, 이젠 그 권한 집합을 갖는 ‘InternetSmartClient_Zone’ 코드 그룹을 추가해 보자. 권한 집합의 경우에는 하위 권한에 대한 설정을 추가해야 하는 것으로 인해 다소 복잡한 반면, 코드 그룹의 경우에는 더 간단하게 설정된다.

caspol -machine -addgroup Internet_Zone -url http://192.168.100.19/webapp/*
SmartClientSet -n InternetSmartClient_Zone

앞과 같은 명령을 내리게 되면, Internet_Zone 하위에 URL 멤버 조건으로 선택된 ‘InternetSmartClient_Zone’ 코드 그룹이 생성된다. 실제적인 URL 경로는 여러분의 환경에 맞게 설정하면 된다. 정리해 보면 Caspol.exe를 이용해 보안 설정을 자동화하는 프로그램을 개발하는 단계는 다음과 같다.

① 액티브X 프로젝트 생성
② 리소스 파일로 caspol.exe의 -listpset 옵션으로 구한 SmartClientSet.xml 파일을 담아둔다.
③ 액티브X의 초기화 함수나 별도의 메쏘드를 정의하여 caspol -addposet과 caspol -addgroup을 실행하는 CreateProcess/ShellExecute Win32 API를 실행

앞의 내용으로 구현한 액티브X DLL의 소스 파일은 ‘이달의 디스켓’에 ‘AxForSmartClient’ 프로젝트로 첨부해 놓았으니 참고하자.

② System.Security를 이용한 보안 설정 프로그래밍. 액티브X에서는 이용할 수 없고 닷넷 개발 언어로 만든 경우에만 이용 가능하다.

Caspol.exe에 대한 사용법을 아는 것도 유용하지만, 그 내부에서 어떻게 돌아가는지를 아는 것도 그에 못지 않게 중요하다. 프로그래밍으로 구현하는 순서도 caspol.exe로 할 때와 동일하다. 우선 새로운 권한 집합 SmartClientSet을 생성한다.
NamedPermissionSet permSet = new NamedPermissionSet( “SmartClientSet”, PermissionState.None );

앞처럼 권한 집합 생성은 단순히 클래스 인스턴스 하나를 정의하는 것으로 끝난다. 두 번째 인자에 대해서 좀 더 알아 본다면, Named PermissionSet 클래스의 생성자에서 PermissionState 인자를 지정하지 않으면 기본적으로 ‘무제한’ 리소스 접근인 ‘Full Trust’와 동일한 권한 집합이 된다. 권한 허용은 Permission State.None으로 시작해서 원하는 권한을 추가하는 방식으로만 가능하며, 그 반대로 PermissionState.Unrestricted로 시작해서 권한을 제거하는 것은 허용되지 않는다. 이제 우리가 원하는 각각의 권한이 어떻게 클래스로 구현되는지 알아 볼 차례이다.

<IPermission class=”FileDialogPermission” version=”1” Access=”Open”/>
FileDialogPermission fileDialogPerm =
new FileDialogPermission( FileDialogPermissionAccess.Open );
<IPermission class=”IsolatedStorageFilePermission” version=”1”
Allowed=”DomainIsolationByUser” UserQuota=”10240”/>
IsolatedStorageFilePermission isolatedStorageFilePerm =
new IsolatedStorageFilePermission( PermissionState.None );
isolatedStorageFilePerm.UsageAllowed =
IsolatedStorageContainment.DomainIsolationByUser;
isolatedStorageFilePerm.UserQuota = 10240;
<IPermission class=”SecurityPermission” version=”1”
      Flags=”UnmanagedCode, Execution”/>
SecurityPermission securityPerm =
new SecurityPermission( SecurityPermissionFlag.UnmanagedCode
| SecurityPermissionFlag.Execution );
<IPermission class=”UIPermission” version=”1”
Window=”SafeTopLevelWindows” Clipboard=”OwnClipboard”/>
UIPermission uiPerm = new UIPermission( UIPermissionWindow.SafeTopLevelWindows,
UIPermissionClipboard.OwnClipboard );
<IPermission class=”PrintingPermission” version=”1”
Level=”SafePrinting”/>
PrintingPermission printingPerm =
new PrintingPermission( PrintingPermissionLevel.SafePrinting );

Security.Config 파일에 설정된 <IPermission/> 노드 하나당 동일한 이름의 권한 클래스를 만들어서 정의한 후 속성에 지정된 값들을 권한 클래스의 속성에 그대로 지정하면 된다. 앞과 같이 권한 클래스를 생성했다면 권한 집합에 NamedPermissionSet. AddPermission을 이용해서 추가할 수 있다. 이렇게 구성된 권한 집합 인스턴스를 ‘Machine’ 정책에 추가한 후 수정사항을 반영하면 된다. 해당 Machine 정책에 대한 클래스화된 인스턴스를 찾기 위해서는 System.Security.SecurityManager 클래스의 static으로 정의된 PolicyHierarchy 메쏘드를 사용하여 다음과 같이 구현될 수 있다.

PolicyLevel machinePolicyLevel = null;
System.Collections.IEnumerator ph = SecurityManager.PolicyHierarchy();

// 다음의 코드를 통해 “Enterprise”, “Machine”, “User” 정책을 열람
while( ph.MoveNext() ) {
PolicyLevel pl = (PolicyLevel)ph.Current;
if( pl.Label == “Machine” ) {
machinePolicyLevel = pl;
break;
}
}
NamedPermissionSet permSet = new NamedPermissionSet( “SmartClientSet”, PermissionState.None );
///////// permSet 구성 부분 생략 /////////////
machinePolicyLevel.AddNamedPermissionSet( permSet );

// 변경된 사항을 security.config 파일에 저장
SecurityManager.SavePolicy();

이와 같이 새로운 권한 집합이 생성되는데, 사실 단순 작업의 반복일 뿐 그다지 어려운 사항은 없다. 다음으로 앞에서 생성한 ‘SmartClientSet’ 권한 집합을 갖는 ‘InternetSmartClient_Zone’ 코드 그룹을 생성해 보겠다. 코드 그룹의 경우 동일한 이름으로 CodeGroup이라는 클래스가 존재하지만 추상 클래스인 관계로 직접 생성할 수는 없고 파생 클래스인 UnionCodeGroup을 이용해 인스턴스화해야 한다.
UnionCodeGroup의 생성자에서 해당 코드 그룹에 적용될 ‘멤버 조건’과 ‘권한 집합’을 지정한다. 권한 집합의 경우 앞에서 생성한 permSet 인스턴스를 넣어주면 되지만, 멤버 조건의 경우는 우리가 원하는 상황을 반영하는 클래스를 만들어야 한다. 현재 구현된 멤버 조건은 총 8개가 있다.
스마트 클라이언트의 경우 웹에서 배포되므로 UrlMembership Condition을 선택해 다음과 같이 인스턴스를 생성해야 한다.

IMembershipCondition memberShipCondition = new UrlMembershipCondition( “http://127.0.0.1/webapp/*” );

물론, 앞에 지정된 URL은 각자 자신의 상황에 맞게 수정해야 한다. 이렇게 코드 그룹에 대한 멤버 조건이 결정되었으면 Union CodeGroup을 생성할 수 있다.

// 이전에 생성해 두었던 SmartClientSet 권한 집합을 갖는 PolicyStatement 클래스 생성
PolicyStatement policyStatement = new PolicyStatement( permSet );

// 권한 집합과 멤버 조건을 갖춘 코드 그룹 생성
CodeGroup smartClientGroup = new UnionCodeGroup( memberShipCondition, policyStatement );
smartClientGroup.Name = “InternetSmartClient_Zone”;

// Machine 정책의 코드 그룹에 추가
level.RootCodeGroup.AddChild( smartClientGroup );



생성자에서 멤버 조건과 권한 집합을 지정하고, 이후 Name 속성에 생성될 코드 그룹에 대한 이름을 지정한다. 그런 후 코드 그룹을 이미 정책에 포함되어 있는 기존 코드 그룹의 자식에 추가하고 Security Manager.SavePolicy() 메쏘드를 호출하면 모든 설정이 끝난다. 완전한 실행 코드는 ‘이달의 디스켓’에 ‘SmartClientSecurity Setup’이라는 C# 콘솔 프로젝트를 추가했으니 참고하자.
비록 개발자인 여러분들은 프로그래밍을 통한 보안 설정을 아는 것도 중요하지만, 현실적인 이유로 인해 필자의 경우에는 Caspol.exe를 통한 보안 설정을 추천한다. C/C++로 만든 액티브X에서도 사용할 수 있다는 장점도 있지만, 무엇보다도 복잡한 권한 설정을 쉽게 마무리할 수 있기 때문이다. 만약 하나의 권한 집합에 권한이 30개라면 그 권한 하나하나에 해당하는 클래스를 일일이 프로그래밍으로 구현해야 할 텐데, 여간 귀찮은 일이 아닐 수 없다. 대신에 그러한 권한 설정을 MMC에서 제공하는 손쉬운 UI로 처리하고 Caspol.exe -listgroups 옵션으로 해당 권한 집합을 XML 파일로 별도 저장한 후 Caspol.exe -addpset으로 추가하는 것이 시간적인 면으로도 유리할 수 있다.