Windows 2008 R2之三十六ADCS实现跨森林注册(二)

简介:

Windows 2008 R2之三十五ADCS实现跨森林注册(一)

5、复制”用户“证书模板为”跨森林用户证书“,相关设设置如下图

打开证书颁发机构,右击”证书模板“选择”管理“

快照8

右击”用户“证书,选择”复制“

快照9

快照10

快照11

在”安全“选项卡中添加森Hbyc.net中的Domain Users有如下图权限。

快照12

分布复制的证书。

快照13

6、设置CA的扩展属性如下图:

快照14

7、在DCSRVB上,将计算机DCSRV加入到组Cert Publishers.

8、在DCSRV上运行

certutil –config dcsrv\hbsycsrsj-dcsvr-ca –ca.cert c:\ca.cer

其中hbsycsrsj-dcsvr-ca为证书颁发机构的名称,ca.cer为导出的根CA证书。

将CA.CER复制到DCSRVB上。

9、在DCSRVB运行如下命令

certutil –dspublish –f c:\ca.cer rootca

certutil –dspublish –f c:\ca.cer ntauthca

10、复制以下脚本为Pkisync.ps1脚本文件


# This script allows updating PKI objects in Active Directory for the 
# cross-forest certificate enrollment 

#This sample script is not supported under any Microsoft standard support 
#program or service. This sample script is provided AS IS without warranty of 
#any kind. Microsoft further disclaims all implied warranties including, 
#without limitation, any implied warranties of merchantability or of fitness 
#for a particular purpose. The entire risk arising out of the use or 
#performance of the sample scripts and documentation remains with you. In no 
#event shall Microsoft, its authors, or anyone else involved in the creation, 
#production, or delivery of the scripts be liable for any damages whatsoever 
# (including, without limitation, damages for loss of business profits, business 
#interruption, loss of business information, or other pecuniary loss) arising 
#out of the use of or inability to use this sample script or documentation, 
#even if Microsoft has been advised of the possibility of such damages. 
#

# Command line variables 

$SourceForestName = "" 
$TargetForestName = "" 
$SourceDC = "" 
$TargetDC = ""

$ObjectType = "all" 
$ObjectCN = $null

$DryRun = $FALSE 
$DeleteOnly = $FALSE 
$OverWrite = $FALSE

function ParseCommandLine() 

    if (2 -gt $Script:args.Count) 
    { 
        write-warning "Not enough arguments" 
        Usage 
        exit 87 
    } 
    
    for($i = 0; $i -lt $Script:args.Count; $i++) 
    { 
        switch($Script:args[$i].ToLower()) 
        { 
            -sourceforest 
            { 
                $i++ 
                $Script:SourceForestName = $Script:args[$i] 
            } 
            -targetforest 
            { 
                $i++ 
                $Script:TargetForestName = $Script:args[$i] 
            }                 
            -cn 
            { 
                $i++ 
                $Script:ObjectCN = $Script:args[$i] 
            } 
            -type 
            { 
                $i++ 
                $Script:ObjectType = $Script:args[$i].ToLower() 
            } 
            -f 
            { 
                $Script:OverWrite = $TRUE 
            } 
            -whatif 
            { 
                $Script:DryRun = $TRUE 
            } 
            -deleteOnly 
            { 
                $Script:DeleteOnly = $TRUE 
            } 
            -targetdc 
            { 
                $i++ 
                $Script:TargetDC = $Script:args[$i] 
            } 
            -sourcedc 
            { 
                $i++ 
                $Script:SourceDC = $Script:args[$i] 
            } 
            default 
            { 
                write-warning ("Unknown parameter: " + $Script:args[$i]) 
                Usage 
                exit 87 
            } 
        } 
    } 
}

