How to: Create a Constraint on a Relationship

How to: Create a Constraint on a Relationship

This topic describes how to create a constraint on a relationship that puts restrictions on some of its settings. This topic uses the sample from a previous topic How to: Create an SDM Resource and demonstrates how to add a constraint to a relationship defined in that sample.

Standard Setting Constraints

The relationship setting uses the built-in ListComparison constraint to impose a condition on one of its settings. There are several simple setting constraints provided that you can consider to use before writing your own custom setting constraint. They are contained in the System.Constraints.sdmdocument file.

The standard setting constraints each have the following settings:

  • ActualValue: The value that is specified by the user.
  • DesiredValue: The value that the constraint requires.
  • Operator: The operator used to perform the comparison.
Constraint Operators Description
SimpleComparison =, <, <=, >, >=, !=, Contains, Between. The default is =. Compares one setting value to another setting value. The operators will also operate on the following built-in setting definitions: Any, String, Int, UnsignedInt, Long, UnsignedLong, Float, Decimal, Double, Boolean, and TimeSpan.
EnumComparison OneOf, NoneOf. The default is OneOf Compares whether a value exists (OneOf) or doesn't exist (NoneOf) in a list of values.
ListComparison ContainsAll, ContainsOne, ContainsNone. The default is ContainsAll. Compares whether a list of values is contained entirely by the desired list of values (ContainsAll), or has at least one value in the desired list (ContainsOne), or does not have any values in the desired list (ContainsNone).
  1. Add a constraint to check that a setting related to the certificate is valid.

    Add a constraint to the certificates resource sample. This constraint will be added to the containment relation between a Web application (the containing parent) and a certificate (the contained member).

    <ContainmentDefinition 
         Name="WebApplicationContainsCertificate" 
         ParentDefinition="WebApp:WebApplication" 
         MemberDefinition="X509Certificate">

    This is the context in which the constraint is defined, and therefore applies to certificate members which are contained in Web applications.

<!-- A certificate that is used by a web application must satisfy EnhancedKeyUsage = ServerAuthentication --> <ObjectConstraint Name="CheckCertificates" PrimaryRole="Member" PrimaryObjectDefinition="X509Certificate"> <!-- Constraint details --> <Constraint Name="RequireServerAuthenticationUsage" Definition="Constraints:ListComparison"> <SettingValue Path="Operator">ContainsAll</SettingValue> <SettingValueList Path="DesiredValue" Definition="EnhancedKeyUsageType"> <Value>ServerAuthentication</Value> </SettingValueList> <Input Name="ActualValue" Path="Member.EnhancedKeyUsage"/> </Constraint> </ObjectConstraint>

Because this is a constraint on an object setting, the element \<ObjectConstraint\> is used to describe it. To see the structure of an object constraint, it is useful to look at the topic [**ObjectConstraint (ConstraintDefinition) Element**](bb168185\(v=vs.90\).md) which in turn describes an element of [**ObjectConstraint Complex Type**](bb168184\(v=vs.90\).md). The object constraint has a **Name** attribute that gives the constraint a meaningful name. In this case, it is called "CheckCertificates". The **PrimaryRole** attribute is the name of the role in the relationship that this constraint targets. Here it has a value "Member" which references the contained object in the containment relationship. The name of the object definition associated with the primary role is mentioned in the **PrimaryObjectDefinition** attribute. The name here is "X509Certificate", which is a value of the simple type **QualifiedName**.

