Hey, Scripting Guy!Active Directory 검색

The Microsoft Scripting Guys

코드 다운로드 위치: HeyScriptingGuy2009_02.exe(151 KB)

목차

도움말 제공
핵심 요소
도우미 함수

아는 분도 있겠지만 Scripting Editor와 필자는 최근에 새 정식 Microsoft Scripting Guy로 합류하여 scripter@microsoft.com 전자 메일 계정에 배달되는 수천 통의 메시지를 확인하느라 정신 없이 보내고 있습니다. 그런데 굳이 통계를 내보지 않더라도 "Active Directory 브라우저를 구하는 방법"을 묻는 문의 메일이 가장 많았다는 사실을 알 수 있습니다. 하지만 Scripting Guy도 그런 브라우저는 본 적이 없습니다. 열심히 찾고 또 찾아봤지만 없더군요.

최후의 수단으로 인터넷 게시판에서 은밀하게 수도 없이 물어본 끝에 코딩된 답변을 얻어 해독한 결과 ADSI Scriptomatic이 실은 Active Directory 브라우저라는 것을 알게 되었습니다. 하지만 Active Directory 브라우저로 불리지도 않고 실제로 Active Directory를 검색하는 용도로 개발된 것도 아니기 때문에(ADSI 스크립트 작성용) Active Directory 스키마를 검색할 수 있는 Windows PowerShell 스크립트를 직접 작성하기로 마음 먹었습니다. 이상한 이름이긴 하지만 BrowseActiveDirectorySchema.ps1이라고 불리는 이 스크립트는 그림 1에 나와 있습니다.

그림 1 BrowseActiveDirectorySchema.ps1

Param($action,$class, [switch]$help)

Function GetHelp()
{
  $helpText= '
@"
 DESCRIPTION:
 NAME: BrowseActiveDirectorySchema.ps1
 Browse Active Directory Schema. Lists Classes, and properties. 

 PARAMETERS: 
 -Action <L(ist all classes), M(andatory), O(ptional), F(ind)>
 -Class class to search: user, computer, person, contact etc
 -Help displays this help topic

 SYNTAX:
 BrowseActiveDirectorySchema.ps1 -A L
 Lists the name of each class defined in the AD schema

 BrowseActiveDirectorySchema.ps1 -A M -c user
 Lists the mandatory properties of the user class

 BrowseActiveDirectorySchema.ps1 -A O -c computer
 Lists the optional properties of the computer class

 BrowseActiveDirectorySchema.ps1 -A F -c user
 Lists all Active Directory Classes that contain the word user 
 in the actual class name

 BrowseActiveDirectorySchema.ps1 -Action Find -c user
 Lists all Active Directory Classes that contain the word user 
 in the actual class name

 BrowseActiveDirectorySchema.ps1 -help
 Prints the help topic for the script
"@ #end helpText
  $helpText
} #end GetHelp
Function GetADSchema($Action, $class)
{
 $schema = [DirectoryServices.ActiveDirectory.ActiveDirectorySchema]::GetCurrentSchema()
 Switch ($Action)
  {
   "classes" { 
              $schema.FindAllClasses() | 
              Select-Object -Property Name 
             }
   "Mandatory" 
             {
              "Mandatory Properties of $class object"
              ($schema.FindClass("$class")).MandatoryProperties | 
               Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
             }
   "Optional" 
             {
              "Optional Properties of $class object"


              "This might take a few seconds ..."
              ($schema.FindClass("$class")).OptionalProperties | 
              Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
             }
   "Find" 
             {
              $schema.FindAllClasses() | 
              Where-Object { $_.name -match "$class" } |
              Select-Object -property name
             }
   DEFAULT {"$action is not a valid action." ; GetHelp ; Exit}
  }
} #end GetADSchema

Function GetAllClasses()
{
 GetAdSchema("classes")
} #end GetAllClasses

Function GetMandatory($class)
{
 GetAdSchema -action "Mandatory"  -class $class 
} #end GetMandatory

Function GetOptional($class)
{
 GetAdSchema -action "Optional"  -class $class 
} #end GetOptional

Function FindClasses($class)
{
 GetAdSchema -action "Find" -class $class
} #end FindClasses
# *** Entry Point to Script ***
if($help) { GetHelp ; Exit }

Switch ($action)
{
 "L" {GetAllClasses ; Exit}
 "M" {GetMandatory($class) ; Exit}
 "O" {GetOptional($class) ; Exit}
 "F" {FindClasses($class) ; Exit}
 DEFAULT { "$action is not a valid action." ; GetHelp ; Exit} 
}