function Usage() 

    write-host "" 
    write-host "Script to copy or delete PKI objects (default is copy)" 
    write-host "" 
    write-host "  Copy Command:" 
    write-host "" 
    write-host "  .\PKISync.ps1 -sourceforest <SourceForestDNS> -targetforest <TargetForestDNS> [-sourceDC <SourceDCDNS>] [-targetDC <TargetDCDNS>] [-type <CA|Template|OID> [-cn <ObjectCN>]] [-f] [-whatif]" 
    write-host "" 
    write-host "  Delete Command:" 
    write-host "" 
    write-host "  .\PKISync.ps1 -targetforest <TargetForestDNS> [-targetDC <TargetDCDNS>] [-type <CA|Template|OID> [-cn <ObjectCN>]] [-deleteOnly] [-whatif]" 
    write-host "" 
    write-host "-sourceforest           -- DNS of the forest to process object from" 
    write-host "-targetforest           -- DNS of the forest to process object to" 
    write-host "-sourcedc               -- DNS of the DC in the source forest to process object from" 
    write-host "-targetdc               -- DNS of the DC in the target forest to process object to" 
    write-host "-type                   -- Type of object to process, if omitted then all object types are processed" 
    write-host "                           CA         -- Process CA object(s)" 
    write-host "                           Template   -- Process Template object(s)" 
    write-host "                           OID        -- Process OID object(s)" 
    write-host '-cn                     -- Common name of the object to process, do not include the cn= (ie "User" and not "CN=User"' 
    write-host "                           This option is only valid if -type <> is also specified" 
    write-host "-f                      -- Force overwrite of existing objects when copying. Ignored when deleting." 
    write-host "-whatif                 -- Display what object(s) will be processed without processing" 
    write-host "-deleteOnly             -- Will delete object in the target forest if it exists"            
    write-host "" 
    write-host ""    
}


# Build a list of attributes to copy for some object type 

function GetSchemaSystemMayContain($ForestContext, $ObjectType) 

    # 
    # first get all attributes that are part of systemMayContain list 
    # 
    $SchemaDE = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass]::FindByName($ForestContext, $ObjectType).GetDirectoryEntry() 
    $SystemMayContain = $SchemaDE.systemMayContain

    # 
    # if schema was upgraded with adprep.exe, we need to check mayContain list as well 
    # 
    if($null -ne $SchemaDE.mayContain) 
    { 
        $MayContain = $SchemaDE.mayContain 
        foreach($attr in $MayContain) 
        { 
            $SystemMayContain.Add($attr) 
        } 
    } 
        
    # 
    # special case some of the inherited attributes 
    # 
    if (-1 -eq $SystemMayContain.IndexOf("displayName")) 
    { 
        $SystemMayContain.Add("displayName") 
    } 
    if (-1 -eq $SystemMayContain.IndexOf("flags")) 
    { 
        $SystemMayContain.Add("flags") 
    } 
    if ($objectType.ToLower().Contains("template") -and -1 -eq $SystemMayContain.IndexOf("revision")) 
    { 
        $SystemMayContain.Add("revision") 
    } 
    
    return $SystemMayContain 
}


# Copy or delete all objects of some type 

function ProcessAllObjects($SourcePKIServicesDE, $TargetPKIServicesDE, $RelativeDN) 

    $SourceObjectsDE = $SourcePKIServicesDE.psbase.get_Children().find($RelativeDN) 
    $ObjectCN = $null 
    
    foreach($ChildNode in $SourceObjectsDE.psbase.get_Children()) 
    { 
        # if some object failed, we will try to continue with the rest 
        trap 
        { 
            # CN maybe null here, but its ok. Doing best effort. 
            write-warning ("Error while coping an object. CN=" + $ObjectCN) 
            write-warning $_ 
            write-warning $_.InvocationInfo.PositionMessage 
            continue 
        }

        $ObjectCN = $ChildNode.psbase.Properties["cn"] 
        ProcessObject $SourcePKIServicesDE $TargetPKIServicesDE $RelativeDN $ObjectCN 
        $ObjectCN = $null 
    } 
    
}