The constraint details appear in a \<Constraint\> element. For more information on the \<Constraint\> element see [**Constraint (ObjectConstraint) Element**](bb168039\(v=vs.90\).md). It has a **name** attribute whose value is a meaningful name for the constraint at the certificate (member) level. Here, the value is "RequireServerAuthenticationUsage". The **Definition** attribute of the constraint tells us that the type of constraint is a "Constraints:ListComparison", which is a predefined constraint in the "Constraints" namespace. The list comparison constraint in this case uses a "ContainsAll" operator, which checks to see if the actual value pointed to by the \<Input\> element is among the desired values contained in the list that is described by the \<SettingValueList\> element. The value of **Path** attribute, of the \<Input\> element points to the "EnhancedKeyUsage" setting as the source of the actual value used for the comparison. The **Definition** attribute of the \<SettingValueList\> element describes the type of contents expected to be in the list. Here, the value of the **Definition** attribute of the \<SettingValueList\> element is an enumeration called "EnhancedKeyUsageType" described previously in the topic [How to: Create an SDM Resource](bb167812\(v=vs.90\).md). In this case, the list of \<Value\> elements that follows contains a singleton entry from the possible entries in the enumeration, namely, "ServerAuthentication". The constraint thus checks to see if the "EnhancedKeyUsage" setting of the "X509Certificate" member mentioned in the object constraint has the value "ServerAuthentication". In simple words, the constraint checks to make sure that a certificate contained in a Web application can only be used for server authentication.
  1. Create an error message for a failed constraint.

    The following example shows how to create a more meaningful error message when a constraint fails. Without a custom error message, you will see a generic error message. ITo return an error message specific to the failure, you need to add a <Description> element with the attribute ErrorDescription. When this constraint fails, this very specific error message will be returned to the user.

<!-- Error Description for this constraint --> <Description> <Entry Name="ErrorDescription" Manager="CertManager" Substitute="Parent.InstanceName Member.EnhancedKeyUsage" ResourceId="RequireServerAuthenticationUsage"> The web application '{0}' contains a certificate with the EnhancedKeyUsage value '{1}', but the constraint dictates that the EnhancedKeyUsage value must be 'ServerAuthentication'. Please change the value. </Entry> </Description>

To substitute parameters into the message, the **Substitute** attribute is used, with substitution parameters separated by a space. The sdm compiler uses the standard String.Format method to insert the parameters. Make sure the insertion indices are zero-based. Note that the SDM compiler will not attempt to resolve the parameters at compile time. They will only be resolved when the constraint fails, so ensure that each constraint failure message is tested.
  1. The .sdm file that results from adding the above constraint and error definition to the sample in the How to: Create an SDM Resource topic is given below in its entirety.

    [XML]

