스키마 마스터 검색
Active Directory Domain Services 다중 master 업데이트 시스템이 있습니다. 모든 도메인 컨트롤러는 디렉터리의 쓰기 가능한 복사본을 보유합니다. 스키마 업데이트는 동일한 트리 또는 포리스트에 속하는 모든 도메인에 전파됩니다. 스키마에 충돌하는 업데이트를 조정하기 어렵기 때문에 스키마 업데이트는 단일 서버에서만 수행할 수 있습니다. 업데이트를 수행할 수 있는 권한이 있는 서버는 변경될 수 있지만 지정된 시간에는 하나의 서버만 해당 권한을 갖습니다. 이 서버를 스키마 master 호출합니다. 엔터프라이즈에 설치된 첫 번째 DC는 기본적으로 스키마 master.
스키마 변경은 스키마 master 수준에서만 수행할 수 있습니다. 스키마 master DC를 검색하려면 다음 단계를 수행합니다.
DC 스키마 마스터 검색
- 모든 DC에서 스키마 컨테이너의 fsmoRoleOwner 특성을 읽습니다. fsmoRoleOwner 특성은 스키마 master 대한 nTDSDSA 개체의 고유 이름(DN)을 반환합니다.
- 방금 검색한 DN의 nTDSDSA 개체에 바인딩합니다. 이 개체의 부모는 스키마 master 포함하는 DC의 서버 개체입니다.
- nTDSDSA 개체의 부모에 대한 ADsPath를 가져옵니다. 부모는 서버 개체입니다.
- 서버 개체에 바인딩합니다.
- 서버 개체의 dNSHostName 특성을 가져옵니다. 스키마 master 포함하는 DC의 DNS 이름입니다.
- 스키마 master DNS 이름을 서버로 지정하고 DN을 스키마 컨테이너의 DN으로 지정하여 스키마 master 바인딩합니다. 예를 들어 서버가 "dc1.fabrikam.com"이고 스키마 컨테이너 DN이 "cn=schema,cn=configuration,dc=fabrikam,dc=com"인 경우 ADsPath는 다음과 같습니다.
LDAP://dc1.fabrikam.com/cn=schema,cn=configuration,dc=fabrikam,dc=com
스키마 master 찾아서 스키마를 변경하려면 스키마에 바인딩하는 것이 좋습니다. 그러나 스키마 master 다른 서버로 이동할 수 있습니다.
다른 서버를 스키마 master 만들기 위해 적절한 권한 있는 사용자는 다음을 수행할 수 있습니다.
스키마 관리자 MMC 스냅인을 사용합니다.
참고
Active Directory 스키마 MMC 스냅인을 수동으로 등록해야 합니다. 스키마 스냅인을 등록하려면 Windows System32 디렉터리의 명령 프롬프트에서 다음 명령을 실행해야 합니다.
regsvr32.exe schmmgmt.dll
NTDSUTIL 명령줄 유틸리티를 사용합니다.
타사 애플리케이션(적절한 LDAP 쓰기를 발급하는 애플리케이션)을 사용합니다.
프로그래밍 방식으로 master 스키마가 되기 위해 적절한 권한 있는 사용자의 컨텍스트에서 실행되는 애플리케이션은 운영 특성인 becomeSchemaMaster의 LDAP 쓰기를 해당 DC의 rootDSE에 발급할 수 있습니다. 이렇게 하면 현재 소유자에서 로컬 DC로 스키마 master 원자성 전송이 시작됩니다.
다음 코드 예제에서는 스키마 master 찾습니다. 다음 함수는 스키마 master 컴퓨터의 스키마 컨테이너에 바인딩됩니다.
HRESULT BindToSchemaMaster(IADsContainer **ppSchemaMaster)
{
HRESULT hr = E_FAIL;
// Get rootDSE and the schema container DN.
IADs *pObject = NULL;
IADs *pTempSchema = NULL;
IADs *pNTDS = NULL;
IADs *pServer = NULL;
BSTR bstrParent;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
VARIANT var, varRole,varComputer;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (hr == S_OK)
{
hr = pObject->Get(CComBSTR("schemaNamingContext"), &var);
if (hr == S_OK)
{
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,var.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pTempSchema);
if (hr == S_OK)
{
/*
Read the fsmoRoleOwner attribute to identify which server is
the schema master.
*/
hr = pTempSchema->Get(CComBSTR("fsmoRoleOwner"), &varRole);
if (hr == S_OK)
{
// The fsmoRoleOwner attribute returns the nTDSDSA object.
// The parent is the server object.
// Bind to NTDSDSA object and get parent.
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,varRole.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&pNTDS);
if (hr == S_OK)
{
hr = pNTDS->get_Parent(&bstrParent);
if (hr == S_OK)
{
/*
Bind to server object and get the DNS name of
the server.
*/
wcscpy_s(szPath,bstrParent);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&pServer);
if (hr == S_OK)
{
// Get the dns name of the server.
hr = pServer->Get(CComBSTR("dNSHostName"),
&varComputer);
if (hr == S_OK)
{
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,varComputer.bstrVal);
wcscat_s(szPath,L"/");
wcscat_s(szPath,var.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)ppSchemaMaster);
if (FAILED(hr))
{
if (*ppSchemaMaster)
{
(*ppSchemaMaster)->Release();
(*ppSchemaMaster) = NULL;
}
}
}
VariantClear(&varComputer);
}
if (pServer)
pServer->Release();
}
SysFreeString(bstrParent);
}
if (pNTDS)
pNTDS->Release();
}
VariantClear(&varRole);
}
if (pTempSchema)
pTempSchema->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
return hr;
}
다음 코드 예제에서는 스키마 master 컴퓨터의 DNS 이름을 표시합니다.
On Error Resume Next
'''''''''''''''''''
' Bind to the rootDSE
''''''''''''''''''''
sPrefix = "LDAP://"
Set root= GetObject(sPrefix & "rootDSE")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method"
End If
'''''''''''''''''''
' Get the DN for the schema
''''''''''''''''''''
sSchema = root.Get("schemaNamingContext")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on Get method"
End If
'''''''''''''''''''
' Bind to the schema container
''''''''''''''''''''
Set Schema= GetObject(sPrefix & sSchema )
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method to bind to schema"
End If
''''''''''''''''''''
' Read the fsmoRoleOwner attribute to see which server is the
' schema master.
''''''''''''''''''''
sMaster = Schema.Get("fsmoRoleOwner")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADs::Get method for fsmoRoleOwner"
End If
''''''''''''''''''''
' The fsmoRoleOwner attribute returns the nTDSDSA object.
' The parent is the server object.
' Bind to NTDSDSA object and get the parent object.
''''''''''''''''''''
Set NTDS = GetObject(sPrefix & sMaster)
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method for NTDS"
End If
sServer = NTDS.Parent
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADs::get_Parent method"
End If
''''''''''''''''''''
' Bind to server object
' and get the reference to the computer object.
''''''''''''''''''''
Set Server = GetObject(sServer)
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method for " & sServer
End If
sComputer = Server.Get("dNSHostName")
''''''''''''''''''''
' Display the DNS name for the computer.
''''''''''''''''''''
strText = "Schema master has the following DNS name: "& sComputer
WScript.echo strText
''''''''''''''''''''
' Display subroutines
''''''''''''''''''''
Sub BailOnFailure(ErrNum, ErrText)
strText = "Error 0x" & Hex(ErrNum) & " " & ErrText
MsgBox strText, vbInformation, "ADSI Error"
WScript.Quit
End Sub