# Copy or delete an object 

function ProcessObject($SourcePKIServicesDE, $TargetPKIServicesDE, $RelativeDN, $ObjectCN) 

    $SourceObjectContainerDE = $SourcePKIServicesDE.psbase.get_Children().find($RelativeDN) 
    $TargetObjectContainerDE = $TargetPKIServicesDE.psbase.get_Children().find($RelativeDN)

    # 
    # when copying make sure there is an object to copy 
    # 
    if($FALSE -eq $Script:DeleteOnly) 
    { 
        $DSSearcher =  [System.DirectoryServices.DirectorySearcher]$SourceObjectContainerDE 
        $DSSearcher.Filter = "(cn=" +$ObjectCN+")" 
        $SearchResult = $DSSearcher.FindAll() 
        if (0 -eq $SearchResult.Count) 
        { 
            write-host ("Source object does not exist: CN=" + $ObjectCN + "," + $RelativeDN) 
            return 
        } 
        $SourceObjectDE = $SourceObjectContainerDE.psbase.get_Children().find("CN=" + $ObjectCN) 
    } 
    
    # 
    # Check to see if the target object exists, if it does delete if overwrite is enabled. 
    # Also delete is this a deletion only operation. 
    # 
    $DSSearcher =  [System.DirectoryServices.DirectorySearcher]$TargetObjectContainerDE 
    $DSSearcher.Filter = "(cn=" +$ObjectCN+")" 
    $SearchResult = $DSSearcher.FindAll() 
    if ($SearchResult.Count -gt 0) 
    { 
        $TargetObjectDE = $TargetObjectContainerDE.psbase.get_Children().find("CN=" + $ObjectCN)

        if($Script:DeleteOnly) 
        { 
            write-host ("Deleting: " + $TargetObjectDE.DistinguishedName) 
            if($FALSE -eq $DryRun) 
            { 
                $TargetObjectContainerDE.psbase.get_Children().Remove($TargetObjectDE) 
            } 
            return 
        } 
        elseif ($Script:OverWrite) 
        { 
            write-host ("OverWriting: " + $TargetObjectDE.DistinguishedName) 
            if($FALSE -eq $DryRun) 
            { 
                $TargetObjectContainerDE.psbase.get_Children().Remove($TargetObjectDE) 
            } 
        } 
        else 
        { 
            write-warning ("Object exists, use -f to overwrite. Object: " + $TargetObjectDE.DistinguishedName) 
            return 
        } 
    } 
    else 
    { 
        if($Script:DeleteOnly) 
        { 
            write-warning ("Can't delete object. Object doesn't exist. Object: " + $ObjectCN + ", " + $TargetObjectContainerDE.DistinguishedName) 
            return 
        } 
        else 
        {        
            write-host ("Copying Object: " + $SourceObjectDE.DistinguishedName) 
        } 
    } 
    
    # 
    # Only update the object if this is not a dry run 
    # 
    if($FALSE -eq $DryRun -and $FALSE -eq $Script:DeleteOnly) 
    { 
        #Create new AD object   
        $NewDE = $TargetObjectContainerDE.psbase.get_Children().Add("CN=" + $ObjectCN, $SourceObjectDE.psbase.SchemaClassName)

        #Obtain systemMayContain for the object type from the AD schema 
        $ObjectMayContain = GetSchemaSystemMayContain $SourceForestContext $SourceObjectDE.psbase.SchemaClassName 
        #Copy attributes defined in the systemMayContain for the object type 
        foreach($Attribute in $ObjectMayContain) 
        { 
            $AttributeValue = $SourceObjectDE.psbase.Properties[$Attribute].Value 
            if ($null -ne $AttributeValue) 
            { 
                $NewDE.psbase.Properties[$Attribute].Value = $AttributeValue 
                $NewDE.psbase.CommitChanges() 
            } 
        } 
        #Copy secuirty descriptor to new object. Only DACL is copied. 
        $BinarySecurityDescriptor = $SourceObjectDE.psbase.ObjectSecurity.GetSecurityDescriptorBinaryForm() 
        $NewDE.psbase.ObjectSecurity.SetSecurityDescriptorBinaryForm($BinarySecurityDescriptor, [System.Security.AccessControl.AccessControlSections]::Access) 
        $NewDE.psbase.CommitChanges() 
    } 
}