그림에서 보듯이 이 스크립트는 Param 문으로 시작합니다. 이 명령문은 서로 다른 동작을 확인하기 위해 스크립트를 편집하는 대신 스크립트를 실행하면서 수정할 수 있도록 해주는 세 가지 유용한 명령줄 매개 변수를 만드는 데 사용됩니다.

Param($action,$class, [switch]$help)

예를 들어 AD DS(Active Directory 도메인 서비스)의 필수 속성을 확인하려는 경우 그림 2와 같이 –action M과 –class user를 지정합니다.

fig02.gif

그림 2 user 클래스의 필수 속성 보기

마찬가지로 group 클래스의 선택적 속성도 쉽게 선택할 수 있습니다. 이렇듯 계획하고 테스트하는 대신 런타임에 스크립트의 동작을 수정할 수 있다는 것이 바로 명령줄 매개 변수의 이점입니다. 따라서 한 번만 사용하는 것이 아니라 유틸리티로 사용할 스크립트는 명령줄 매개 변수를 사용하여 작성하는 것이 좋습니다.

도움말 제공

그림 1에서 스크립트의 다음 섹션에는 GetHelp 함수가 나와 있습니다. 명령줄 매개 변수를 표시하는 스크립트를 작성할 때는 스크립트 사용 방법에 대한 도움말을 표시하는 함수를 포함하는 것이 좋습니다. 스크립트 사용자가 기능을 알아보기 위해 도움말 파일을 열고 필요한 내용을 찾아 전체를 살펴보도록 하는 것은 바람직하지 않습니다. 알아보기 쉽도록 간결하게 작성하는 것이 스크립트 설계의 기본 원칙이긴 하지만 도우미 함수를 포함하는 편이 사용자의 입장에서는 훨씬 도움이 됩니다.

GetHelp 함수는 Get-Help cmdlet와 매우 유사한 방식으로 정보를 표시합니다. 표시되는 내용은 설명, 매개 변수 및 구문의 세 가지 섹션으로 나뉩니다. GetHelp는 표시할 텍스트가 포함된 here-string을 만든 다음 here-string이 들어 있는 변수(예제의 경우 $helpText)의 내용을 표시합니다.

here-string은 따옴표 사용 규칙에 신경 쓰지 않고 정보를 입력하고 출력 서식을 지정할 수 있도록 하는 Windows PowerShell 구문입니다. here-string에 입력한 내용은 모두 텍스트로 간주됩니다. GetHelp는 –help 스위치를 사용하여 스크립트를 실행하거나 잘못된 매개 변수를 입력한 경우 호출됩니다. 그림 3은 –help 스위치를 사용하여 스크립트를 호출한 결과를 보여 줍니다.

fig03.gif

그림 3 –help 스위치를 사용한 스크립트 호출

핵심 요소

다음으로 그림 1의 스크립트에서 대부분의 실질적인 작업을 수행하는 GetADSchema 함수가 있습니다. 이 함수에서 핵심은 DirectoryServices.ActiveDirectory.ActiveDirectorySchema라는 Microsoft .NET Framework 클래스를 사용하는 것입니다. 이 클래스를 대괄호 안에 넣고 대괄호 뒤에 콜론을 두 개 추가하여 클래스의 메서드(예제의 경우 GetSchema 및 GetCurrentSchema)에 액세스할 수 있습니다.

GetCurrentSchema 정적 메서드는 현재 연결된 스키마를 나타내는 ActiveDirectorySchema 클래스의 인스턴스를 반환합니다. 그림 4에는 ActiveDirectorySchema 클래스의 멤버가 나와 있습니다.

fig04.gif

DirectoryServices.ActiveDirectory.ActiveDirectorySchema .NET Framework 클래스의 인스턴스를 생성하고 그 결과로 생성된 스키마 개체를 $schema 변수에 저장한 후에는 수행할 작업을 결정해야 합니다. 이를 위해 Switch 문은 $action 변수에서 전달된 값을 평가합니다.

부합하는 조건에 따라 GetADSchema 함수는 AD DS에서 모든 클래스를 찾거나 특정 클래스의 필수 또는 선택적 속성을 표시하거나 지정된 조건에 맞는 클래스를 검색합니다. Switch 문을 사용하는 경우 항상 기본 조건을 포함하는 것이 좋습니다.

도우미 함수

코드의 일부분을 나누고 스크립트를 확장하기 쉽도록 하기 위해 실행 시에 스크립트로 전달되는 매개 변수에 따라 호출되는 여러 가지 도우미 함수를 추가했습니다. 각각의 도우미 함수는 GetADSchema를 호출하고 명령줄에서 -action 매개 변수에 제공되는 값에 따라 다른 매개 변수 집합을 전달합니다.