<?xml version="1.0" encoding="UTF-8"?> <SystemDefinitionModel Name="Microsoft.Samples.Certificates" Version="1.0.0.0" DocumentLanguage="en" xmlns="https://schemas.microsoft.com/SystemDefinitionModel/2005/1"> <Information> <FriendlyName>Sample certificate model</FriendlyName> <CompanyName>Microsoft Corporation</CompanyName> <Copyright> Copyright (c) Microsoft Corporation.
All rights reserved.
This is provided AS IS with no warranties, and confers no rights. </Copyright> <Description Manager="CertManager" ResourceId="DocumentDescription"> SDM model for certificate resources </Description> </Information> <Import Alias="WindowsHost" Name="Microsoft.WindowsHost" /> <Import Alias="WindowsApp" Name="Microsoft.WindowsApplication" /> <Import Alias="IIS" Name="Microsoft.InternetInformationServices" /> <Import Alias="WebHost" Name="Microsoft.WebHost" /> <Import Alias="WebApp" Name="Microsoft.WebApplication" /> <Import Alias="FileSystem" Name="Microsoft.FileSystem" /> <Import Alias="Constraints" Name="System.Constraints" /> <Import Alias="Flow" Name="System.Flow"/> <!-- Setting definitions --> <SettingDefinitions Manager="CertManager" ClrNamespace="Microsoft.Sdm.Samples.Certificates"> <xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns="https://Microsoft.Samples.Certificates" targetNamespace="https://Microsoft.Samples.Certificates"> <xs:simpleType name="HexString"> <xs:annotation> <xs:documentation> Defines a type for representing a hex encoded number. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="[0-9A-Fa-f]+" /> </xs:restriction> </xs:simpleType> <xs:simpleType name="KeyUsageType"> <xs:annotation> <xs:documentation> Defines an enumeration for key usage. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:enumeration value="DigitalSignature" /> <xs:enumeration value="NonRepudiation" /> <xs:enumeration value="KeyEncryption" /> <xs:enumeration value="DataEncryption" /> <xs:enumeration value="KeyAgreement" /> <xs:enumeration value="CertificateValidation" /> <xs:enumeration value="CRLValidation" /> </xs:restriction> </xs:simpleType> <xs:simpleType name="EnhancedKeyUsageType"> <xs:annotation> <xs:documentation> Defines an enumeration for enhanced key usage. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:enumeration value="ClientAuthentication" /> <xs:enumeration value="ServerAuthentication" /> <xs:enumeration value="EmailProtection" /> <xs:enumeration value="CodeSigning" /> <xs:enumeration value="TimeStampSigning" /> <xs:enumeration value="IPSec" /> <xs:enumeration value="Other" /> </xs:restriction> </xs:simpleType> <xs:complexType name="PropertyValuePairType"> <xs:sequence> <xs:element name="Property" type="xs:string" /> <xs:element name="Value" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:schema> </SettingDefinitions> <ResourceDefinition Name="CertificateStore" Layer="ApplicationHost" Abstract="true"> <SettingDeclaration Name="Name" Definition="String" /> </ResourceDefinition> <ResourceDefinition Name="X509Certificate" Layer="Application" Abstract="true"> <!-- X509 V3 settings --> <SettingDeclaration Name="Version" Definition="String" /> <SettingDeclaration Name="SerialNumber" Definition="HexString" /> <SettingDeclaration Name="AlgorithmId" Definition="String" /> <SettingDeclaration Name="AlgorithmParameters" Definition="String" List="true" /> <SettingDeclaration Name="IssuerName" Definition="String" /> <SettingDeclaration Name="ValidFrom" Definition="DateTime" /> <SettingDeclaration Name="ValidTo" Definition="DateTime" /> <SettingDeclaration Name="SubjectName" Definition="String" /> <SettingDeclaration Name="PublicKey" Definition="HexString" /> <SettingDeclaration Name="PublicKeyAlgorithm" Definition="String" /> <SettingDeclaration Name="PublicKeyParameters" Definition="String" List="true" /> <SettingDeclaration Name="Signature" Definition="String" /> <SettingDeclaration Name="IssuerId" Definition="String" /> <SettingDeclaration Name="SubjectId" Definition="HexString" /> <SettingDeclaration Name="Extensions" Definition="PropertyValuePairType" List="true" /> <!-- Key and Policy extensions --> <SettingDeclaration Name="AuthorityKeyId" Definition="HexString" /> <SettingDeclaration Name="SubjectKeyId" Definition="HexString" /> <SettingDeclaration Name="KeyUsage" Definition="KeyUsageType" List="true" /> <SettingDeclaration Name="PrivateKeyUsagePeriod" Definition="String" /> <SettingDeclaration Name="CertificatePolicies" Definition="String" List="true" /> <SettingDeclaration Name="PolicyMappings" Definition="String" List="true" /> <!-- Certificate Subject and Issuer Extensions --> <SettingDeclaration Name="SubjectAlternativeName" Definition="String" List="true" /> <SettingDeclaration Name="IssuerAlternativeName" Definition="String" List="true" /> <SettingDeclaration Name="SubjectDirectoryAttributes" Definition="String" List="true" /> <!-- Certification Path Constraints --> <SettingDeclaration Name="BasicConstraints" Definition="String" List="true" /> <SettingDeclaration Name="NameConstraints" Definition="String" List="true" /> <SettingDeclaration Name="PolicyConstraints" Definition="String" List="true" /> <!-- Other extensions --> <SettingDeclaration Name="EnhancedKeyUsage" Definition="EnhancedKeyUsageType" List="true" /> <SettingDeclaration Name="Thumbprint" Definition="HexString" /> <SettingDeclaration Name="ThumbprintAlgorithm" Definition="String" /> </ResourceDefinition>

&lt;!--
Certificate Store containment relationships
--&gt;
&lt;ContainmentDefinition 
 Name="WindowsHostContainsCertificateStore" 
 ParentDefinition="WindowsHost:WindowsHost" 
 MemberDefinition="CertificateStore"&gt;
    &lt;Description 
     Manager="CertManager" 
     ResourceId="WindowsHostContainsCertificateStore"&gt;
     A WindowsHost system can contain certificate store resources.
    &lt;/Description&gt;