# Get parent container for all PKI objects in the AD 

function GetPKIServicesContainer([System.DirectoryServices.ActiveDirectory.DirectoryContext] $ForestContext, $dcName) 

    $ForObj = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext) 
    $DE = $ForObj.RootDomain.GetDirectoryEntry() 
    
    if("" -ne $dcName) 
    { 
        $newPath = [System.Text.RegularExpressions.Regex]::Replace($DE.psbase.Path, "LDAP://\S*/", "LDAP://" + $dcName + "/") 
        $DE = New-Object System.DirectoryServices.DirectoryEntry $newPath 
    }

    $PKIServicesContainer = $DE.psbase.get_Children().find("CN=Public Key Services,CN=Services,CN=Configuration") 
    return $PKIServicesContainer 
}

######################################################### 
# Main script code 
#########################################################


# All errors are fatal by default unless there is another 'trap' with 'continue' 

trap 

    write-error "The script has encoutnered a fatal error. Terminating script." 
    break 
}

ParseCommandLine


# Get a hold of the containers in each forest 

write-host ("Target Forest: " + $TargetForestName.ToUpper()) 
$TargetForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext Forest, $TargetForestName 
$TargetPKIServicesDE = GetPKIServicesContainer $TargetForestContext $Script:TargetDC

# Only need source forest when copying 
if($FALSE -eq $Script:DeleteOnly) 

    write-host ("Source Forest: " + $SourceForestName.ToUpper()) 
    $SourceForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext Forest, $SourceForestName 
    $SourcePKIServicesDE = GetPKIServicesContainer $SourceForestContext $Script:SourceDC 

else 

    $SourcePKIServicesDE = $TargetPKIServicesDE 
}

if("" -ne $ObjectType) {write-host ("Object Category to process: " + $ObjectType.ToUpper())}


# Process the command 

switch($ObjectType.ToLower()) 

    all 
    { 
        write-host ("Enrollment Serverices Container") 
    ProcessAllObjects $SourcePKIServicesDE $TargetPKIServicesDE "CN=Enrollment Services" 
        write-host ("Certificate Templates Container") 
        ProcessAllObjects $SourcePKIServicesDE $TargetPKIServicesDE "CN=Certificate Templates" 
        write-host ("OID Container") 
        ProcessAllObjects $SourcePKIServicesDE $TargetPKIServicesDE "CN=OID" 
    } 
    ca 
    { 
        if($null -eq $ObjectCN) 
        { 
            ProcessAllObjects $SourcePKIServicesDE $TargetPKIServicesDE "CN=Enrollment Services" 
        } 
        else 
        { 
            ProcessObject $SourcePKIServicesDE $TargetPKIServicesDE "CN=Enrollment Services" $ObjectCN 
        } 
    } 
    oid 
    { 
        if($null -eq $ObjectCN) 
        { 
            ProcessAllObjects $SourcePKIServicesDE $TargetPKIServicesDE "CN=OID" 
        } 
        else 
        { 
            ProcessObject $SourcePKIServicesDE $TargetPKIServicesDE "CN=OID" $ObjectCN 
        } 
    } 
    template 
    { 
        if($null -eq $ObjectCN) 
        { 
            ProcessAllObjects $SourcePKIServicesDE $TargetPKIServicesDE "CN=Certificate Templates" 
        } 
        else 
        { 
            ProcessObject $SourcePKIServicesDE $TargetPKIServicesDE "CN=Certificate Templates" $ObjectCN 
        }    
    } 
    default 
    { 
        write-warning ("Unknown object type: " + $ObjectType.ToLower()) 
        Usage 
        exit 87 
    } 
}

 

