TPS - New Recovery Option: External Registration DS

From Dogtag
Jump to: navigation, search

New Recovery Option: External Registration DS

This page contains a preliminary design that implements a new TPS cert/key recovery option in which TPS will obtain key enrollment and recovery information from an external registration Directory Server where user entries are kept. Such an option would allow a site to have control to overwrite the token enrollment, revocation, and recovery policies which were previously inherent to TPS.

  • Base External Registration Design-
    • In the first part of this document, it details the Base External Registration Design.
  • Delegation Option-
    • In the second part of this document, an optional enhancement called "Delegation Option" is introduced. The Delegation option will be useful in the scenario that a delegate could potentially own a token which contains certain certificates and their keys so that a delegate can act on behalf of the executive.
  • Alternative Base External Registration Design (currently preferred)-
    • In the third part of this document, an alternative to the Base Design is introduced. It is to replace the Base Design in how the certs/keys on the token are controlled from the registration database. The introduction of this alternative base design does not affect the delegation option listed above.
 Note: Only one of the base designs will be implemented.  We currently prefer the 
 Alternative Base External Registration Design and unless we hear otherwise, 
 we will start on the implementation of this alternative base design on 7/15/2013.

Base External Registration Design

Assumptions

When this new option is turned on, the following are assumed:

  • The External Registration DS is expected to contain user login entries where each entry contains expected attributes specified in the proposal below.
  • All the inherent TPS policies are ignored, such as:
    • one token per user
    • revocation per change of token status
    • which certs/keys to recover
    • etc.
  • the "Registration DB" is the same as TPS' "authentication db" specified in CS.cfg:
    • e.g. auth.instance.0.authId=ldap1
    • where the host, port, baseDN, etc have been defined
  • The connector definition information (e.g. conn.ca1.xxx, conn.drm1.xxx) are retained for revocation and recovery purpose.

Proposed Design

New Configuration Parameters

  • New global flag introduced into CS.cfg to turn on and off such "lookup registration db" option:
    • e.g. externalReg.enable=true|false
  • New global (not per db instance) parameters for the lookup attributes:
    • externalReg.tokenTypeAttributeName=tokenType
    • externalReg.certs.recoverAttributeName=certsToRecover
    • externalReg.certs.deleteAttributeName=certsToDelete
    • externalReg.certs.cuidAttributeName=tokenCUID
  • New global parameter to point to one of the auth instances:
    • e.g. externalReg.authId=0 (where the value is the auth.instance.X value)
 Note that we are hoping the "recover" and "delete" attributes are multi-valued attributes. 
    It is also proposed to use class-of-service on ldap to define group certs,
    where it will share the same attribute certsToRecover as the certs to recover.
 Also note that for recovery, it is essential for TPS to know which DRM instance to recover the cert(s) from.
    It is therefore proposed that the drm id being stored with the certsToRecover.
      e.g. (34456, ca1, 81, drm1), where 34456 is the serial number (in decimal), 81 is the key id (in decimal)
          and ca1 and drm1 are respective connid's defined in TPS's CS.cfg
 Also to consider is whether certsToDelete should include a flag to indicate if the cert(s) should be revoked or not,
      e.g. (2231, ca1, true), where 2231 is the serial number, ca1 is the connid, and true indicates revocation is requested
 In order to ensure the right token gets updated by the rightful owner, another ldap attribute can be added to store the 
      cuid of the smart card token along with the user registration entry.
      e.g. (a00192030405060800c9)
      In this case the registration software that manages the external db can do the following:
      * if the cuid attribute is absent in the user registration entry, at each enrollment, cuid can be extracted
        from the TPS token db and stored in the user entry.
       (assumption here is that initially, for a blank token, it does not matter which user it is tied to)
      while TPS can do the following:
      * if the cuid attribute is present in the user registration entry, then at each enrollment/recovery, the cuid is verified
      * if the cuid attribute is absent in the user registration entry, then enrollment/recovery is allowed once passed authentication
  • The names under externalReg.certs.xxxAttriuteName need to be listed under an existing auth attributes parameter in order to be retrieved:
    • e.g. auth.instance.0.attributes=mail,cn,uid,tokenType,certsToRecover,certsToDelete,tokenCUID

Design Detail

  • If externalReg is enabled, relax all the relevant policies; otherwise, it works the same as before.
  • token has already been formatted (not necessarily tied to any uid)
  • user authentication takes place before token type is determined (retrieved from user entry in registration db).
    • this turns things around in TPS. Currently, the tokenType is determined before auth db is identified. In the new design when externalReg is enabled, the "op.enroll.<tokenType>.auth.id" will be ignored, as the tokenType is retrieved from the reg user entry on the ldap after the authentication.
    • tokenCUID attribute retrieved and
      • If present, then it is validated against the active token to assure that only the right token is being acted upon.
      • If not present, then any token can be used (which is the case for any initial enrollment).
  • during enrollment or recovery, enrollment info will be retrieved from the tokenType entry in CS.cfg and enrollment will proceed; whereas the "certs.recover" info will be retrieved from the user reg entry on the ldap. And if "certs.delete" is specified, certs specified will be deleted. For example, op.enroll.userKey.keyGen.signing.xxx instructs TPS to generate new signing keys/cert, while the "externalReg.certs.recoverAttributeName" gives info on which encryption keys/certs to recover.
  • the "certs to recover" are identified by the drm and serial number (and perhaps additional ca SKI for verification purposes).
  • modify the code so that for each cert/key added to the token, it has a "counter" added to the label to make sure each name is unique.
  • At this point, we do not need anything fancy to handle cases when a token is full (just reject gracefully will be good enough)

Delegation Design

This design is considered as an optional option on top of the base design specified above and the alternative base design below. The scenario is that an executive has a number of delegates that can act on his/her behalf, in terms of:

  • authentication (login)
  • encrypt/decrypt emails
  • signing (LIMITED use)

It offers the following features:

  • The delegate has two tokens:
    • a token of his own which contains his own certs. It is to be registered through the system with the base design above. This will not be discussed further in this part of the design.
    • a token (ref. as "delegate token" here on) that the delegate uses to act on behalf of the executive, which contains a combination of (determined by TPS profiles) the following certs/keys:
      • auth cert/keys - cn contains name and the unique id of the delegate's; SAN (Subject Alternative Name extension) contains the UPN (Other Name:Principal Name) of the executive's.
      • enc cert - the executive's encryption cert (exact copy of the executive's own encryption cert)
      • signing cert - cn contains name and the unique id of the delegate's; SAN contains RFC822Name of the executive's.

Assumptions

The assumptions for the Delegation option are the same as that of the base design.

Proposed Design

New Configuration Parameters

In addition to the proposed parameters in the base design, a few more parameters are introduced:

  • New global flag introduced into CS.cfg to turn on and off such "delegation" option:
    • e.g. externalReg.delegation.enable=true|false
  • note: The name attributes can be retrieved via the auth parameter, e.g.
    • auth.instance.0.attributes=mail,cn,uid,tokenType,certsToRecover,certsToDelete,tokenCUID,execRFC822Name
  • New profile-specific parameters:
    • op.enroll.userKey.keyGen.signing.DN=
    • op.enroll.userKey.keyGen.signing.SAN=

Design Detail

  • TPS: TPS profile enhancement: a (or, a set of) per-TPS profile parameter(s) to get the desired DN and the exec's upn:
    • a pattern'd DN entry (e.g. op.enroll.userKey.keyGen.signing.DN=CN=$auth.cn$,O=Token Key User (assuming auth instance ldap attributes set includes the needed entries: e.g. auth.instance.1.attributes=execUPN,cn,uid )
    • a pattern'd SAN entry (e.g. op.enroll.userKey.keyGen.signing.SAN=$auth.execRFC822Name$
    • RHCS will provide sample TPS profiles that make use of the new enhancements (perhaps one for the id/enc token and one for the id/enc/sign token).
  • CA: a new CA enrollment profile as well as needed profile default plugin will be implemented to take DN and UPN directly from TPS.
  • DRM: for key recovery, per design for recovery above, only the serial numbers and associated subsystem ids are stored in the user registration record, DRM (and TPS) will be modified to handle "recovery by serial numbers."

Alternative Base External Registration Design