첫 번째 도우미 함수인 GetAllClasses는 GetADSchema를 호출하고 "classes"라는 단어를 전달합니다. 그리고 GetADSchema 함수의 Switch 문이 "classes"라는 문자열과 일치하면 ActiveDirectorySchema 클래스의 FindAllClasses 메서드를 호출합니다. Switch 문으로 호출되는 코드는 다음과 같습니다.

"classes" { 
              $schema.FindAllClasses() | 
              Select-Object -Property Name'

GetAllClasses 함수는 다음과 같습니다.

Function GetAllClasses()
{
GetADSchema("classes")
} #end GetAllClasses

다음 도우미 함수는 GetMandatory로, 스크립트 실행 시에 –class 매개 변수에 지정된 개체의 필수 속성을 반환합니다. 이 함수는 –class 매개 변수를 통해 명령줄에서 $class의 값을 받습니다. GetMandatory는 GetADSchema 함수를 호출할 때 매개 변수를 두 개 전달합니다. 전달되는 매개 변수가 두 개이므로 두 매개 변수 모두에 전체 이름을 지정하여 코드에서 쉽게 인식되도록 하는 것이 좋습니다. 반면 GetAllClasses 함수에서는 GetADSchema 함수를 호출할 때 –action 매개 변수를 사용하지 않습니다. 이 경우 "classes" 값은 그 위치를 기준으로 전달됩니다.

GetADSchema 함수가 호출되면 ActiveDirectorySchema 클래스의 FindClass 메서드를 사용하여 $class 변수에 지정된 클래스를 검색한 후 ActiveDirectorySchemaClass 클래스의 인스턴스를 반환합니다. 이 클래스의 멤버는 그림 5에 나와 있습니다.

fig05.gif

다음으로 GetADSchema 함수는 반환된 개체의 MandatoryProperties 속성을 쿼리하고 결과를 Format-Table cmdlet에 전달합니다. Format-Table cmdlet는 Name, Syntax 및 IsSingleValued 속성을 선택하여 출력합니다. Format-Table cmdlet의 스위치 매개 변수인 –Autosize는 가능하면 속성 값이 잘리지 않도록 열 크기를 자동으로 조정합니다. 다음은 "Mandatory"라는 문자열과 일치하는 경우 실행되는 코드입니다.

"Mandatory" 
       {
       "Mandatory Properties of $class object"
       ($schema.FindClass("$class")).MandatoryProperties | 
       Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
       }

GetMandatory 함수는 다음과 같습니다.

Function GetMandatory($class)
{
 GetAdSchema -action "Mandatory" -class $class 
} #end GetMandatory

다음으로 GetOptional 함수가 어떻게 AD DS 클래스의 선택적 속성을 표시하는지 살펴보겠습니다. GetOptional은 -class 매개 변수를 통해 명령줄에서 $class 값을 받은 다음 GetADSchema 함수에 "Optional"이라는 action과 함께 $class 값을 전달합니다.

Switch 문에서 문자열 "Optional"이 일치하면 선택적 속성을 표시하는 데 몇 초 정도 걸린다는 사실을 설명하는 메시지가 화면에 출력됩니다. 그러면 ActiveDirectorySchema 클래스의 FindClass 메서드가 호출됩니다. FindClass 메서드는 ActiveDirectorySchemaClass 클래스의 인스턴스를 반환합니다. ActiveDirectorySchemaClass 클래스의 OptionalProperties 속성을 쿼리하는 경우에는 AD DS에서 선택된 클래스에 대해 정의된 선택적 속성을 반환합니다.

결과는 Format-Table cmdlet에 전달됩니다. Format-Table cmdlet는 필수 속성과 같은 방식으로 정보를 표시합니다. 코드에서 여기에 해당하는 섹션은 다음과 같습니다.

"Optional" 
      {
      "Optional Properties of $class object"
      "This might take a few seconds ..."
      ($schema.FindClass("$class")).OptionalProperties | 
      Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
      }

다음은 GetOptional 함수 전체를 보여 주는 코드입니다.

Function GetOptional($class)
{
 GetAdSchema -action "Optional"  -class $class 
} #end GetOptional

마지막 도우미 함수인 FindClasses는 GetADSchema 함수를 호출하고 값을 두 개 전달합니다. 전달되는 첫 번째 값은 Find라는 action이고 두 번째 값은 찾을 클래스입니다. 이 함수는 사용자가 AD DS 스키마에서 자세히 확인할 필요가 있는 클래스를 파악하는 데 도움을 주는 용도로 사용됩니다.

전자 메일 작업을 수행하려는 경우를 예로 들어보겠습니다. 이 경우 전자 메일과 관련 있는 클래스가 어느 것인지, 그리고 해당 클래스의 속성은 어떤 것이 있는지를 확인해야 합니다. 그림 6에서 보듯이 먼저 –action f 및 –class mail 매개 변수를 사용하여 스크립트를 실행합니다. 그러면 이름에 "mail"이라는 문자열이 있는 클래스가 모두 반환됩니다. 원하는 클래스를 찾은 후에는 action m(필수 속성을 나타냄)을 선택하고 –c(클래스를 나타냄) 매개 변수와 클래스의 정확한 이름을 지정하여 클래스의 속성을 검색합니다.

fig06.gif

그림 6 AD DS 스키마에서 클래스 검색

FindClasses 함수가 GetADSchema를 호출하면 FindAllClasses 메서드가 호출되고 그 결과로 생성된 ActiveDirectorySchemaClass 클래스의 컬렉션이 파이프라인을 통해 전달됩니다. Where-Object는 정규식 패턴 일치 방식을 사용하여 $class 변수에 저장된 값과 일치하는 클래스를 찾습니다. 코드는 다음과 같습니다.

"Find" 
    {
    $schema.FindAllClasses() | 
    Where-Object { $_.name -match "$class" } |
    Select-Object -property name

FindClasses 함수는 다음과 같습니다.

Function FindClasses($class)
{
 GetAdSchema -action "Find" -class $class
} #end FindClasses

도우미 함수를 모두 정의하고 나면 스크립트의 진입점에 도달합니다. 이 진입점은 명령줄을 검사하여 호출할 함수를 확인하는 역할만 합니다. 이때 가장 먼저 –help 매개 변수가 있는지를 확인하게 됩니다. –h 또는 –help를 사용하여 스크립트를 실행하면 스크립트는 다음과 같이 GetHelp 함수를 호출하여 도움말을 표시한 후 종료됩니다.

if($help) { GetHelp ; Exit }

–help 매개 변수를 가장 먼저 찾기 때문에 명령줄에 이 매개 변수가 있는지 여부가 무엇보다 우선합니다. –help 매개 변수를 사용하지 않은 경우 스크립트는 기본 매개 변수인 –action 매개 변수에 대해 제공된 값을 평가해야 합니다. 다른 매개 변수를 사용하지 않으면 명령줄에서 입력한 내용은 모두 –action의 값으로 해석됩니다. 따라서 스크립트에 대해 잘못된 입력을 찾아낼 수 있다는 이점이 있습니다.

Switch 문은 –action에 대해 제공된 값을 평가하는 데 사용되는 기본 구문입니다. 정의된 네 가지 action은 각각 해당 함수를 호출합니다. 정의된 다섯 번째 조건은 기본 action으로, 해당 action이 허용되지 않는다는 메시지를 표시한 다음 GetHelp 함수를 호출합니다.

Switch 문을 사용하면 일치하는 항목이 여러 개 검색될 수 있습니다. 때문에 각 함수가 호출된 후에는 Exit 문이 사용됩니다. Switch 문 코드는 다음과 같습니다.

Switch ($action)
{
 "L" {GetAllClasses ; Exit}
 "M" {GetMandatory($class) ; Exit}
 "O" {GetOptional($class) ; Exit}
 "F" {FindClasses($class) ; Exit}
 DEFAULT { "$action is not a valid action." ; GetHelp ; Exit} 
}

이것으로 스크립트에 대한 설명은 끝이 났습니다. 아직 ADSI Scriptomatic 이외에 Active Directory 브라우저는 존재하지 않지만 당장은 BrowseActiveDirectorySchema.ps1 스크립트로 충분하리라 생각합니다. Active Directory 스크립트 작성에 대해 좀 더 자세히 알아보려면 Active Directory 스크립팅 허브를 참조하시기 바랍니다. 그리고 스크립트 센터의 문도 항상 열려 있다는 사실을 잊지 마십시오.

Ed Wilson은 Microsoft의 수석 컨설턴트이자 유명한 스크립팅 전문가입니다. Microsoft Certified Trainer이기도 한 그는 전 세계 Microsoft 프리미어 고객들을 대상으로 인기 높은 Windows PowerShell 워크샵을 제공합니다. 그는 Windows 스크립팅에 관한 책을 비롯하여 8권의 책을 썼으며 약 12권의 다른 책에도 기고한 바 있습니다. Ed는 20개가 넘는 산업 분야 자격증을 보유하고 있습니다.

언어의 달인인 Craig Liebendorfer는 오랫동안 Microsoft 웹 편집자로 일해 왔습니다. 매일 글을 쓰면서 돈을 버는 직업이 있다는 사실을 그는 아직도 믿을 수 없어 합니다. 그가 좋아하는 것 중 하나가 인습을 타파하는 유머인 만큼 그는 이 자리에 안성맞춤입니다. Craig는 자신의 딸이 그의 인생에서 거둔 최대 업적이라 생각한다고 합니다.