11、在DCSRVB打开PowerSell运行以下命令

set-ececutionpolicy unrestricted

pkisync.ps1 –sourceforest hbsycsrsj.com –targetforest hbyc.net –f

12、打开组策略编辑器,编辑默认的策略。如下图

快照2

13、重启计算机dcsrv和dcsrvB.。在DCsrvB运行Certmgr.msc,申请证书成功。














本文转自ycrsjxy51CTO博客,原文链接:http://blog.51cto.com/ycrsjxy/1039818,如需转载请自行联系原作者


相关文章
|
4月前
|
存储 安全 Apache
2023-10 适用于基于 x64 的系统的 Windows Server 2012 R2 月度安全质量汇总(KB5031419)
2023-10 适用于基于 x64 的系统的 Windows Server 2012 R2 月度安全质量汇总(KB5031419)
276 2
|
4月前
|
XML Arthas Java
Windows【工具 04】WinSW官网使用说明及实例分享(将exe和jar注册成服务)实现服务器重启后的服务自动重启
Windows【工具 04】WinSW官网使用说明及实例分享(将exe和jar注册成服务)实现服务器重启后的服务自动重启
105 0
|
9月前
|
缓存 JavaScript 前端开发
Windows7压缩包安装node.js 报错提示windows Server 2012 R2 和安装React脚手架 最详细教程
对于Windows 7安装node.js 提示“This application is only supported on wWindows 8.1,windows Server 2012 R2, or higher.”类似这种情况的,该问题是因为node.js官方在 x12版本后就不支持win7系统了。
|
4月前
|
监控 安全 API
7.2 Windows驱动开发:内核注册并监控对象回调
在笔者上一篇文章`《内核枚举进程与线程ObCall回调》`简单介绍了如何枚举系统中已经存在的`进程与线程`回调,本章`LyShark`将通过对象回调实现对进程线程的`句柄`监控,在内核中提供了`ObRegisterCallbacks`回调,使用这个内核`回调`函数,可注册一个`对象`回调,不过目前该函数`只能`监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。
29 0
7.2 Windows驱动开发:内核注册并监控对象回调
|
15天前
|
Ubuntu 安全 Linux
【Linux】安装VMWare虚拟机(安装配置)和配置Windows Server 2012 R2(安装配置连接vm虚拟机)以及环境配置(Windows版详细教程)
【Linux】安装VMWare虚拟机(安装配置)和配置Windows Server 2012 R2(安装配置连接vm虚拟机)以及环境配置(Windows版详细教程)
219 0
|
6月前
|
关系型数据库 MySQL Linux
【Linux】安装VMWare虚拟机(安装配置)和配置Windows Server 2012 R2(安装配置连接vm虚拟机)以及环境配置
【Linux】安装VMWare虚拟机(安装配置)和配置Windows Server 2012 R2(安装配置连接vm虚拟机)以及环境配置
111 0
|
9月前
|
Windows
Windows Server 2012 R2多用户远程连接配置步骤
Windows Server 2012 R2多用户远程连接配置步骤
655 0
|
10月前
|
Windows
Windows编程基础,第一个Windows程序,注册窗口,创建窗口(下)
Windows编程基础,第一个Windows程序,注册窗口,创建窗口
|
10月前
|
编译器 API 开发工具
Windows编程基础,第一个Windows程序,注册窗口,创建窗口(上)
Windows编程基础,第一个Windows程序,注册窗口,创建窗口
|
11月前
|
网络架构 Windows
使用Windows Server 2012 R2创建DHCP作用域(DHCP地址池),并测试使用
使用Windows Server 2012 R2创建DHCP作用域(DHCP地址池),并测试使用
233 0