&lt;/ContainmentDefinition&gt;    
&lt;ContainmentDefinition 
 Name="WebServerContainsCertificateStore" 
 ParentDefinition="WebHost:WebServer" 
 MemberDefinition="CertificateStore"&gt;
    &lt;Description 
     Manager="CertManager" 
     ResourceId="WebServerContainsCertificateStore"&gt;
     A WebServer can contain a certificate store.
    &lt;/Description&gt;
&lt;/ContainmentDefinition&gt;

&lt;!--
Certificate containment relationships
--&gt;
&lt;ContainmentDefinition 
 Name="WindowsApplicationContainsCertificate" 
 ParentDefinition="WindowsApp:WindowsApplication" 
 MemberDefinition="X509Certificate"&gt;
    &lt;Description 
     Manager="CertManager" 
     ResourceId="WindowsApplicationContainsCertificate"&gt;
     A WindowsApplication system can contain certificate resources.
    &lt;/Description&gt;
&lt;/ContainmentDefinition&gt;

&lt;ContainmentDefinition 
 Name="WebApplicationContainsCertificate" 
 ParentDefinition="WebApp:WebApplication" 
 MemberDefinition="X509Certificate"&gt;
    &lt;Description 
     Manager="CertManager" 
     ResourceId="WebApplicationContainsCertificate"&gt;
     A WebApplication system can contain certificate resources.
    &lt;/Description&gt;
    &lt;!-- 
     Constraint: A certificate that is used by a web application 
     must have EnhancedKeyUsage = ServerAuthentication 
    --&gt;
    &lt;ObjectConstraint 
     Name="CheckCertificates" 
     PrimaryRole="Member" 
     PrimaryObjectDefinition="X509Certificate"&gt;
        &lt;Constraint 
         Name="RequireServerAuthenticationUsage" 
         Definition="Constraints:ListComparison"&gt;
                &lt;!--
                Error Description for this constraint
                --&gt;               
                &lt;Description&gt;
                &lt;Entry 
                 Name="ErrorDescription" 
                 Manager="CertManager"
                 Substitute="Parent.InstanceName Member.EnhancedKeyUsage" 
                 ResourceId="RequireServerAuthenticationUsage"&gt;
                 The web application '{0}' contains a certificate 
                 with the EnhancedKeyUsage value '{1}', 
                 but the constraint dictates that the EnhancedKeyUsage value 
                 must be 'ServerAuthentication'. Please change the value. 
                &lt;/Entry&gt;
            &lt;/Description&gt;
            &lt;!-- 
            Constraint details
            --&gt;
            &lt;SettingValue Path="Operator"&gt;
            ContainsAll
            &lt;/SettingValue&gt;
            &lt;SettingValueList 
             Path="DesiredValue" 
             Definition="EnhancedKeyUsageType"&gt;
                &lt;Value&gt;ServerAuthentication&lt;/Value&gt;
            &lt;/SettingValueList&gt;
            &lt;Input 
             Name="ActualValue" 
             Path="Member.EnhancedKeyUsage" /&gt;
        &lt;/Constraint&gt;
    &lt;/ObjectConstraint&gt;
&lt;/ContainmentDefinition&gt;
&lt;!--
CertificateStore hosts a Certificate, 
although this isn't used by the design surface.
--&gt;
&lt;HostingDefinition 
 Name="CertificateStoreHostsCertificate" 
 HostDefinition="CertificateStore" 
 GuestDefinition="X509Certificate"&gt;
    &lt;Description 
     Manager="CertManager" 
     ResourceId="CertificateStoreHostsCertificate"&gt;
     A certificate store can host certificates.
    &lt;/Description&gt;
&lt;/HostingDefinition&gt;
&lt;Manager 
 Name="CertManager" 
 AssemblyName="Microsoft.Sdm.Samples.Certs" 
 SourcePath="Microsoft.Sdm.Samples.Certs.dll" /&gt;

</SystemDefinitionModel>

See Also

How to: Create an SDM Resource
ObjectConstraint (ConstraintDefinition) Element
ObjectConstraint Complex Type
Constraint (ObjectConstraint) Element

Send comments about this topic to Microsoft

Build date: 10/2/2007