简体   繁体   English

C# Active Directory - 如何从注册服务目录 object 加载“certificateTemplates”属性?

[英]C# Active Directory - How can I load the “certificateTemplates” Property from an Enrollment Services directory object?

I am trying to load details about the Microsoft PKI Issuing CAs from my AD Forest by iterating through the Enrollment Services AD container.我正在尝试通过迭代 Enrollment Services AD 容器从我的 AD 森林中加载有关 Microsoft PKI 颁发 CA 的详细信息。 One of the details that I'd like to include is the list of certificate templates enabled on each CA.我想包括的细节之一是每个 CA 上启用的证书模板列表。 In ADSIEdit, I can clearly see that there is a property named certificateTemplates in each Enrollment Services object which contains the information I need (please forgive all the redaction):在 ADSIEdit 中,我可以清楚地看到每个 Enrollment Services object 中有一个名为certificateTemplates的属性,其中包含我需要的信息(请原谅所有的编辑):

在此处输入图像描述

However, when I pull any of these objects into a .NET DirectoryEntry object, "certificateTemplates" is not one of the properties that is included by default.但是,当我将这些对象中的任何一个拉入 .NET DirectoryEntry object 时,“certificateTemplates”不是默认包含的属性之一。 I discovered the RefreshCache method , which should allow you to pull in additional properties from a directory entry (so long as they exist on the entry), but this did not work for me:我发现了RefreshCache 方法,它应该允许您从目录条目中提取其他属性(只要它们存在于条目中),但这对我不起作用:

DirectoryEntry EnrollmentServices = new DirectoryEntry($"LDAP://{MyDC}/CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=example,DC=com");
DirectoryEntries CAs = EnrollmentServices.Children;
foreach(DirectoryEntry CA in CAs)
{
    object[] objectClass = (object[])CA.Properties[objectClassProperty].Value;
    if (objectClass[1].ToString() == @"pKIEnrollmentService")
    {
        CA.RefreshCache(new string[] { "certificateTemplates" });
        var Templates = CA.Properties["certificateTemplates"].Value;
        //Templates remains null
    }
}

Has anyone encountered/resolved this issue before?有没有人遇到过/解决过这个问题?

The RefreshCache() method does, in fact, correctly add the certificateTemplates property to each CA DirectoryEntry object.实际上, RefreshCache()方法确实将certificateTemplates属性正确添加到每个 CA DirectoryEntry object。 The first CA encountered in my loop simply has no templates assigned, which explains the null value for Templates in the first iteration of my foreach loop.在我的循环中遇到的第一个 CA 根本没有分配模板,这解释了我的 foreach 循环的第一次迭代中模板的 null 值。

Update: If the certificateTemplates property contains only one entry, the property value will be a single string rather than an array containing only 1 element (thanks, Microsoft.).更新:如果 certificateTemplates 属性仅包含一个条目,则属性值将是单个字符串,而不是仅包含 1 个元素的数组(感谢 Microsoft。)。 I use a try/catch to handle this edge case, If anyone has a more elegant approach.我使用 try/catch 来处理这种边缘情况,如果有人有更优雅的方法。 be my guest.别客气。

DirectoryEntry EnrollmentServices = new DirectoryEntry($"LDAP://{MyDC}/CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=example,DC=com");
DirectoryEntries CAs = EnrollmentServices.Children;

List<string> templateNames;

foreach(DirectoryEntry CA in CAs)
{
    object[] objectClass = (object[])CA.Properties[objectClassProperty].Value;
    if (objectClass[1].ToString() == @"pKIEnrollmentService")
    {
        CA.RefreshCache(new string[] { "certificateTemplates" });
        object[] Templates;

        try
        {
            Templates = (object[])CAEntry.Properties[PropertyIndex.CertificateTemplates].Value;
        }
        catch (InvalidCastException)
        {
            Templates = new object[] { CAEntry.Properties[PropertyIndex.CertificateTemplates].Value };
        }

        //I place the template names into a string list for ease of retrieval later.
        templateNames = new List<string>();
        if (Templates != null)
        {
            for (int x = 0; x < Templates.Length; x++) templateNames.Add(Templates[x].ToString());
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM