C# Active Directory - 如何从注册服务目录对象加载 "certificateTemplates" 属性?

C# Active Directory - How can I load the "certificateTemplates" Property from an Enrollment Services directory object?

我正在尝试通过循环访问注册服务 AD 容器从我的 AD 林加载有关 Microsoft PKI 颁发 CA 的详细信息。我想包括的细节之一是在每个 CA 上启用的证书模板列表。在 ADSIEdit 中,我可以清楚地看到每个注册服务对象中都有一个名为 certificateTemplates 的 属性,其中包含我需要的信息(请原谅所有编辑):

但是,当我将这些对象中的任何一个拉入 .NET DirectoryEntry 对象时,"certificateTemplates" 不是默认包含的属性之一。我发现了 RefreshCache method,它应该允许您从目录条目中提取其他属性(只要它们存在于条目中),但这对我不起作用:

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
    }
}

有人encountered/resolved遇到过这个问题吗?

RefreshCache() 方法实际上正确地将 certificateTemplates 属性 添加到每个 CA DirectoryEntry 对象。在我的循环中遇到的第一个 CA 根本没有分配模板,这解释了在我的 foreach 循环的第一次迭代中 Templates 的空值。

更新: 如果 certificateTemplates 属性 仅包含一个条目,则 属性 值将是单个字符串而不是仅包含 1 个元素的数组(谢谢,微软!)。我使用 try/catch 来处理这种边缘情况。如果有人有更优雅的方法,请成为我的客人。

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());
        }
    }
}