NOTE: Because of some internal limitations, all mentioning of the "retaining" feature in regards to encryption certs
      below shall be exercised with the full 4-tuplet: (serial#, caID, keyid, drmID), just like when you are 
      "recovering" a cert/key.

Assumptions

When this new option is turned on, the following are assumed:

  • The External Registration DS is expected to contain user login entries where each entry contains expected attributes specified in the proposal below.
  • All the inherent TPS policies are ignored, such as:
    • one token per user
    • revocation per change of token status
    • which certs/keys to recover
    • etc.
  • the "Registration DB" is the same as TPS' "authentication db" specified in CS.cfg:
    • e.g. auth.instance.0.authId=ldap3
    • where the host, port, baseDN, etc have been defined
  • The connector definition information (e.g. conn.ca1.xxx, conn.drm1.xxx) are retained for revocation and recovery purpose.

Proposed Design

This is proposed as an alternative to the original Base External Registration Design. In this case, it differs in that instead of having two separate lists, one to recover, and one to delete (revocation assumed not to happen upon delete), this alternative design only works with one list, where the certs represents ALL of the certs (and their associated keys) to put on (or retained) the token after the TPS profile has been processed for enrollment or renewal. Any extra certs/keys not newly created or listed on this list will be deleted (with option to revoke).

The idea is actually pretty straight-forward. Whatever you want to keep on the token, you put the necessary info in "certsToAdd", and whatever you want issued anew, you specify in the profile (just like before). Anything not falling into either gets removed.

Recovering(Adding) certs onto Existing Token

The externalRegAddToToken profile is a sample profile that shows how to "add" certs to the token without generating new certs (yes, even if your token already has some certs on it). So for example, if you have 3 existing certs: signingA, encryptionB, and authC on the token, and you want to add encryptionB2 without disturbing the existing certs/keys on token, you

  1. point to externalRegAddToToken profile
  2. add ALL certs' info on the user's registration record certsToAdd attribute. e.g. (say, signingA is serial #32, encryptionB is serial#33, and authC is serial#34, and encryptionB2 is serial#12)
    • certsToAdd: 32,ca1
    • certsToAdd: 33,ca1,4,drm1
    • certsToAdd: 34,ca1
    • certsToAdd: 12,ca1,1,drm1
    NOTE how all the encryption certs need drm info (regardless of whether it's retaining or adding)

Regenerate, Retain, and Recover(Add)

Now, if you want to "generate, retain, and recover certificates all in one swoop" then you can point to a profile such as userKey, and change your certsToAdd attribute. The userKey will generate the new certs/keys for you, and if you fill in the info correctly as instructed above with certsToAdd, then it should do the "generate, retain, and recover certificates all in one swoop" for you.

New Configuration Parameters

  • New global flag introduced into CS.cfg to turn on and off such "lookup registration db" option:
    • externalReg.default.tokenType=externalRegAddToToken
    • externalReg.delegation.enable=true
    • externalReg.enable=true
    • externalReg.format.loginRequest.enable=false
  • New per db instance parameters for the lookup attributes:
    • auth.instance.2.externalReg.certs.recoverAttributeName=certsToAdd
    • auth.instance.2.externalReg.cuidAttributeName=tokenCUID
    • auth.instance.2.externalReg.tokenTypeAttributeName=tokenType
  • New global parameter to point to one of the auth instances:
    • e.g. externalReg.authId=ldap3 (where the value is the auth.instance.authId value)
 Note that we are hoping the "tokenCerts" attribute is a multi-valued attribute. 
    It is also proposed to use class-of-service on ldap to define group certs,
    where it will share the same attribute tokenCerts as the certs to go on the token.
      e.g. (34456, ca1, 81, drm1, revoke), where 34456 is the serial number (in decimal),
          81 is the key id (in decimal)
          ca1 and drm1 are respective connid's defined in TPS's CS.cfg
          note now the "revoke" flag is removed from this alternative design.  The idea is that since there is now a
          "revoke" flag in the tokendb cert entry, we can assume no revocation for deletion, unless specified
          otherwise in the tokendb cert entry. Also the revocation can be done on the CA manually.
    In case of a signing cert/key already on token, a serial number and ca connid are enough to identify the object.
    The cuid part of usage is the same as that of the Base Design, where it's presence will restrict the enrollment
        of the user to one particular token with the specified unique tokenCUID in record.

Design Detail

  • Design regarding tokenType and enrollment from profiles remains the same as that of the Base Design.
  • TPS uses the tokenCerts as a template to decide what needs to go on the token and what not.
    • all certs and their associated keys that do not appear on the tokenCerts list are deleted. Revocation is now to be managed manually when needed.
  • Enrollment is still done per profile. A new per-cert-per-profile attribute might be added to decide is a cert is to be revoked when delete is performed:
    • op.enroll.userKey.keyGen.encryption.delete.revokeCert=false
    • upon enrollment per such profile, the revocation instruction is stored on the new attribute in the tokendb.

To Revoke or Not to Revoke (VERY IMPORTANT)

Since part of the reason for having this new feature is to allow shared certs within a whole department or group, revocation decision should be made with caution because you don't want to inadvertently revoke the shared cert unnecessarily. And because of this reason, we have set all the externalReg profiles revokeCert configuration parameters to "false" by default, and allowing sites to make their own decision to turn them back on or just go to the CA to revoke certs manually.<p> Warning: This applies even when you terminate a token when there is a possibility of key compromise. In the case when a shared cert is revoked, all tokens need to be updated with a new shared cert, it involves a numbers of things to be updated on every token that contained the revoked shared cert:

  • Delete the revoked shared cert on the token: This involves no steps, as if you don't list the cert in the certsToAdd attribute in the user registration record, it's deleted
  • Add the new shared cert on the token: Modify the certsToAdd attribute to have the new cert info,
    • e.g. certsToAdd: 23,cs1,4,drm1
  • Retain the individual certs existing on each token: Find out ALL info on every cert and list them into certsToAdd attribute(s)
    • WARNING: If you don't add them to the certsToAdd list, you lose them
      • and when you lose them, either of the following will happen:
        • if they are NOT revoked: they become orphaned, unused certs.
        • if they are revoked: they cause your CRL to grow unnecessarily large
    • This can be cumbersome, but it is the approved design

Test Description (this section is slightly outdated; when in doubt, always read the design above)

 Some background:
 1. please read the design above
 2. ALL profiles provided are just samples to demonstrate what you can do.
    People are expected to customize these profiles.
 3. Please note that the new profiles are introduced as addition to existing profiles, not replacing in
    the case of externalReg.  For example,
    * there is no existing profile that allows one to "recover" certs only (without generating new certs),
      so externalRegAddToToken is added to demonstrate that. The existing userKey can be used with externalReg
      to already demonstrate that you can issue new certs AND recover using externalReg, so no need to create 
      another sample profile specific for it. 
 4. There are two major features introduced on that design page: 
    * The concept of allowing the registration record to control which profile to use and which certs to "recover"
       - to use and which certs to "recover"
    * The concept of allowing "delegation" (which is explained in the design).
      And for this, as examples, two new sample profiles are provided to show the delegation feature:
      - delegateISEtoken and delegateIEtoken 
      They are ONLY for delegation case.

The test cases scenarios are somewhat outdated.

Scenario 1: Same userid for one user. In a non-delegation, externalReg environment
  • Note during each of these scenarios, there may be a need to format a token. For this to work in the exernal reg environment, the tokenCUID field of the registration record must match that of the token for even Format to succeed.

case 1 (with blank token) enrollment for an ISE (Id, Signing, Encryption) token, where the "encryption" cert is a shared cert "recovered" from ldap.

  • Modify user record, "user1a", with the following info:
    • tokenType: delegateISEtoken
    • certsToAdd: 33,ca1,55,drm1
  • enroll with user1a
    • (this will generate two certs: signing and authentication, but "recover" the encryption cert as specified)

case 2 (with same already-loaded token) enrollment for an ISE token, where the "encryption" cert is a shared cert "recovered" from ldap to ADD to the existing certs/keys on the token without destroying them.)

  • Modify user record, "user1a", with the following info:
    • tokenType: externalRegAddToToken
    • certsToAdd: 44,ca1,66,drm1
    • certsToAdd: <find out what's already on the token, and add them to this multi-value field>
  • enroll with user1a
    • (this will not generate any new certs, but retain the existing certs on token, but "recover" one more encryption cert onto the token as specified)

case 3 (with same already-loaded token) enrollment for an ISE token, where there are TWO "encryption" certs that are "recovered" from ldap.

  • replace the tokenType: delegateISE
  • replace certsToAdd from user1a with two values:
    • certsToAdd: 33,ca1,55,drm1
    • certsToAdd: 77,ca1,88,drm1
  • enroll with user1a
    • (this will wipe out the existing certs/keys on token, and generate two certs: signing and authentication, but "recover" the two encryption certs as specified)
    • also, for the certs that are "wiped out"
      • if externalReg.delete.deleteFromDB=true, then check if the cert entry is deleted from TUS
      • if externalReg.delete.deleteFromDB= false, then check if the cert entry stays in TUS
      • (note: revocation is NOT assumed per design... one will have to go to the CA to do so manually)

case 4 (with same already-loaded token) enrollment for an ISE token, where there is one "encryption" cert that is to be "recovered" from ldap, and one existing encryption cert on token to be retained, and one existing signing cert and one existing ID (authentication) cert to be deleted.

    • certsToAdd: 44,ca1,66,drm1
    • certsToAdd: 33,ca1
      • note: if drm id and key id are specified a full "recovery" will be processed from DRM, whereas if they are missing as specified above, then the (serial#, caID) will be used to search in the existing pkcs11 object on token to retain.
  • enroll with user1a
    • this will
      • generate the certs specified in the TPS profile
      • recover or retain the certs/keys specified in certsToAdd
      • delete all the certs not in "certsToAdd"
NOTE: 
 -  At the minimum, negative cases should not cause any system crash
 -  Ideally, negative cases should not leave token in a "between" state
      (e.g. keys gone on the token but cert did not)
Below is just a few sample negative cases.  It's not exhaustive.

case 4 negative case - ca unreachable

  • replace certsToAdd: 44,ca4,66,drm1 (where ca4 is undefined)

case 5 negative case - drm unreachable

  • replace certsToAdd: 44,ca1,66,drm4 (where drm4 is undefined)

case 6 negative case - keyid not found on drm1

  • replace certsToAdd: 50,ca1,80,drm1 (where keyid 80 not found)
Scenario 2: Unique userid at each enrollment, for one user. In a non-delegation, externalReg environment
  • setup
    • create a user record, "user1b" (this is the same user as "user1a" above, but a different uid for new enrollment)
    • modify the following CS.cfg:
      • externalReg.delegation.enable=false
    • restart the server

case 1: (with the same already-loaded token) enrollment for an IE token, where the Id cert is generated, and the encryption cert is "recovered" from ldap.

  • add tokenType: delegateIE
  • add certsToAdd from user1b with the value:
    • certsToAdd: 33,ca1,55,drm1
  • add tokenCUID: <the token's CUID>
  • Enroll with the token, which will be compared with the tokenCUID (if exists) and if it's a match, it'll be allowed to enroll, if not, it is not allowed. If tokenCUID does not exist then it doesn't care.
  • Enroll with a different token, which should result in failure.
Scenario 3: In a delegation externalReg environment
  • setup
    • create a user record, "executive1"
    • enroll for executive1 (e.g. using userKey profile)
    • create a user record, "delegate1"
    • modify the following CS.cfg:
      • externalReg.delegation.enable=true
      • op.enroll.delegateISEtoken.keyGen.signing.ca.profileId=
        • from caTokenUserSigningKeyEnrollment to caTokenUserDelegateSigningKeyEnrollment
      • op.enroll.delegateISEtoken.keyGen.encryption.ca.profileId=
        • from caTokenUserAuthenticationKeyEnrollment to caTokenUserDelegateAuthenticationKeyEnrollment
    • restart the server

case 1: delegate1 (with a blank token) enrollment for an ISE (Id, Signing, Encryption) token, where the "encryption" cert will be executive1's encryption cert

  • add tokenType: delegateISE
  • add certToAdd: <executive1's cert and key info> (e.g. 202,ca1,89,drm1)
  • add lastname (e.g. Doe)
  • add firstname (e.g. John)
  • add memberID (e.g. 7654321)
  • add catCode (e.g. AC)
  • add mail (e.g. johndoe@EXAMPLE.com)
  • add exec-memberID (e.g. 1234567)
  • add exec-catCode (e.g. AC)
  • add exec-mail (e.g. janeexec@EXAMPLE.com)
  • Once enrolled, authentication (ID) cert and signing cert should be generated, while encryption cert should be taken from executive1. Note the following:
    • subject DN should have the "dnpattern" mapping worked out
    • Subject Alternative Name extension should have the "SANpattern" mapping worked out

Instruction

This section provides instruction on how to setup and configure for this feature. Please ignore the externalReg.prototype.* parameters in CS.cfg.

External Registration (authentication ldap) setup

The premise of enabling the External Registration feature is that an external ldap db is setup for authentication and retrieval of needed information to make decisions on a few things that used to be determined solely by TPS and CA. Such information include:

  • tokenType (the TPS "profile" used for enrollment activities)
  • certificates to be "recovered" onto the token

In addition, the following two additions allow finer control of the subject DN and Subject Alternative name by allowing patterns to be specified in the TPS profile where each $<pattern-token>$ can be replaced by <pattern-token> attributes defined in the ldap record:

  • dnpattern
    • e.g. op.enroll.delegateIEtoken.keyGen.authentication.dnpattern=cn=$auth.firstname$.$auth.lastname$.$auth.edipi$,e=$auth.mail$,o=TMS Org
  • SANpattern
    • e.g. op.enroll.delegateIEtoken.keyGen.authentication.SANpattern=$auth.exec-edipi$.$auth.exec-pcc$@EXAMPLE.com

with the following interested TPS profile params:

  • auth.instance.2.attributes=mail,cn,uid,tokenCUID,tokenType,lastname,firstname,edipi,pcc,exec-edipi,exec-pcc,exec-mail,certsToAdd
    • this is so that during authentication, the interested attributes will be retrieved to fulfil the pattern mappings
    • note that this specification is per authentication instance
  • op.enroll.delegateIEtoken.keyGen.authentication.ca.profileId=caTokenUserDelegateAuthKeyEnrollment
    • this is so that the right ca enrollment profile will be used to cooperate and form the right DN and SAN during issuance
    • note that this specification is per profile

To take advantage of the new features, one needs to determine and setup the following for each of the authentication ldap user record:

  • ldap attribute name for the tokenType (TPS profile):
    • This attribute now determines which TPS profile to use
    • e.g. auth.instance.2.externalReg.tokenTypeAttributeName=tokenType
  • ldap attribute name for the CUID:
    • this attribute, if specified in the ldap user record, will be used to compare and restrict the token used for the action
    • e.g. auth.instance.2.externalReg.cuidAttributeName=tokenCUID
  • ldap attribute name for the field where certs to recover are specified:
    • this attribute, if specified correctly, lists out all the certs to be either retained or recovered onto the token, aside from the certs generated per specified by the tokenType.
    • e.g. auth.instance.2.externalReg.certs.recoverAttributeName=certsToAdd

Here is an example of what an ldap record looks like with the above attribute names:

 dn: uid=test9,ou=People,dc=sjc,dc=redhat,dc=com
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
 objectClass: inetorgperson
 objectClass: extensibleObject
 uid: test9
 cn: test9
 sn: test9
 givenName: test9
 userPassword: {SSHA}1KvkyymH93B7Pd1LxtrCIJSkpBnMZHIjP421oA==
 certstoadd: 200,ca1,88,drm1
 certstoadd: 202,ca1,89,drm1
 certstoadd: 375,ca1
 certstoadd: 376,ca1
 tokenType: externalRegAddToToken
 lastname: Doe
 firstname: JanePaul
 edipi: 123456789
 pcc: AA
 mail: janedoe@EXAMPLE.com
 exec-edipi: 999999999
 exec-pcc: BB
 exec-mail: joeexec@EXAMPLE.com

Note that the "certstoadd" attribute is multi-valued so one can add multiple certs. Also note that there are two types of specification for this attribute:

  • The ones with keyid and drm id (e.g. 200,ca1,88,drm1) specifies which ca to retrieve which serial number (in decimal), and which drm to retrieve which key id (in decimal)
  • The ones with only serial number and ca id (e.g. 375,ca1) specifies which cert that's currently on the token to retain. NOTE: as per design, all certs/keys currently on token, but are not specified in the "certstoadd" attribute are deleted from the token.
TPS Configuration

Now that the ldap server used for external registration authentication is setup, we need to make sure that TPS configuration is configured correctly. First of all, as discussed above, the authentication instance points to the External Registration ldap, and the required attribute names need to be set to match the ones you set up in the ldap server. e.g.:

...
auth.instance.2.authId=ldap3
auth.instance.2.externalReg.tokenTypeAttributeName=tokenType
auth.instance.2.externalReg.cuidAttributeName=tokenCUID
auth.instance.2.externalReg.certs.recoverAttributeName=certsToAdd
...
auth.instance.2.attributes._000=##############################################
auth.instance.2.attributes._001=# For isExternalReg
auth.instance.2.attributes._002=#   attributes will be available as
auth.instance.2.attributes._003=#       $<attribute>$
auth.instance.2.attributes._004=#   attributes example:
auth.instance.2.attributes._005=#mail,cn,uid,edipi,pcc,firstname,lastname,exec-pcc,exec-mail
auth.instance.2.attributes._006=##############################################
auth.instance.2.attributes=mail,cn,uid,tokenCUID,tokenType,lastname,firstname,edipi,pcc,exec-edipi,exec-pcc,exec- mail,certsToAdd
...

the following are the relevant global parameters in the TPS CS.cfg:

externalReg._000=#########################################
externalReg._001=#External Registration
externalReg._002=#    Design: http://pki.fedoraproject.org/wiki/TPS_-_New_Recovery_Option:_External_Registration_DS
externalReg._003=#
externalReg._004=# enable - is user external registration DB enabled?
externalReg._005=# authId - auth id of the user external registration DB
externalReg._006=# delegation.enable - is delegation enabled?
externalReg._007=#
externalReg._008=# 
externalReg._009=# format.loginRequest.enable - login required for format?
externalReg._010=#                   1. requires no login to format
externalReg._011=#                     or
externalReg._012=#                   2. user record does not contain tokenType
externalReg._013=#########################################
externalReg.authId=ldap3
externalReg.default.tokenType=userKey
externalReg.delegation.enable=false
externalReg.enable=false
externalReg.format.loginRequest.enable=false
  • externalReg.enable
    • used to turn on the external registration feature. By default, it is set to false.
  • externalReg.authId
    • Authentication id used to store registration records. By default, it is set to ldap3. Make sure you point it to the auth instance specifically for external registration db
  • externalReg.delegation.enable
    • used to turn on delegation option. By default it is set to false.
  • externalReg.format.loginRequest.enable
    • used to turn on login request for the format operation. By default, it is set to false.

The following are the relevant parameters in each of the default TPS profile (tokenType):

  • delegateIEtoken
    • This example demonstrates a token with ID (Authentication) and Encryption certs where
      • the "ID" (authentication) cert is newly requested with the dnpattern and SANpattern mapped as specified
      • the "encryption" cert is expected to be "recovered", if specified in the ldap registration user record (not specified in the TPS profile)
op.enroll.delegateIEtoken._000=#########################################
op.enroll.delegateIEtoken._001=# Enrollment for externalReg
op.enroll.delegateIEtoken._002=#     ID, Encryption
op.enroll.delegateIEtoken._003=#    where Encryption cert/keys are "recovered"
op.enroll.delegateIEtoken._004=#    is controlled by registration user record
op.enroll.delegateIEtoken._005=#########################################
...
op.enroll.delegateIEtoken.keyGen.authentication.dnpattern=
   cn=$auth.firstname$.$auth.lastname$.$auth.edipi$,e=$auth.mail$,o=TMS Org
op.enroll.delegateIEtoken.keyGen.authentication.SANpattern=$auth.exec-edipi$.$auth.exec-pcc$@EXAMPLE.com
op.enroll.delegateIEtoken.keyGen.authentication.ca.profileId=caTokenUserDelegateAuthKeyEnrollment
...
op.pinReset.delegateIEtoken.*
op.format.delegateIEtoken.*
  • delegateISEtoken -
    • This example demonstrates a token with (Authentication), Signing, and Encryption certs where
      • the "ID" (authentication) cert is newly requested with the dnpattern and SANpattern mapped as specified
      • the "signing" cert is newly requested with the dnpattern and SANpattern mapped as specified
      • the "encryption" cert is expected to be "recovered", if specified in the ldap registration user record (not specified in the TPS profile)
    • note the following errors:
      • op.enroll.delegateISEtoken.keyGen.encryption.ca.profileId=caTokenUserAuthenticationKeyEnrollment, where caTokenUserAuthenticationKeyEnrollment does not exist. caTokenUserEncryptionKeyEnrollment would be more suitable. However, "encrytion" is not turned on in this profile by default)
      • <op.pinReset.delegateISEtoken.* -- this one seems to be missing in default; manually add when needed>
op.enroll.delegateISEtoken._000=#########################################
op.enroll.delegateISEtoken._001=# Enrollment for externalReg
op.enroll.delegateISEtoken._002=#     ID, Signing, Encryption
op.enroll.delegateISEtoken._003=#    where Encryption cert/keys is "recovered"
op.enroll.delegateISEtoken._004=#    is controlled by registration user record
op.enroll.delegateISEtoken._005=#########################################
...
op.enroll.delegateISEtoken.keyGen.signing.dnpattern=cn=
    $auth.firstname$.$auth.lastname$.$auth.edipi$,e=$auth.mail$,o=TMS Org
op.enroll.delegateISEtoken.keyGen.signing.SANpattern=$auth.exec-mail$
op.enroll.delegateISEtoken.keyGen.signing.ca.profileId=caTokenUserDelegateSigningKeyEnrollment
...
op.enroll.delegateISEtoken.keyGen.authentication.dnpattern=
    cn=$auth.firstname$.$auth.lastname$.$auth.edipi$,e=$auth.mail$,o=TMS Org
op.enroll.delegateISEtoken.keyGen.authentication.SANpattern=$auth.exec-edipi$.$auth.exec-pcc$@redhat.com
op.enroll.delegateISEtoken.keyGen.authentication.ca.profileId=caTokenUserDelegateAuthKeyEnrollment
...
op.format.delegateISEtoken.*
  • externalRegAddToToken
    • This example demonstrates a token with no new certs and the profile's purpose is just to "recover" certs/keys onto the token.
    • notice how the authentication must be enabled so that the certstoadd attributes can be retrieved and processed
op.enroll.externalRegAddToToken._000=#########################################
op.enroll.externalRegAddToToken._001=# for externalReg recovering certs/keys only
op.enroll.externalRegAddToToken._002=#########################################
op.enroll.externalRegAddToToken.auth.enable=true
op.enroll.externalRegAddToToken.auth.id=ldap3
...
Misc. Configuration Parameters
NOTE:
    By default, TPS has a an HTTP receive buffer size of 8192. In case of certain errors such as recovering an revoked cert,
    the response by CA is truncated whereby the actual cert is not in the receive buffer.  To fix the issue, one will have to
    increase the buffer size to something larger (perhaps double it).  The default is maintained as is to minimize memory use.
    The parameter to tune the size is the following:
        tps.recvBufSize=16384
    [NOTE: The response from CA has been trimmed to be minimal reply, so in general, the default 8192 bytes buffer should be large enough]
    Also, by default the printing of Buffer is truncated in the tps-debug log.  To print full Buffer's, one can enable it:
        tps.printBufFull=true/false (note that enabling it will increase the debug log a great deal; use with caution)

Supporting multiple keySets for different cards for ExternalReg

Introduction

Currently, in the case of non-externalReg, we use the filtering system that processes a set of mappings such as following to resolve the tokenType (tps profile):

op.enroll.mapping.0.filter.appletMajorVersion=1
op.enroll.mapping.0.filter.appletMinorVersion=
op.enroll.mapping.0.filter.tokenATR=
op.enroll.mapping.0.filter.tokenCUID.end=
op.enroll.mapping.0.filter.tokenCUID.start=
op.enroll.mapping.0.filter.tokenType=userKey
op.enroll.mapping.0.target.tokenType=userKey
op.enroll.mapping.1.filter.appletMajorVersion=
op.enroll.mapping.1.filter.appletMinorVersion=
op.enroll.mapping.1.filter.tokenATR=
op.enroll.mapping.1.filter.tokenCUID.end=
op.enroll.mapping.1.filter.tokenCUID.start=
op.enroll.mapping.1.filter.tokenType=soKey
op.enroll.mapping.1.target.tokenType=soKey
op.enroll.mapping.2.filter.appletMajorVersion=
op.enroll.mapping.2.filter.appletMinorVersion=
op.enroll.mapping.2.filter.tokenATR=
op.enroll.mapping.2.filter.tokenCUID.end=
op.enroll.mapping.2.filter.tokenCUID.start=
op.enroll.mapping.2.filter.tokenType=
op.enroll.mapping.2.target.tokenType=userKey
op.enroll.mapping.order=0,1,2

The keySet is determined by the following configuration:

...
conn.tks1.keySet=defKeySet
...

When multiple keySets are desired, one is expected to define multiple sets of conn.tks entries, e.g.

...
conn.tks2.keySet=jForte
...

TPS Profiles will then point to the "conn.tks" that defines the desired keySet. e.g.

op.enroll.delegateIEtoken.tks.conn=tks1

In the case of externalReg, however, the above filtering system is completely bypassed and instead it retrieves the tokenType from the user record. This presents a challenge when in an environment where multiple vendor cards are supported where keySets are to be different. When a user's ldap record is populated with a set tokenType, it does not know which card will end up doing the enrollment, and therefore keySet cannot be predetermined.

Design Proposal

We can extend the existing GetTokenType filtering system to support resolving keySet. Currently the function signature looks like this:

bool RA_Processor::GetTokenType(const char *prefix, int major_version, int minor_version,
    const char *cuid, const char *msn, NameValueSet *extensions,
    RA_Status &o_status /* out */, const char *&o_tokenType /* out */)

It is cleaner to let externalReg have its own set of filtering config params. So, instead of "op.enroll.", we will replace the prefix with "externalReg."when calling. Since "prefix" is already one of the parameters, it does not require changes to the function as far as prefix is concerned. The following is one way to do it:

  • change the name GetTokenType to something like ProcessMappingFilter
  • in the now ProcessMappingFilter function, we have to make the tokenType-specific code generic enough to work for both tokenType and keySet. Here is a sample function that I changed from the existing GetTokenType(). Note: This is meant for giving an idea of the design only, it is by no means complete or efficient.
/*
* Determine the selection by processing through a set up mapping rules.
* Admin can set up mapping rules in the config file which allow different
* operations depending on the CUID, apple tversion, ATR, etc.
* This method is currently intended for making Token Type or Key Set
* selection.
*/
bool RA_Processor::ProcessMappingFilter(const char *prefix, int major_version, int  minor_version, const char *cuid, const char *msn, NameValueSet *extensions,
   RA_Status &o_status /* out */, const char *&o_selection /* out */)
{
   const char *e_tokenATR = NULL;
   const char *tokenATR = NULL;
   const char *e_tokenType = NULL;
   const char *tokenType = NULL;
   const char *tokenCUIDStart = NULL;
   const char *tokenCUIDEnd = NULL;
   const char *targetSelection = NULL;
   const char *majorVersion = NULL;
   const char *minorVersion = NULL;
   const char *order = NULL;
   char *order_x = NULL;
   const char *mappingId = NULL;
   char configname[256];
   int start_pos = 0, done = 0;
   unsigned int end_pos = 0;
   const char *cuid_x = NULL;
   const char *e_keySet = NULL;
   const char *keySet = NULL;
   const char *FN="RA_Processor::ProcessMappingFilter";
   // just use isExternalReg to decide for now; can refine by adding another
   // config
   PR_snprintf((char *)configname, 256, "externalReg.enable");
   bool isExternalReg = RA::GetConfigStore()->GetConfigAsBool(configname, 0);
   cuid_x = cuid;
   sprintf(configname, "%s.mapping.order", prefix);
   order = RA::GetConfigStore()->GetConfigAsString(configname);
   if (order == NULL) {
       RA::Error(FN, "Token type is not found");
       // should probably add something like STATUS_ERROR_FILTER_ORDER_NOT_FOUND
       o_status = STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND;
       RA::Debug(LL_PER_PDU, FN,
               "cannot find config ", configname);
       return false; /* no mapping found */
   }
   RA::Debug(LL_PER_PDU, FN,
           "Starting:");
   order_x = PL_strdup(order);
   start_pos = 0;
   end_pos = 0;
   done = 0;
   while (1)
   {
       if (done) {
           break;
       }
       end_pos = start_pos;
       while ((end_pos < strlen(order)) && (order_x[end_pos] != ',')) {
           end_pos++;
       }
       }
       if (end_pos < strlen(order)) {
           order_x[end_pos] = '\0';
           done = 0;
       } else {
           done = 1;
       }
       mappingId = &order_x[start_pos];
       RA::Debug(LL_PER_PDU, FN,
               "mappingId='%s'", mappingId);
       start_pos = end_pos + 1;
       if (!isExternalReg) {
           sprintf(configname, "%s.mapping.%s.target.tokenType", prefix,
               mappingId);
       } else {
           sprintf(configname, "%s.mapping.%s.target.keySet", prefix,
               mappingId);
       }
       targetSelection = RA::GetConfigStore()->GetConfigAsString(configname);


       if (targetSelection == NULL) {
           break;
       }
       // isExternalReg should not care what the caller wants for tokenType
       if (!isExternalReg) {
           sprintf(configname, "%s.mapping.%s.filter.tokenType", prefix,
                   mappingId);
           tokenType = RA::GetConfigStore()->GetConfigAsString(configname);
           RA::Debug(LL_PER_PDU, FN,
                   "tokenType: %s",tokenType);
           if (tokenType != NULL && strlen(tokenType) > 0) {
               if (extensions == NULL) {
                   continue; /* mapping not matched, next mapping */
               }
               e_tokenType = extensions->GetValue("tokenType");
               if (e_tokenType == NULL) {
                   continue; /* mapping not matched, next mapping */
               }
               if (strcmp(tokenType, e_tokenType) != 0) {
                   continue; /* mapping not matched, next mapping */
               }
           }
       } else {
           sprintf(configname, "%s.mapping.%s.filter.keySet", prefix,
                   mappingId);
           keySet = RA::GetConfigStore()->GetConfigAsString(configname);
           RA::Debug(LL_PER_PDU, "RA_Processor::ProcessMappingFilter",
                   "keySet: %s",keySet);
           if (keySet != NULL && strlen(keySet) > 0) {
               if (extensions == NULL) {
                   continue; /* mapping not matched, next mapping */
               }
               e_keySet = extensions->GetValue("keySet");
               if (e_keySet == NULL) {
                   continue; /* mapping not matched, next mapping */
               }
               if (strcmp(keySet, e_keySet) != 0) {
                   continue; /* mapping not matched, next mapping */
               }
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.tokenATR", prefix,
               mappingId);
       tokenATR = RA::GetConfigStore()->GetConfigAsString(configname);
       if (tokenATR != NULL && strlen(tokenATR) > 0) {
           if (extensions == NULL) {
               continue; /* mapping not matched, next mapping */
           }
           e_tokenATR = extensions->GetValue("tokenATR");
           if (e_tokenATR == NULL) {
               continue; /* mapping not matched, next mapping */
           }
           if (strcmp(tokenATR, e_tokenATR) != 0) {
               continue; /* mapping not matched, next mapping */
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.tokenCUID.start", prefix, 
               mappingId);
       tokenCUIDStart = RA::GetConfigStore()->GetConfigAsString(configname);
       if (tokenCUIDStart != NULL && strlen(tokenCUIDStart) > 0) {
           if (cuid_x == NULL) {
               continue; /* mapping not matched, next mapping */
           }
           RA::Debug(LL_PER_PDU, FN,
                   "cuid_x=%s tokenCUIDStart=%s %d", cuid_x, tokenCUIDStart,
                   PL_strcasecmp(cuid_x, tokenCUIDStart));
           if(strlen(tokenCUIDStart) != 20)
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDStart: %s",tokenCUIDStart);
               continue;
           }
           char *pend = NULL; 
           strtol((const char *) tokenCUIDStart, &pend, 16);
           if(*pend != '\0')
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDStart: %s",tokenCUIDStart);
               continue;
           }
           if (PL_strcasecmp(cuid_x, tokenCUIDStart) < 0) {
               continue; /* mapping not matched, next mapping */
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.tokenCUID.end", prefix,
               mappingId);
       tokenCUIDEnd = RA::GetConfigStore()->GetConfigAsString(configname);
       if (tokenCUIDEnd != NULL && strlen(tokenCUIDEnd) > 0) {
           if (cuid_x == NULL) {
               continue; /* mapping not matched, next mapping */
           }
           RA::Debug(LL_PER_PDU, FN,
                   "cuid_x=%s tokenCUIDEnd=%s %d", cuid_x, tokenCUIDEnd,
                   PL_strcasecmp(cuid_x, tokenCUIDEnd));
           if(strlen(tokenCUIDEnd) != 20)
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
               continue;
           }
           char *pend = NULL; 
           strtol((const char *) tokenCUIDEnd, &pend, 16);
           if(*pend != '\0')
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
               continue;
           }
           if (PL_strcasecmp(cuid_x, tokenCUIDEnd) > 0) {
               continue; /* mapping not matched, next mapping */
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.tokenCUID.end", prefix,
               mappingId);
       tokenCUIDEnd = RA::GetConfigStore()->GetConfigAsString(configname);
       if (tokenCUIDEnd != NULL && strlen(tokenCUIDEnd) > 0) {
           if (cuid_x == NULL) {
               continue; /* mapping not matched, next mapping */
           }
           RA::Debug(LL_PER_PDU, FN,
                   "cuid_x=%s tokenCUIDEnd=%s %d", cuid_x, tokenCUIDEnd,
                   PL_strcasecmp(cuid_x, tokenCUIDEnd));
           if(strlen(tokenCUIDEnd) != 20)
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
               continue;
           }
           char *pend = NULL; 
           strtol((const char *) tokenCUIDEnd, &pend, 16);
           if(*pend != '\0')
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
               continue;
           }
           if (PL_strcasecmp(cuid_x, tokenCUIDEnd) > 0) {
               continue; /* mapping not matched, next mapping */
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.tokenCUID.end", prefix,
               mappingId);
       tokenCUIDEnd = RA::GetConfigStore()->GetConfigAsString(configname);
       if (tokenCUIDEnd != NULL && strlen(tokenCUIDEnd) > 0) {
           if (cuid_x == NULL) {
               continue; /* mapping not matched, next mapping */
           }
           RA::Debug(LL_PER_PDU, FN,
                   "cuid_x=%s tokenCUIDEnd=%s %d", cuid_x, tokenCUIDEnd,
                   PL_strcasecmp(cuid_x, tokenCUIDEnd));
           if(strlen(tokenCUIDEnd) != 20)
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
               continue;
           }
           char *pend = NULL; 
           strtol((const char *) tokenCUIDEnd, &pend, 16);
           if(*pend != '\0')
           {
               RA::Debug(LL_PER_PDU, FN,
                       "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
               continue;
           }
           if (PL_strcasecmp(cuid_x, tokenCUIDEnd) > 0) {
               continue; /* mapping not matched, next mapping */
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.appletMajorVersion",
               prefix, mappingId);
       majorVersion = RA::GetConfigStore()->GetConfigAsString(configname);
       if (majorVersion != NULL && strlen(majorVersion) > 0) {
           if (major_version != atoi(majorVersion)) {
               continue; /* mapping not matched, next mapping */
           }
       }
       sprintf(configname, "%s.mapping.%s.filter.appletMinorVersion",
               prefix, mappingId);
       minorVersion = RA::GetConfigStore()->GetConfigAsString(configname);
       if (minorVersion != NULL && strlen(minorVersion) > 0) {
           if (minor_version != atoi(minorVersion)) {
               continue; /* mapping not matched, next mapping */
           }
       }
       if( order_x != NULL ) { 
           PL_strfree( order_x );
           order_x = NULL;
       }
       RA::Debug(FN,
                       "Selection is '%s'", targetSelection);
       o_selection = targetSelection;
       return true;
   }


   if( order_x != NULL ) { 
       PL_strfree( order_x );
       order_x = NULL;
   }
   RA::Error(FN, "selection is not found");
   // maybe add a STATUS_ERROR_FILTER_KEYSET_NOT_FOUND for isExternalReg
   o_status = STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND;
   return false;
}
  • in the code where RequestUserId() and AuthenticateUser() are called under isExternalReg, we add a call to the new function ProcessMappingFilter() to resolve the keySet.
  • wherever keySet is retrieved, e.g.
       PR_snprintf((char *)configname, 256, "conn.%s.keySet", connid);
       const char *keySet = RA::GetConfigStore()->GetConfigAsString(configname);

we use the keySet resolved from ProcessMappingFilter()

Testing

Here is an example instruction on how to test this feature, once implemented:

server side

The above sample code did not provide a separate config parameter for this feature, so let's just assume the isExternalReg parameter is the trigger as sample indicated above:

  • make sure ldap is setup, and all config in place and set correctly
  • turn on isExteranalReg
  • add the externalReg.mapping.X.target.Y=Z parameters like the op.enroll. ones, with the following exceptions (instead of tokenType, you do keySet):
    • externalReg.mapping.X.target.keySet=<selected keySet name supported on tks>
    • externalReg.mapping.X.filter.keySet=<selected keySet name supported on tks>
  • make sure you specify a cuid range that your card(s) will fall into
  • restart server

client side

  • if you have all the supported actual physical smart cards, then you can just try to format and enroll
  • if you are testing with tpsclient, you need to add extra extension keySet and leave out the tokenType . e.g.:
    • op=ra_enroll uid=user2a num_threads=1 pwd=netscape new_pin=netscape extensions=keySet=defKeySet
    • also make sure your cuid fall into the cuid range filter that you intend it to fall into

others

It seems this method could be used in the non-externalReg condition too.

Support for Group Certificates

Introduction

There may exist a need for a group of people to share an encryption certificate. This design proposes one way of doing it. The goal is to provide an easy to use mechanism to generate group certs/keys; Members of the group will "recover" them at their next enrollment. Some ideas have been kicked around. One is Auto-generation of "first" token and auto-population of its certsToAdd data to other members of the group. However, it could be problematic. For example:

  • Have to determine who is first when multiple users are enrolling - how to eliminate such window?
  • if we solved issue 1 above, do the other externalReg recovery ops hang and wait, or proceed without recovering any, or fail with error while waiting? How do we know when to do what?
  • maintenance. With the data populated to all members of the group, any change to the group certificate will have to be propagated to all members.
  • etc.

Proposal:

This design proposes:

  • make generating the "group cert" a separate step
  • TPS will provide a per-group entry for a "group certsToAdd" entry. Upon enrollment via externalReg, the enrolling user's personal certsToAdd entry will be concatenated with the group certToAdd entry.
    • This eliminates the need to populate certsToAdd
    • administering the group certsToAdd is much simplier

Assumption

  • The members of the each group has something like "memberOf' ldap attribute in each user record.
  • A user could belong to multiple groups; and multiple "group certsToAdd" coule be applied to each user enrollment

On CA

  • Create a group enrollment profile for encryption certs only. e.g. tokenGroupEncCertProfile.cfg, it is for initiating the enrollment of a group cert that can be later used to "recover" using the externalReg mechanism.
    • we could add a new profilie input to take group name for group enrollment
    • we could add a new authz evaluator to compare the group input to see if its one of the actual authenticating user memberOf list of groups
    • we could make the profile take the group info to be applied in the subject dn

On TPS

  • provide a "group record" in TPS db associated with each group where we could add a group "certsToAdd" attribute
  • modify TPS externalReg code so that during each user enrollment it will pull and "recover" the certs/keys in both
    • group "certsToAdd" (multiple groups allowed)
    • user "certsToAdd"

Advantages

  • Since the group certs/keys info are centralized in one single location, no propagation needed
  • maintenance of the group certs is much easier, not having to touch all user records when group certs are updated
  • if a user belongs to multiple groups, this should work as well

Procedure (flow)

  • A designated member of each group goes through enrollment via the tokenGroupEncCertProfile to enroll a certificate and have its private key escrowed with kra.
  • TPS admin runs ldapmodify to add the certsToAdd attribute with the new group cert and keyid info to the "group record" certsToAdd attribute
  • when a user enrolls his/her token, both user record and group record will be pulled for a concatenated certs to add list in TPS memory for further processing

References