From Free IPA
Contents |
Host
The analyses section below shows the object classes that have been evaluated to represent host identity in the IPA v2.
Analyses
IPA is not the first one to define the host object in the LDAP schema. Research showed that several RFCs have already defined some parts of the host object IPA plans to use.
The RFC2307 defines an AUXILARY class for ipHost.
objectclass ( nisSchema.2.6
NAME 'ipHost'
SUP top AUXILIARY
DESC 'Abstraction of a host, an IP device. The distinguished value of the cn attribute denotes the host's canonical name. Device SHOULD be used as a structural class'
MUST ( cn $ ipHostNumber )
MAY ( l $ description $ manager ) )
The ipHostNumber attribute is defined as following:
objectclass ( nisSchema.1.19
NAME 'ipHostNumber'
DESC 'IP address as a dotted decimal, eg. 192.168.1.1, omitting leading zeros'
EQUALITY caseIgnoreIA5Match
SYNTAX 'IA5String{128}' )
Other attributes are standard attributes defined in RFCs 1247 (manager) & 2256 (all the rest).
In RFC2007bis the ipHost class is defined as following:
objectclass ( 1.3.6.1.1.1.2.6
NAME 'ipHost'
SUP top AUXILIARY
DESC 'Abstraction of a host, an IP device. The distinguished value of the cn attribute denotes the host's canonical name. Device SHOULD be used as a structural class'
MUST ( cn $ ipHostNumber )
MAY ( authPassword $ userPassword $ l $ description $ manager ) )
The required attribute ipHostNumber is defined as following:
attribute ( 1.3.6.1.1.1.1.19
NAME 'ipHostNumber'
DESC 'IPv4 addresses as a dotted decimal omitting leading zeros or IPv6 addresses as defined in RFC2373'
SUP name )
As one can see in comments it is recommended to use ipHost class with the device class. The device class is defined in RFC2265 as following:
objectclass ( 2.5.6.14
NAME 'device'
SUP top STRUCTURAL
MUST cn
MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
There is also an nsHost class defined in the DS server that might be much more suitable for IPA needs.
objectclass ( nsHost-oid
NAME 'nsHost'
DESC 'Netscape defined objectclass'
SUP top STRUCTURAL
MUST cn
MAY ( serverHostName $ description $ l $ nsHostLocation $ nsHardwarePlatform $ nsOsVersion )
X-ORIGIN 'Netscape' )
As it was mentioned on the Concepts and Objects page we would want to express the following attributes:
| Attribute | Meaning and use | Suggested Attribute | Comes from | Comment |
|---|---|---|---|---|
| Fully qualified hostname | Name of the host used in UI/CLI to identify the host | commonName | device or nsHost | Potentially from nsHost |
| Kerberos principal | This a kerberos name of the host | krbPrincipalName | krbPrincipalAux | |
| Kerberos keytab | Key the host will use to authenticate against IPA | krbPrincipalKey | krbPrincipalAux | |
| Kerberos key expiration | Expiration information for the kerberos keytab | krbPrincipalExpiration | krbPrincipalAux | |
| User password | Standard DS hash of password used for the bulk enrollment | userPassword or new attribute. | <TBD> | userPassword might trigger additional behavior in plugins. This might not be the right way to go. |
| Unique identifier | It is assigned to the host at the moment of the enrollment or record creation. | nsuniqueid | <Any> | |
| CN (or DN) if the administrator who enrolled the machine | If the machine was enrolled manually | enrolledBy | <new> | There is no such attribute yet. For beter referential integrity we will use DN, not cn. |
| Version of the client installed on the machine | This version is maintained and updated by the client | ipaClientVersion | <new> | There is no such attribute yet |
| OS version | This attribute is maintained by the client | nsOsVersion | nsHost | |
| Comment | This field will be used by the administrator to add comment about the purpose of the machine | description | nsHost |
Summary
By matching ipHost and nsHost attributes with entities in the table above one can see that nsHost object is much more suitable for the IPA needs than the ipHost object. Based on this we will use the following classes to represent hosts in IPA.
- nsHost – structural class
- krbPrincipalAux – auxiliary class that holds all necessary kerberos attributes
- ipaHost – auxiliary class that will hold specific attributes that IPA cases about.
It is not clear how we should deal with the password in the host entry. We have two options:
- Use userPassword attribute. In this case there might be some unexpected behavior in the password management plugin.
- Create a new attribute for the password. In this case we would have to deal with new ACI's for this attribute.
The solution is to start using the userPassword attribute and if we hit the wall define a new attribute for enrollment password.
New Attributes
attribute ( 2.16.840.1.113730.3.8.3.10
NAME 'ipaClientVersion'
DESC 'Text string describing client version of the IPA software installed'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'IPA v2' )
attribute ( 2.16.840.1.113730.3.8.3.11
NAME 'enrolledBy'
DESC 'DN of administrator who performed manual enrollment of the host'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
X-ORIGIN 'IPA v2' )
Next attribute is defined here in case we would not be able to reuse userPassword.
attribute ( 2.16.840.1.113730.3.8.3.12
NAME 'enrollmentPwd'
DESC 'Password used to bulk enroll machines'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128}
X-ORIGIN 'IPA v2' )
Other Attributes (for reference)
attribute ( nsHostLocation-oid
NAME 'nsHostLocation'
DESC 'Netscape defined attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'Netscape')
attribute ( nsHardwarePlatform-oid
NAME 'nsHardwarePlatform'
DESC 'Netscape defined attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'Netscape' )
attribute ( nsOsVersion-oid
NAME 'nsOsVersion'
DESC 'Netscape defined attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'Netscape' )
Object Classes
Standard object class for hosts defined by Netscape.
objectclass ( nsHost-oid
NAME 'nsHost'
DESC 'Netscape defined objectclass'
SUP top STRUCTURAL
MUST cn
MAY ( serverHostName $ description $ l $ nsHostLocation $ nsHardwarePlatform $ nsOsVersion )
X-ORIGIN 'Netscape' )
Kerberos related auxiliary class:
objectclass ( 2.16.840.1.113719.1.301.6.8.1
NAME 'krbPrincipalAux'
AUXILIARY
MAY ( krbPrincipalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $
krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData )
X-ORIGIN 'user defined' )
New IPA related auxiliary class that will hold the IPA specific information:
objectclass ( 2.16.840.1.113730.3.8.4.2
NAME 'ipaHost'
AUXILIARY
MAY ( userPassword $ ipaClientVersion $ enrolledBy)
X-ORIGIN 'IPA v2' )
In case the userPassword attribute approach does not work out the object class will be altered like this:
objectclass ( 2.16.840.1.113730.3.8.4.2
NAME 'ipaHost'
AUXILIARY
MAY ( enrollmentPwd $ ipaClientVersion $ enrolledBy)
X-ORIGIN 'IPA v2' )
Example
dn: cn=ipa-client.ipa-realm.com, cn=computers, cn=accounts, ... objectClass: nsHost objectClass: krbPrincipalAux objectClass: ipaHost cn: ipa-client.ipa-realm.com serverHostName: ipa-client description: IPA test client machine localityname: Westford, MA nsHostLocation: Development Lab nsHardwarePlatform: Lenovo T61 nsOsVersion: Red Hat Enterprise Linux 5.3 krbPrincipalName: host/ipa-client.ipa-realm.com@ipa-realm.com userPassword: XYZZY ipaClientVersion: 2.1 enrolledBy: cn=ipa-admin,cn=users,cn=accounts,...
Searching for Hosts
Host can be viewed from the perspective of kerberos authentication to be a special kind of service entry.
The search that kerberos server perfoms when it is looking for a kerberos pricipals should include users, services and now hosts.
It was identified that in v1.x the function that looks up services is assuming krbPrincipal object class.
That should change. The entities that can be used in the kerberos authentication will have krbPrincipalAux object class.
This is the main criteria that should be used to find kerberos pricipals.
If the users shall be excluded but hosts and services included the search should look for krbPrincipalAux and exclude posixAccount
((objectclass = krbPrincipalAux) & (!(objectclass=posixAccount)))
The search for service will be fixed to lookup services be a new object class that will be created for services. See details below.
Bulk Deployment of Hosts
When the hosts are created for the bulk enrollment and one time enrollment password is set in the userPassword attribute the kerberos attributes and krbPrincipalAux object class won't be initially set. The enrollment procedure after authenticating with userPassword will remove the password attribute, generate kerberos attributes and apply the krbPrincipalAux object class to the host entry.
This may be done via a DS plugin that accepts a special request from ipa-getkeytab. This way we aren't relying on client code to set things properly, particularly removing the userPassword attribute.
If ipa-getkeytab is modified to be able to do a simple bind then it could authenticate to the LDAP server, issue an LDAP extended operation provided by this plugin. This plugin will then remove the userPassword attribute, update objectClass and set krbPrincipalName. If successful then ipa-getkeytab would do its keytab operation.
The result would be a local keytab that could be used for subsequent operations.
Services
A new object class will be created and applied to services during migration so that services can be easily idetified and searched.
objectclass ( OTD-TBD
NAME 'ipaService'
DESC 'IPA service objectclass'
SUP top AUXILIARY
X-ORIGIN 'IPA v2' )
The searches in the XML-RPC layer will be updated to leverage this object class.
Certificate Related Attributes and Objects
As part of the IPA v2 project we are going to integrate the certificate authority into IPA server. CA will share the back end DS with IPA as a data storage. In IPA v2 there is no plan to provide the certificate authentication capabilities for users or allow services and hosts to authenticate to IPA using the certificate as an alternative to Kerberos keytab. However it will be beneficial from the very beginning to have proper object classes applied to user, host and service entries so that certificates can actually be published into those entries.
To accomplish this we will use the attributes and object classes defined in the rfc4523.
userCertificate - The userCertificate attribute holds the X.509 certificates issued to the user by one or more certificate authorities, as discussed in clause 11.2.1 of [X.509].
( 2.5.4.36 NAME 'userCertificate'
DESC 'X.509 user certificate'
EQUALITY certificateExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
As required by this attribute type's syntax, values of this attribute are requested and transferred using the attribute description "userCertificate;binary". This is the only attribute that needs to be added to those entries. It will be added using the following object class. This object class is used in augment entries for objects that may be subject to certificates, as defined in clause 11.1.1 of [X.509].
( 2.5.6.21 NAME 'pkiUser'
DESC 'X.509 PKI User'
SUP top AUXILIARY
MAY userCertificate )
The pkiUser object class will be applied to service and host entries, so that the certificate can be published to those entries. For the user entry currently we already apply inetOrgPerson object class that contains the userCertificate attribute. However we think it would be beneficial to also apply pkiUser class to user entry so that we can easily search for all the entries that can have userCertificate attribute in the system.
Other attributes described below specify the data that will be associate with the CA as a whole. The pkiCA object will be created in the configuration section of the DIT in cn=ipaconfig,cn=etc... It is unclear whether this AUXILIARY class would be added to some already existing configuration entry user by IPA or there will be a special new configuration entry created that will contain just certificate information. This is left undecided for now it is unclear whether there will be any generic configuration information in IPA v2. Currently in IPA v1 there is no such entry.
cACertificate - The cACertificate attribute holds the X.509 certificates issued to the certificate authority (CA), as discussed in clause 11.2.2 of [X.509].
( 2.5.4.37 NAME 'cACertificate'
DESC 'X.509 CA certificate'
EQUALITY certificateExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
As required by this attribute type's syntax, values of this attribute are requested and transferred using the attribute description "cACertificate;binary".
crossCertificatePair - The crossCertificatePair attribute holds an X.509 certificate pair, as discussed in clause 11.2.3 of [X.509].
( 2.5.4.40 NAME 'crossCertificatePair'
DESC 'X.509 cross certificate pair'
EQUALITY certificatePairExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
As required by this attribute type's syntax, values of this attribute are requested and transferred using the attribute description "crossCertificatePair;binary".
certificateRevocationList - The certificateRevocationList attribute holds certificate lists, as discussed in 11.2.4 of [X.509].
( 2.5.4.39 NAME 'certificateRevocationList'
DESC 'X.509 certificate revocation list'
EQUALITY certificateListExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
As required by this attribute type's syntax, values of this attribute are requested and transferred using the attribute description "certificateRevocationList;binary".
authorityRevocationList - The authorityRevocationList attribute holds certificate lists, as discussed in 11.2.5 of [X.509].
( 2.5.4.38 NAME 'authorityRevocationList'
DESC 'X.509 authority revocation list'
EQUALITY certificateListExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
As required by this attribute type's syntax, values of this attribute are requested and transferred using the attribute description "authorityRevocationList;binary".
pkiCA object class is used to augment entries for objects that act as certificate authorities, as defined in clause 11.1.2 of [X.509]
( 2.5.6.22 NAME 'pkiCA'
DESC 'X.509 PKI Certificate Authority'
SUP top AUXILIARY
MAY ( cACertificate $ certificateRevocationList $
authorityRevocationList $ crossCertificatePair ) )
Also in the same location in the DIT we might decide to store the revocation lists.
cRLDistributionPoint class is used to represent objects that act as CRL distribution points, as discussed in clause 11.1.3 of [X.509].
( 2.5.6.19 NAME 'cRLDistributionPoint'
DESC 'X.509 CRL distribution point'
SUP top STRUCTURAL
MUST cn
MAY ( certificateRevocationList $ authorityRevocationList $ deltaRevocationList ) )
It may be simpler to add cRLDistributionPoint entry to IPA directory to have a place to store CRLs instead of defining new CA entry (containing pkiCA). This aspect is yet to be decided.
The deltaRevocationList attribute used in this class holds certificate lists, as discussed in 11.2.6 of [X.509].
( 2.5.4.53 NAME 'deltaRevocationList'
DESC 'X.509 delta revocation list'
EQUALITY certificateListExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
As required by this attribute type's syntax, values of this attribute MUST be requested and transferred using the attribute description "deltaRevocationList;binary".
Group of Hosts
Analysis
Since group of host has similar properties as group of users it should leverage same or similar object classes as group of users.
The following is the example of the group of users named “Support”.
dn:cn=Support,cn=groups,cn=accounts,dc=gsslab,dc=rdu,dc=redhat,dc=com objectClass: top objectClass: groupofnames objectClass: posixGroup objectClass: inetUser cn: Support description: Support Group gidNumber: 1100 member: uid=ssupport,cn=users,cn=accounts,dc=gsslab,dc=rdu,dc=redhat,dc=com
In this example one sees that the group of users leverages base structural class groupofnames
objectclass ( 2.5.6.9
NAME 'groupOfNames'
DESC 'Standard LDAP objectclass'
SUP top STRUCTURAL
MUST cn
MAY ( member $ businessCategory $ description $ o $ ou $ owner $ seeAlso )
X-ORIGIN 'RFC 2256' )
On top of it it uses posix attributes that come with posixGroup.
objectclass ( 1.3.6.1.1.1.2.2
NAME 'posixGroup'
DESC 'Standard LDAP objectclass'
SUP top STRUCTURAL
MUST ( cn $ gidNumber )
MAY ( userPassword $ memberUid $ description )
X-ORIGIN 'RFC 2307' )
The inetUser object class is used to provide the nesting capability.
objectclass ( 2.16.840.1.113730.3.2.130
NAME 'inetUser'
DESC 'Auxiliary class which must be present in an entry for delivery of subscriber services'
SUP top AUXILIARY
MAY ( uid $ inetUserStatus $ inetUserHttpURL $ userPassword $ memberOf )
X-ORIGIN 'Netscape subscriber interoperability' )
As one can see the choice of the object classes to represent the groups in IPA is not very clean since inetUser for example brings a lot of attributes that do not make sense in the context of the group. Another issue is that posixGroup and groupOfnames are both structural objects. This is not a good object design and violates the schema design rules though DS does not enforce them.
We evaluated several different approaches and decided that we will clean the schema for the user group a bit and use a new generic structural object class for the collections of objects that can nest each other. The new class will be based on the groupOfNames object class and look like this:
objectclass ( OID-TBD
NAME 'nestedGroup'
DESC 'Group that supports nesting'
SUP groupOfNames STRUCTURAL
MAY memberOf
X-ORIGIN 'IPA v2' )
Though groups of users and groups of hosts will be stored in different sections of the tree and we can potentially use one and the same object class for them we will also create specific object classes to differentiate them so it would be easier to perform searches.
objectclass ( OID-TBD
NAME 'ipaUserGroup'
DESC 'IPA user group object class'
SUP nestedGroup STRUCTURAL
X-ORIGIN 'IPA v2' )
objectclass ( OID-TBD
NAME 'ipaHostGroup'
DESC 'IPA host group object class'
SUP nestedGroup STRUCTURAL
X-ORIGIN 'IPA v2' )
Since the objects derive from each other creating ipaHostGroup entry will imply that it is object of the nestedGroup and groupOfNames classes.
The user groups shall from now on be created using ipaUserGroup object class. For groups that will be migrated from previous version of IPA the ipaUserGroup object class will be applied. There is a bit of collision since the ipaUseGroup is a structural class but DS does not enforce this. So we will use this back door to correct the structure of the user groups for future.
Other objects classes that will represent collections of other objects that support nesting can be derived from the common nestedGroup object class.
Association
One of the basic objects that will be used in the IPA to represent different combinations of users and hosts is named “association”. It will be the base for multiple other objects that represent netgroups, user roles, host based access control rules and may be other entities in the future. The main purpose of this object is to define association between set of users and hosts. Users can be expressed as groups, individual users or all. Hosts can be expressed via groups of hosts, individual hosts or all. The association defines the relation between set of users and set of hosts. For example in case of netgroups it is collection of users and collection of hosts that constitute the netgroup. In case of the host base access control it is the collection of users who can or depending on type of rule can't access the set of hosts.
Association Attributes
( 2.16.840.1.113730.3.8.3.13
NAME 'allUsersFlag'
DESC 'The flag to represent all users in different objects.
If true then the object references all users in the realm.
If false then other attributes will be used to determine
the set of users referenced by the object.'
EQUALITY booleanMatch
ORDERING booleanMatch
SUBSTR booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
X-ORIGIN 'IPA v2')
( 2.16.840.1.113730.3.8.3.14
NAME 'allHostsFlag'
DESC 'The flag to represent all hosts in different objects.
If true then the object references all hosts in the realm.
If false then other attributes will be used to determine
the set of hots referenced by the object.'
EQUALITY booleanMatch
ORDERING booleanMatch
SUBSTR booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
X-ORIGIN 'IPA v2')
( 2.16.840.1.113730.3.8.3.15
NAME 'memberUsers'
DESC 'Multivalue attribute that points to user DN.
Used to create reference between different IPA objects.'
SUP distinguishedName
EQUALITY distinguishedNameMatch
ORDERING distinguishedNameMatch
SUBSTR distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
X-ORIGIN 'IPA v2')
( 2.16.840.1.113730.3.8.3.16
NAME 'memberHosts'
DESC 'Multivalue attribute that points to host DN.
Used to create reference between different IPA objects.'
SUP distinguishedName
EQUALITY distinguishedNameMatch
ORDERING distinguishedNameMatch
SUBSTR distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
X-ORIGIN 'IPA v2')
Association Object
The following object class represents the ipaAssociation. The description attribute is added to store comments.
( 2.16.840.1.113730.3.8.4.3
NAME 'ipaAssociation'
SUP top
ABSTRACT
MUST ( allHostsFlag $ allUsersFlag )
MAY ( memberHosts $ memberUsers $ description)
X-ORIGIN 'IPA v2' )
The association is created as an abstract class since it contains a common set of attributes other classes will use.
Example
There is no example of the association object since it is an abstract class and thus can't be instantiated.
Host Based Access Control
Host based access control will define which users can access which machines. As it was mentioned on the Concepts and Objects page the decision about whether user can login into the host is will depend on the following factors:
- User who is trying to log in
- Machine he is trying to access
- Service (login method) he is trying to use
- Source machine from where he is trying to log in
- Time of day
Host Based Access Control Attributes
The following new attributes will be used in the host base access control entries (rules).
This attribute will store the name of the service user is using to log in.
attribute ( 2.16.840.1.113730.3.8.3.17
NAME 'serviceName'
DESC 'Name of the service used in HBAC in IPA'
EQUALITY caseIgnoreMatch
ORDERING caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'IPA v2')
The following attribute will contain information about the host the user is logging from. This attribute is a twin of the memberHosts link so it is derived from it.
attribute ( 2.16.840.1.113730.3.8.3.18
NAME 'sourceHost'
DESC 'Link to the host or group of hosts'
SUP memberHosts
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
X-ORIGIN 'IPA v2')
There might be an argument that the source hosts are not a part of the managed environment. For example access should be granted from Windows machine. In the first implementation we would require customers to create host entries for those hosts. There is no need to deploy keytabs or install software. The dummy host entry without kerberos principal and other attributes would be enough for the system to recognize it as a host entry so it can be used as source host in the HBAC rule. If we see push for things like IP address masks, IP address ranges or host name templates we will add it in future versions.
The next attribute is also a twin of an already existing attribute allHostsFlag. It is used to denote if the login is allowed from all the remote hosts or only from a specific set or subset of hosts.
attribute ( 2.16.840.1.113730.3.8.3.19
NAME 'allSourceHostsFlag'
DESC 'The flag to represent all source hosts in HBAC entry.'
SUP 'allHostsFlag'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
X-ORIGIN 'IPA v2')
The following attribute holds type of the HBAC rule.
attribute ( 2.16.840.1.113730.3.8.3.20
NAME 'accessRuleType'
DESC 'The flag to represent if it is allow or deny rule.'
EQUALITY booleanMatch
ORDERING booleanMatch
SUBSTR booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
X-ORIGIN 'IPA v2')
Expressing Time in a Rule
There are several approaches that can be used to deal with time.
- One approach is to use binary blob to represent an array of access time buckets
- Another is to have ranges.
We evaluated the two approaches and decided to go with the approach based on ranges.
Attribute
The following attribute can be used to store range information.
attribute ( 2.16.840.1.113730.3.8.3.TBD
NAME 'accessTime'
DESC 'Access time'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'IPA v2' )
It is important to acknowledge that it is a multi value attribute and that one and the same rule can have a bunch of range values. All of these values will be retrieved by the client and validated for each HBAC rule.
Grammar
The following grammar describes the format that we will use to express ranges:
timerange = Absolute / Periodic Absolute = "absolute" WSP generalizedTime WSP "~" WSP generalizedTime generalizedTime as defined in RFC 4517 section 3.3.13 but without time zone at the end Periodic = "periodic" WSP Yearly / Monthly / Weekly / Daily Yearly = "yearly" WSP Y-specifier WSP HHMM WSP "~" WSP HHMM Monthly = "monthly" WSP M-specifier WSP HHMM WSP "~" WSP HHMM Weekly = "weekly" WSP W-specifier WSP HHMM WSP "~" WSP HHMM Daily = "daily" WSP HHMM WSP "~" WSP HHMM Y-specifier = Y-month / Y-week / Y-day Y-month = "month" WSP month-number WSP M-specifier Y-week = "week" WSP week-of-the-year WSP W-specifier Y-day = "day" WSP day-of-the-year M-specifier = M-week / M-day M-week = "week" WSP week-of-the-month WSP W-specifier M-day = "day" WSP day-of-the-month W-specifier = "day" WSP day-of-the-week month-number = interval 1-12 week-of-the-year = interval 1-54 week-of-the-month = interval day-of-the-month = interval 1-31 day-of-the-week = interval 1-7 (or Mon-Sun) HH = "00" to "23" MM = "00" to "59" interval XX-YY = comma separated list of items form XX to YY, or dash separated ranges. Example (interval 1-31) 3-7,10,12,15,25-31 with no spaces inside.
This grammar allows creating a flexible set of time ranges that include absolute date ranges and periodic data ranges. The dates in the range will not contain the time zone information. After some evaluation we came to conclusion that the periodic ranges should be stored without time zone information in the same format as specified in UI and CLI and should be interpreted on the client as time range in local machine's time. For the absolute ranges the time zone would not be specified becuse absolute time ranges must be specified in UTC. This puts some burden on the UI and CLI to convert the time stamps entered in local time format during management operations into the UTC format. The applications that would go directly to LDAP for this data must be aware of the rules and assumptions described above.
Examples
On Saturday and Sunday from 9AM to 1PM EST every second week of every month local machine's time:
periodic monthly week 2 day Sat,Sun 0900-1300
From midnight 10 th of October till midday 15th of October 2008 in UTC
absolute 20081010000000 ~ 20081015120000
Host Based Access Control Objects
The following structural object will be used to denote a HBAC rule. Note that it is derived from IPA association so the attributes that are defined in the ipaAssociation are implied by derivation. The description is added to allow commenting on the meaning of the rule.
objectclass ( 2.16.840.1.113730.3.8.4.5
NAME 'ipaHBACRule'
SUP ipaAssociation
STRUCTURAL
MUST accessRuleType
MAY ( serviceName $ sourceHost $ allSourceHostsFlag $ accessTime $ description)
X-ORIGIN 'IPA v2' )
The HBAC rules will be stored under hbac hive in the DIT. It will be on the same level as accounts, Kerberos, roles and radius.
Example
The following example shows a simple allow rule. It allows user “dpal” access host “dpal-dev” at any time using any service and from any host.
dn: nsuniqueid=782546F1-15FE-11D3-9009-030ABCDC8899, cn=hbac,... objectClass: top objectClass: ipaAssociation objectClass: ipaHBACRule allHostsFlag: false allUsersFlag: false accessRuleType: true memberUsers: cn=dpal,cn=users,cn=accounts,... memberHosts: cn=dpal-dev,cn=computers,cn=accounts,...
The following example allows user “dpal” and group of users “Development” access host “test-ipa@lab.ipa.com” and group of hosts “VirtGuests” via ssh at any time.
dn: nsuniqueid=782546F1-15FE-11D3-9009-030ABCDC8899, cn=hbac,... objectClass: top objectClass: ipaAssociation objectClass: ipaHBACRule allHostsFlag: false allUsersFlag: false accessRuleType: true memberUsers: cn=dpal,cn=users,cn=accounts,... memberUsers: cn=Development,cn=groups,cn=accounts,... memberHosts: cn=test-ipa@lab.ipa.com,cn=computers,cn=accounts,... memberHosts: cn=VirtGuests,cn=hostgroups,cn=accounts,... serviceName: ssh
The following example prohibits user “ssupport” and group of users “Guests” access host “test-ipa@lab.ipa.com” and group of hosts “VirtGuests” via ssh over weekend in local machine time.
dn: nsuniqueid=782546F1-15FE-11D3-9009-030ABCDC8899, cn=hbac,... objectClass: top objectClass: ipaAssociation objectClass: ipaHBACRule allHostsFlag: false allUsersFlag: false accessRuleType: false memberUsers: cn=ssupport,cn=users,cn=accounts,... memberUsers: cn=Guests,cn=groups,cn=accounts,... memberHosts: cn=test-ipa@lab.ipa.com,cn=computers,cn=accounts,... memberHosts: cn=VirtGuests,cn=hostgroups,cn=accounts,... serviceName: ssh accessTime: periodic weekly day Sat,Sun 0000-2400
Extracting Rules from Server
The access control decision is made on the client by PAM responder component. It would happen after the kerberos authentication is performed. To make such decision the client needs to have at hand a set of rules that define would allow it to make a decision. So first the rules should be requested from the IPA server. To request these rules the client only has two pieces of information:
- user identity
- host identity
The client will lookup the user record by login name and host entry by common name or kerberos principal. These lookups are simple and thus not shown here. Some of this information might already be pre-fetched and stored in the LDB cache (see client design pages for more details). Now having all the information about user and host group membership the client would be able to retrieve the set of rules that are applicable to the user-host combination. The rules will be cached locally for offline authentication but will have a short cache lifetime for online authentication. Buy default the cache lifetime for HBAC will be pretty low (60 seconds for “expiring” and 60 seconds more for “expired”). That means that if there are two sequential logins by one and same user within a minute the set of rules would not be refreshed. If logins are more than a minute but less than two minutes apart the decision will be made based on the cached values and the cached rules will be refreshed asynchronously. If there are more than two minutes between two logins the IPA provider will fetch a refreshed set of the HBAC rules from the server.
The main issue with this operation is formulating the right search filter to retrieve the right set of entries.
The filter should reflect the following logic:
Select all rules that are applicable to current host and user.
Since user can be expressed as a specific user, group or all and similarly host the can be expressed as a specific host, group or all the statement above can be translated in to the following mnemo statement:
Select all rules applicable to (all hosts OR this host explicitly OR group of hosts this host is a member of) AND (all users OR this user explicitly OR group of users this user is a member of).
In the first implementation the client will have to dynamically construct the search filter following the template below.
((allHostsFlag = true) |
((allHostsFlag = false) &
(
(memberHosts = <hostdn>) |
(memberHosts = <host's memberOf value A>) |
(memberHosts = <host's memberOf value B>) |
(memberHosts = <host's memberOf value ...>) |
(memberHosts = <host's memberOf value Z>) |
)
)
) &
((allUsersFlag = true) |
((allUsersFlag = false) &
(
(memberUsers = <userdn>) |
(memberUsers = <user's memberOf value A>) |
(memberUsers = <user's memberOf value B>) |
(memberUsers = <user's memberOf value ...>) |
(memberUsers = <user's memberOf value Z>) |
)
)
)
This is a pretty complex search filter so I will break it in parts to explain what different parts actually mean.
Later we might add a convenience control that will do the work on the server side.
There is a concern that this long search filter might have some problems on the client side since the lebgth of the filter might get too long and thus hit the internal buffer limitations (if any). This will be determined while prototyping IPA provider.
Processing Rules on the Client
After retrieving all the HBAC rules and saving them locally the client would have to actually process the rules and check if the user should be granted access or not. The following mnemonic code describes the logic:
SERVICE – name of the service that was used for login. Set by application. REMOTEHOST – name of the host that the user is login from remotely.
BOOL ALLOWACCESS = FALSE
FOR EACH RULE:
IF SERVICE IS KNOWN
IF RULE CONTAINS serviceName ATTRIBUTE
BOOL FOUND = FALSE
FOR EACH serviceName:
IF SERVICE = serviceName
FOUND = TRUE
ENDIF
END FOR
IF FOUND = FALSE
GOTO NEXT RULE
ENDIF
ELSE
/* Continue evaluating this rule. Rule is applicable to all services */
ENDIF
ELSE
/* SERVICE is not known so we should evaluate only rules that apply to all services on the */
IF RULE CONTAINS serviceName ATTRIBUTE
/* Skip rules that are targeting specific services */
GOTO NEXT RULE
ENDIF
ENDIF
/* If we are here the current rule is applicable to the service the user is using to log in */
IF allSourceHostsFlag = FALSE
/* Evaluate details of the source host only if rule is applicable to some subset of hosts otherwise continue to checking time constraints */
IF REMOTEHOST IS KNOWN
IF RULE CONTAINS sourceHost ATTRIBUTE
GET REMOTEHOST RECORD remHost FROM SERVER
BOOL FOUND = FALSE
FOR EACH sourceHost VALUE:
IF serviceHost = remHost
/* We found an explicit rule for the remote host – break from loop */
FOUND = TRUE
BREAK
ELSE
FOR EACH remHost's memberOf VALUE:
IF serviceHost = memberOf
/* We found a group based rule for the remote host – break from loop */
FOUND = TRUE
BREAK
ENDIF
END FOR
ENDIF
END FOR
IF FOUND = FALSE
/* This rule is not applicable to this current source host */
GOTO NEXT RULE
ENDIF
ELSE
/* There is no specific source host in the rule so it is applicable to all hosts – move on to time checking */
ENDIF
ELSE
/* REMOTEHOST is not known but rule has some hosts specified – move to next rule */
GOTO NEXT RULE
ENDIF
ELSE
/* Rule is applicable to all source hosts so go on evaluating time constraints */
ENDIF
/* If we are here the rule is still can be applicable to the current situation */
/* Do time checking */
IF accessTime NOT PRESENT OR EMPTY
/* We matched the rule – fall through ! */
ELSE
IF currentTime in accessTime
/* We matched the rule – fall through! */
ELSE
GOTO NEXT RULE
ENDIF
ENDIF
/* If we are here – we matched the rule */
IF IT IS A DENY RULE
/* No need to loop any more */
RETURN ACCESS DENIED
ELSE
ALLOWACCESS = TRUE
END FOR
/* We walked through all the rules */
IF ALLOWACCESS = TRUE
RETURN ACCESS DENIED
ENDIF
/* No rule matched */
RETURN ACCESS DENIED
Netgroups
The RFC2307bis schema defines nisNetgroup object class to represent netgroups.
objectClass ( 1.3.6.1.1.1.2.8
NAME 'nisNetgroup'
DESC 'Standard LDAP object class'
SUP top
STRUCTURAL
MUST cn
MAY ( nisNetgroupTriple $ memberNisNetgroup $ description )
X-ORIGIN 'RFC 2307' )
- nisNetgroupTriple – is a triplet of host-user-domain.
- MemberNisNetgroup – is the DN of other netgroup to represent nesting.
IPA will contain a special object to represent netgroups. It is done to avoid duplication of information in user, host entries and netgroup's nisNetgroupTriple attribute. According to specification there is no meaning behind the individual user-host pairs so netgroup can and should be represented by collection of hosts and collection of users. Thus the netgroup entry should point to a user entry, group(s) of users or all. It should also be able to point to the host, group(s) of hosts or all hosts. For this purpose the netgroup object will be derived from the ipaAssociation abstract class.
In addition attributes provided by ipaAssociation object the netgroup entry should also be able to specify hosts that are not members of the IPA domain. A new attribute will be added to address this use case.
Also netgroups can nest each other so netgroup entries will have member and memberOf attribute. The plugin that handles referential integrity of group membership attributes will automatically maintain the correct value for memberOf attribute when netgroup is nested into another netgroup.
The domain information will be associated to the netgroup as a whole. There will be a special attribute nisDomainName added for this purpose. If the nisDomainName attribute is not specified then the IPA realm should be automatically assumed. Also a special config entry can be used to fill the default value for nisDomainName. If the customer would need netgroups for different domains he would have to create two different netgroups.
Netgroups Attributes
externalHost is a new multi value string attribute that allows storing host names. It is convenient for specifying hosts that are not directly managed by IPA but which are members of the netgroup. Because values of this attribute are used directly to construct netgroup triples which are seen by client systems, only exact names can be specified.
attribute ( 2.16.840.1.113730.3.8.3.23
NAME 'externalHost'
DESC 'Multivalue string attribute that allows storing host names.'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'IPA v2' )
The following attribute is going to hold the single value for nisDomain name.
attribute ( 2.16.840.1.113730.3.8.3.24
NAME 'nisDomainName'
DESC 'NIS domain name.'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
X-ORIGIN 'IPA v2' )
Netgroups Object
The main netgroup object class will look like this (note that it is derived from ipaAssociation so its attributes are implied):
objectClass ( 2.16.840.1.113730.3.8.4.6
NAME 'ipaNISNetgroup'
DESC 'IPA version of NIS netgroup'
SUP ipaAssociation
STRUCTURAL
MUST cn
MAY ( externalHost $ nisDomainName $ member $ memberOf )
X-ORIGIN 'IPA v2' )
The the netgroups would be stored under cn=ng, cn=alt, ... in the DIT. The “alt” stands for alternative. Later other “alternative” concepts will end up in this hive.
The default configuration object is described later on this page.
NG Plugin
Since IPA is going to change the schema for netgroups it will break the expectations of the LDAP clients that are relying on the standard LDAP schema for netgroups defined in RFC2307. To avoid this situation we will create a special new DS plugin named NG plugin. This plugin will synthesize LDAP entries in the standard format in a different part of the tree. It is very similar to the way the compatibility plugin works. The NG plugin will look at requests targeting “cn=netgroup,cn=compat,...”, read the entries from “cn=ng,cn=alt,...” and translate them into entries of nisNetgroup object class. The details of this mechanism can be found in the Schema Compatibility Plug-in Design page.
The following algorithm illustrates the creation of virtual entries in response to client request for the nisNetgroup object. This is not the algorithm that will be implemented. It is an illustration of a straightforward approach which very fast becomes very complex and ugly but helps to come up with a more elegant solution:
Note: I used * to denote all and – to denote none.
GET ipaNISNetgroup ENTRY
IF nisDomainName IS NOT KNOWN
IF DEFAULT nisDomainName IS DEFINED IN CONFIG
nisDomainName = default domain /* Can be empty */
ELSE
nisDomainName = ipa domain
ENDIF
ENDIF
IF allUsersFlag = TRUE
IF allHostsFlag = TRUE
CREATE nisNetgroupTriple = (*,*,nisDomainName)
ELSE
IF memberHosts IS EMPTY OR NOT PRESENT AND
hostMask IS EMPTY OR NOT PRESENT
CREATE nisNetgroupTriple = (-,*,nisDomainName)
ELSE
CREATE nisNetgroupTriple = (,*,nisDomainName)
IF memberHosts IS PRESENT
FOR EACH memberHosts:
GET obj by memberHosts
IF objectClass of obj = nsHost
CREATE nisNetgroupTriple = (obj's cn,,nisDomainName)
ELSE
/* obj is a group of hosts then */
FOR EACH host member of obj:
GET memberObj as member of obj
IF objectClass of memberObj = nsHost
CREATE nisNetgroupTriple = (memberObj's cn,,nisDomainName)
ELSE
/* Nested group */
... <- will be handled by recursive function
ENDIF
END FOR
ENDIF
END FOR
ENDIF /* memberHosts IS PRESENT */
/* Handle host mask here */
IF hostMask DEFINED
FOR EACH hostMASK VALUE
CREATE nisNetgroupTriple = (hostMASK,,nisDomainName)
ENDIF /* memberHosts IS EMPTY OR ... */
ENDIF /* allHostsFlag = TRUE */
ELSE
IF allHostsFlag = TRUE
IF memberUsers IS EMPTY OR NOT PRESENT
/* All hosts and no users */
CREATE nisNetgroupTriple = (*,-,nisDomainName)
ELSE
CREATE nisNetgroupTriple = (*,,nisDomainName)
FOR EACH memberUsers:
GET obj by memberUsers
/* Similar expansion of user identities into nisNetgroupTriple as above */
... <-iterate and create (,cn,nisDomainName) nisNetgroupTriple attributes. Use recursion for nested groups
END FOR
ENDIF
ELSE
IF memberUsers IS EMPTY OR NOT PRESENT
IF memberHosts IS EMPTY OR NOT PRESENT AND
hostMask IS EMPTY OR NOT PRESENT
/* Empty netgroup */
CREATE nisNetgroupTriple = (-,-,nisDomainName)
ELSE
/* Create empty user entry */
CREATE nisNetgroupTriple = (,-,nisDomainName)
/* Expand host entries as shown above */
...
ENDIF
ELSE
IF memberHosts IS EMPTY OR NOT PRESENT AND
hostMask IS EMPTY OR NOT PRESENT
/* No hosts but there are users */
CREATE nisNetgroupTriple = (-,,nisDomainName)
/* Expand users */
...
ELSE
/* Both links are present */
/* Loop resolving two lists at the same time */
UNTIL NO MORE USERS or HOST
GET NEXT user
GET NEXT host
CREATE nisNetgroupTriple = (user,host,nisDomainName)
END UNTIL
ENDIF
ENDIF
ENDIF
ENDIF
The logic above is very complex but it definitely showed the need for the functions like GET NEXT USER and GET NEXT HOST. These functions should use recursion internally to traverse nested groups of users and hosts. If we hide all the complexity of nesting inside the functions as assume that:
- Function has the following signature: int getNextUser(char *user,... /* ldap handle */). The context parameters related to state are omitted and left till implementation.
- Function puts name of the user into user field and returns 0 if there are more and 1 if there are no more entries (it reached the end of the set)
- If function reached the end of the set and already once returned 1 and called again in this state it returns 1 and the null terminated empty string in the user field.
- If the netgroup specifies all users the function will return 1 and “*” in user field. If called again it will return 1 and empty string in user field as was mentioned above.
- If the netgroup specifies no users the function will return 1 and “-” in user field. If called again it will return 1 and empty string in user field as was mentioned above.
With the similar getNextHost function the logic above can be rewritten in a form of a simple loop:
DO
nomoreusers = getNextUser(user,...)
nomorehosts = getNextHost(host,...)
CREATE nisNetgroupTriple = (host,user,nisDomainName)
UNTIL nomoreusers & nomorehosts
In this case the getNextUser function will logically consist of 3 parts:
- Handle past end condition
- Handle special cases – no users or all users
- Iterate through group containers resolving nesting
The nesting of the netgroups themselves is a simple one-to-one mapping of the member attribute to the memberNisNetgroup attribute of the virtual entry.
Example
This is the example of the 2 netgroups using new IPA schema. One netgroup is nesting another.
dn: cn=ng1,cn=ng,cn=accounts,... objectclass: top objectclass: ipaAssociation objectclass: ipaNISNetgroup cn: ng1 allHostsFlag: false allUsersFlag: false memberHosts: fqdn=myhost.lab.com,cn=computers,cn=accounts,... memberHosts: cn=VirtGuests,cn=hostgroups,cn=accounts,... memberUsers: cn=sss,cn=users,cn=accounts,... memberUsers: cn=dpal,cn=users,cn=accounts,... memberUsers: cn=Engineering,cn=groups,cn=accounts,... nisDomainName: oldnis.domain.com member: cn=ng2,cn=ng,cn=accounts,... dn: cn=ng2,cn=ng,cn=accounts,... objectclass: top objectclass: ipaAssociation objectclass: ipaNISNetgroup cn: ng2 allHostsFlag: false allUsersFlag: false externalHost: foo.lab.domain.com memberUsers: cn=rcrit,cn=users,cn=accounts,... memberUsers: cn=Support,cn=groups,cn=accounts,... nisDomainName: lab.domain.com memberOf: cn=ng1,cn=ng,cn=accounts,...
These two entries will be translated into the following virtual entries assuming that:
- VirtGuests = guest1.vg.com, guest2.vg.com, guest3.vg.com, NestedVirtualGuests
- NestedVirtualGuests = nvguest1.vg.com, nvguest2.vg.com, nvguest3.vg.com
- Engineering = dev1, dev2, dev3
- Support = support1, support2, support3
dn: cn=ng1,cn=netgroups,cn=accounts,... objectclass: top objectclass: nisNetgroup cn: ng1 nisNetgroupTriple: (myhost.lab.com,sss,oldnis.domain.com) nisNetgroupTriple: (guest1.vg.com,dpal,oldnis.domain.com) nisNetgroupTriple: (guest2.vg.com,dev1,oldnis.domain.com) nisNetgroupTriple: (guest3.vg.com,dev2,oldnis.domain.com) nisNetgroupTriple: (nvguest1.vg.com,dev3,oldnis.domain.com) nisNetgroupTriple: (nvguest2.vg.com,,oldnis.domain.com) nisNetgroupTriple: (nvguest3.vg.com,,oldnis.domain.com) memberNisNetgroup: ng2 dn: cn=ng2,cn=netgroups,cn=accounts,... objectclass: top objectclass: nisNetgroup cn: ng2 nisNetgroupTriple: (foo.lab.domain.com,rcrit,lab.domain.com) nisNetgroupTriple: (,support1,lab.domain.com) nisNetgroupTriple: (,support2,lab.domain.com) nisNetgroupTriple: (,support3,lab.domain.com)



