Skip to main content link. Accesskey S
  • HCL Logo
  • HCL Notes and Domino wiki
  • THIS WIKI IS READ-ONLY. Individual names altered for privacy purposes.
  • HCL Forums and Blogs
  • Home
  • Product Documentation
  • Community Articles
  • Learning Center
  • API Documentation
Search
Community Articles > Designer agents > IBM Lotus Notes ID Vault Database Scanner: An overview
  • Share Show Menu▼
  • Subscribe Show Menu▼

Recent articles by this author

IBM Lotus Notes ID Vault Database Scanner: An overview

Learn how to use the Vault Database Scanner tool, which scans the IBM Lotus Notes ID Vault database and Lotus Domino server directory and reports missing Notes ID files for users.

Using a Notes.ini file's automatic backup utility

Learn how to set up a Notes.ini backup utility for IBM Lotus Notes and Domino, which takes the backup of the Notes.ini file, whenever there was a change on the file. The backup copy would be the copy of the Notes.ini file, without that change.
Community articleIBM Lotus Notes ID Vault Database Scanner: An overview
Added by ~Keiko Asakibergakoi | Edited by ~Tate Ekfreeteroopsi on July 17, 2015 | Version 12
  • Actions Show Menu▼
expanded Abstract
collapsed Abstract
Learn how to use the Vault Database Scanner tool, which scans the IBM Lotus Notes ID Vault database and Lotus Domino server directory and reports missing Notes ID files for users.
ShowTable of Contents
HideTable of Contents
  • 1 Introduction
  • 2 Get the database
  • 3 Understanding the Vault Database Scanner
    • 3.1 Create Configuration Document agent
    • 3.2 scanVault agent
  • 4 Running the scanVault agent
  • 5 Conclusion
  • 6 Resources
  • 7 About the author

Introduction


The IBM® Lotus® Notes® ID Vault feature helps users by automatically collecting user ID files, so as to have centralized ID management in Lotus Domino®. Using the ID Vault, we can reset passwords and recover IDs easily; moreover, the ID Vault has removed the need to visit desktops for ID management.

In some cases, however, there may instances when the user ID files might not be collected due to incorrect configurations or some flaws from the administration end. Administrators must then manually check the Vault database to determine whether it contains IDs for all the current users. This can be an easy task, if there a only a few users; however, it can be cumbersome to find missing IDs when there are many users.

To overcome this we propose a solution called the Vault Database Scanner, which can automatically scan the Vault database and the Names.nsf file and report IDs missing from the Vault database.

The tool has been developed as a plug-and-play type in that you don't need to configure the tool to make it operational; all you need to do is deploy the tool and run the desired agent.

Get the database

Please note that since I could not upload a zip or ntf file, you need to get the attachment I was able to upload: VaultScanner-v1r4.zip.pdf.  Just download it (it's at the bottom of the article in the attachments section) and remove the pdf extension to get the zip which you can expand.

Note that the latest version, 1.5, uses Rich text for the result lists, and outputs only 1 document per run of the agent. Caveat: results from 1.4 displayed in 1.5 do not display nicely.

Understanding the Vault Database Scanner


The database contains one LotusScript agent called "scanVault". The scanVault agent is housed in the LotusScript script library 'libVaultSCanner' and consists of two main functions called getVaultDocuments and compareNABVaultDB.  It was rewritten using Lists and objects instead of temporary documents because it was unable to perform with more than a couple records in the NAB or ID Vault. 

Create Configuration Document agent

This agent is obsolete. The scanVault agent looks for a Public AddressBook in the current NotesSession, and uses that to look for the ID Vault config documents. So as long as you are online with a Domino server and can read the NAB and ID Vault you should be OK.

scanVault agent


The scanVault agent consists of two main functions called getVaultDocuments and compareNABVaultDB.

The getVaultDocuments function gets the ID Vault configuration by creating an object of custom class clVaults.

The New subroutine in the class clVaults uses the current NotesSession object property AddressBooks to find a Public AddressBook, reads the ID Vault configuration from it, and creates a list of objects of custom class clVaultConfig.  The clVaultConfig objects know how to read the ID vault configuration documents and extract the server name and path to the ID Vault. The requirement that the VauitScanner application needs to be on a server has been removed by removing the leading / of the ID Vault path. Note that the current implementation just uses the first server from the list of servers in the ID vault configuration document.  For complex environments, this could be enhanced by scanning the list of servers to see if the server which we are using for the NAB is somehwhere in the list, assuming that the current Public directory provider is a server near us.

Once the ID Vault configuration has been read, getVaultDocuments creates an object to hold the names in the IDVault(s), and opens all the individual Vault databases, reads the list of active IDs and the list of inactive IDs.  The only field read is the field IDOwner, which contains one or more names.  The first name is taken to be the main one, and the others are taken to be aliases and marked as such in the list of IDs.

The routine saves and prints a line of statistics at the end.

Listing 1. Code for getVaultDocuments


Const IT_IDVaultPath = "VTPath"


Const IT_VaultServerList = "VaultServerList"

Const VW_IDVAULT = "IDVaults"

Const FRM_Result = "frmresult"

Const IT_Form = "Form"

Const IT_MissingActive = "fldmissingvault"

Const IT_Inactive = "fldVaultInactive"

Const IT_MissingBoth = "fldVaultMissingBoth"

Dim s As NotesSession


Dim db As NotesDatabase

Dim docResult as NotesDocument


Dim vw As NotesView

Dim dbNAB As NotesDatabase

Dim vwNAB As NotesView

Dim vaults As clVaults

Dim IDs As clVaultIDs' clVaults' clVaultConfig' clVaultID ' clVaults

%REM


    Class clVaultConfig

    Description: helper class containing vault stuff

%END REM

Class clVaultConfig

    Public Path As String

    Public Server As String

    

    %REM

        Sub New

        Description: parse a vault doc from the NAB into a useable object

    %END REM

    Sub New(doc As NotesDocument)

        Path = Replace(doc.GetItemValue(IT_IDVaultPath)(0), "\", "/")

        If Left$(Path, 1) = "/" Then

            path = Mid$(path, 2)

        End If

        ' TODO try to match server with current server

        Server = doc.GetItemValue(IT_VaultServerList)(0) ' just use first server

    End Sub ' New

End Class 

%REM


    Class clVaultID

    Description: helper class containing vault ID stuff

%END REM

Class clVaultID

    Public IDOwner As String

    Public isAlias As Boolean

    Public mainName As String ' abbreviated main name for which this name is an alias

End Class 

%REM


    Class clVaults

    Description: Comments for Class

%END REM

Class clVaults

    Public Vaults List As clVaultConfig

    Public numVaults As Long

    

    %REM

        Sub New

        Description: Comments for Sub

    %END REM

    Sub New

        Dim docNAB As NotesDocument

        

        Set dbNAB = Nothing

        numVaults = 0

        Set s = New NotesSession

        If Not IsEmpty(s.AddressBooks) Then


            ForAll vDbNAB In s.AddressBooks

                If vDbNAB.IsPublicAddressBook Then

                    Call vDbNAB.Open("", "")

                    If vDbNAB.IsOpen Then

                        Set dbNAB = vDbNAB

                        Exit ForAll

                    Else

                        MsgBox "Unable to open the Public addressBook found in NotesSession, make sure you are in an online session"

                        Exit Sub

                    End If

                End If

            End ForAll

        End If


        If dbNAB Is Nothing Then

            MsgBox "No Public addressBook found in NotesSession, make sure you are in an online session"

            Exit Sub

        End If

        

        Set vwNAB = dbNAB.GetView(VW_IDVAULT)

        If Not vwNAB Is Nothing Then

            Set docNAB = vwNAB.GetFirstDocument

            

            Do Until docNAB Is Nothing

                numVaults  = numVaults + 1

                Set vaults(numVaults) = New clVaultConfig(docNAB)

                

                Set docNAB = vwNAB.GetNextDocument(docNAB)

            Loop

        End If

    End Sub

End Class 

%REM


    Class clVaultIDs

    Description: container to handle VaultIDs

%END REM

Class clVaultIDs

    Public IDs List As clVaultID

    Public inactiveIDs List As clVaultID

    Public IDsNoAliases List As String

    Public Aliases List As String

    Public numIDs As Long

    Public numInactiveIDs As Long

    Public numActiveIDs As Long

    Public numMainIDs As Long

    Public statsGetVault As String

    Public statsCompare As String

    

    %REM

        Function addID

        Description: parse an IDVault viewentry

    %END REM

    Public Function addID(ve As NotesViewEntry) As Boolean

        ' expects a notesViewEntry from the view 'Vault Users' in an ID Vault db

        Dim v ' will contain 1 or more Abbreviated names

        Dim isAlias As Boolean

        Dim nmMain$

        addID = False

        v =  ve.Columnvalues(0) ' can be multivalue

        numActiveIDs = numActiveIDs + 1

        isAlias = False

        If IsArray(v) Then

            addID = True

            ForAll vNam In v

                If Not isAlias Then nmMain = vNam

                ' if one of the calls returns false, it will make addID false, signaling a failure

                addID = addID And addName(IDs, CStr(vNam), isAlias, nmMain)

                isAlias = True

            End ForAll

        Else

            addID = addName(IDs, CStr(v), False, "")

        End If

    End Function ' addID

    

    %REM

        Function addName

        Description: adds a name if not already in the list

    %END REM

    Function addName(theList List As clVaultID, abbName$, isAlias As Boolean, mainName$) As Boolean

        Dim tID As clVaultID

        Dim nm As NotesName

        Dim lName As String

        addName = False

        lName = LCase$(abbname)

        If Not IsElement(theList(lName)) Then

            numIDs = numIDs + 1

            Set nm = New NotesName(lName)

            Set tID = New clVaultID

            Set theList(lName) = tID

            tID.IDOwner = nm.Canonical

            tID.isAlias = isAlias

            If isAlias Then

                tID.mainName = mainName

                If IsElement(Aliases(lName)) Then

                    Print "Skipping add to list of Aliases for " + abbName + ", already in the list"

                Else

                    Aliases(lName) = mainName

                End If

            Else

                numMainIDs = numMainIDs + 1

                tID.mainName = abbName

                If Not IsElement(IDsNoAliases(lName)) Then

                    IDsNoAliases(lName) = abbName

                Else

                    Print "Skipping add to list of NoAlias for " + abbName + ", already in the list"

                End If

            End If

        Else

            Print "Skipping add for " + abbName + ", already in the list"

            

            Exit Function

        End If

        addName = True

    End Function ' addName

    

    %REM

        Function addIDinactive

        Description: parse an inactive IDVault viewentry

    %END REM

    Public Function addIDinactive(ve As NotesViewEntry) As Boolean

        ' expects a notesViewEntry from the view 'Inactive User IDs' in an ID Vault db

        Dim v ' will contain 1 or more Abbreviated names

        Dim isAlias As Boolean

        Dim nmMain As String

        addIDinactive = False

        v =  ve.Columnvalues(1) ' can be multivalue

        numInactiveIDs = numInactiveIDs + 1

        isAlias = False

        If IsArray(v) Then

            addIDinactive = True

            ForAll vNam In v

                If Not isAlias Then nmMain = vNam

                ' if one of the calls returns false, it will make addIDinactive false, signaling a failure

                addIDinactive = addIDinactive And addName(inactiveIDs, CStr(vNam), isAlias, nmMain)

                isAlias = True

            End ForAll

        Else

            addIDinactive = addName(inactiveIDs, CStr(v), False, "")

        End If

    End Function ' addIDinactive

    

End Class ' clVaultIDs

%REM


    Function getVaultDocuments

    Description: Uses the NotesSession to get a handle on the Public NAB

    gets the ID Vault config from the NAB, and reads the active users from the ID Vaults it finds

    returns True if no errors were encountered 

%END REM

Function getVaultDocuments As Boolean

    getVaultDocuments = False

    Dim i As Long

    Dim dbVault As NotesDatabase

    Dim vwVault As NotesView

    Dim OpenVaultDoc As NotesDocument

    Dim vec As NotesViewEntryCollection

    Dim ve As NotesViewEntry

    Dim vt As clVaultConfig

        

    Set vaults = New clVaults

    If vaults.numVaults = 0 Then

        MsgBox "No vaults found"

        Exit Function

    End If

    Set IDs = New clVaultIDs

    ' read active and inactive users fom vaults

    For i = 1 To vaults.numVaults

        Set vt = vaults.Vaults(i)

        Set dbVault = s.GetDatabase(vt.Server, vt.Path)

        If Not dbVault.IsOpen Then

            MsgBox "Could not open vault db: " + vt.Server +  " !! " + vt.Path

        Else

            ' read active users

            Set vwVault = dbVault.getView("Vault Users")

            Set vec = vwVault.Allentries

            Set ve = vec.GetFirstEntry

            Do Until ve Is Nothing

                If Not IDs.addID(ve) Then

                    MsgBox "Aborting, an error occurred while adding a name from the ID Vault"

                    Exit Function

                End If

                Set ve = vec.GetNextEntry(ve)

            Loop

            ' read inactive users

            Set vwVault = dbVault.getView("Inactive User Ids")

            Set vec = vwVault.Allentries

            Set ve = vec.GetFirstEntry

            Do Until ve Is Nothing

                If Not IDs.addIDinactive(ve) Then

                    MsgBox "Aborting, an error occurred while adding a name from the ID Vault"

                    Exit Function

                End If

                Set ve = vec.GetNextEntry(ve)

            Loop

        End If

    Next i

    ' print statistics

    IDs.statsGetVault = "Found " & IDs.numActiveIDs & " active IDs, " & IDs.numInactiveIDs & " inactive IDs, " & IDs.numMainIDs & " IDs with " & IDs.numIDs & " names"

    Print IDs.statsGetVault

    getVaultDocuments = True

End Function ' getVaultDocuments



The compareNABVaultDB function compares the users in the Address book with the list of IDs obtained from the ID Vault(s). It reports any user who doesn't have a Person entry in the list of active usersand of the persons who obnly have an inactive ID (see listing 2). Because the report might grow too long, the output is split up with another custom class so repetitive and error prone code is avoided.

The routine saves and prints a line of statistics at the end. The statistics are also saved in the results document(s) and used for display in the view.

Listing 2. Code for compareNABVaultDB function


%REM


    Sub compareNABVaultDB

    Description: Comments for Function

%END REM

Sub compareNABVaultDB

    Dim docNAB As NotesDocument

    Dim docResult As NotesDocument

    Dim personDocName As String

    Dim nm As NotesName

    Dim notInActiveUsers List As String

    Dim inInactiveUsers List As String

    Dim notInVault List As String

    Dim numNotActive As Long

    Dim numNotInVault As Long

    Dim numInactive As Long

    Dim numActive As Long

    Dim numNAB As Long

    Dim isFinished As Boolean

    Dim v As Variant

    Dim isActive As Boolean

    Dim isInactive As Boolean

    Dim personMain As String

    Dim multipleCanonical As Boolean

    Dim foundCanonical As Boolean

    Dim nmMain As NotesName

    Dim rtInactive As NotesRichTextItem


    Dim rtBoth As NotesRichTextItem

    Dim rtVault As NotesRichTextItem

    ' scan people view, and check with ID Vault entries


    Set vwNAB = dbNAB.Getview("People")

    Set docNAB = vwNab.GetFirstDocument

    Do Until docNAB Is Nothing

        If docNab.IsValid And docNab.Size > 0 And Not docNab.IsDeleted Then

            numNAB = numNAB + 1

            v = docNAB.FullName

            isActive = False

            isInactive = False

            multipleCanonical = False

            foundCanonical = False

            personMain = ""

            Set nmMain = New NotesName(v(0))

                        

            ForAll vName In v

                Set nm = New NotesName(vName)

                

                If LCase$(Left$(vName, 3)) = "cn=" Then

                    If foundCanonical Then

                        multipleCanonical = True

                    Else

                        Set nmMain = nm

                        foundCanonical = True

                    End If

                End If

                persondocname = LCase$(nm.Abbreviated)

                If IsElement(ids.ids(persondocname)) Then ' person doc but no active ID

                    isActive = True

                    Exit ForAll ' done, person has an active ID

                ElseIf IsElement(ids.inactiveIDs(persondocname)) Then ' person doc with inactive ID

                    If Not isInactive Then ' only if we did not already find an inactive ID for this person

                        numInactive = numInactive + 1

                        inInactiveUsers(numInactive) = ids.inactiveIDs(persondocname).mainName

                        isInactive = True

                    End If

                    ' don't exit the loop, this may be an old name

                End If

            End ForAll

            If isActive Then 'no active ID found for any of the names

                numActive = numActive + 1

                If isInactive Then ' found a person with an Active ID for which one of the aliases has an inactive ID

                    ' => remove false negative

                    Erase inInactiveUsers(numInactive)

                    numInactive = numInactive - 1

                End If

            Else

                personMain = nmMain.Abbreviated

                numNotActive = numNotActive + 1

                notInActiveUsers(numNotActive) = personMain

                If isInactive Then

                    ' already done above

                Else ' person doc also without inactive ID

                    numNotInVault = numNotInVault + 1

                    notInVault(numNotInVault) = personMain

                End If

            End If

        End If

        Set docNAB = vwNAB.GetNextDocument(docNAB)

    Loop

    ' statistics


    IDs.statsCompare = "Found " & numNAB & " person documents, of which " & numActive & " have Active IDs, " & numInactive & " have inactive IDs, " & numNotInVault & " have no record in the IDVault"

    Print IDs.statsCompare

    

    ' output results

    Call docResult.ReplaceItemValue(IT_Form, FRM_Result)

    Call docResult.Replaceitemvalue("statsGetVault", IDs.statsGetVault)

    Call docResult.Replaceitemvalue("statsCompare", IDs.statsCompare)

    

    Set rtInactive = docResult.CreateRichTextItem(IT_Inactive)

    Set rtBoth = docResult.CreateRichTextItem(IT_MissingBoth)

    Set rtVault = docResult.CreateRichTextItem(IT_MissingActive)

    Call dumpListToRT(inInactiveUsers, rtInactive)

    Call dumpListToRT(notInVault, rtBoth)

    Call dumpListToRT(notInActiveUsers, rtVault)

End Sub ' compareNABVaultDB




Listing 3 shows the main Script in the agent.

Listing 3. Script main

%REM


    Sub agScan

    Description: agent that compares

%END REM

Public Sub agScan

    Dim tm As Single

    tm = Timer

    Dim s As New NotesSession

    Set db = s.CurrentDatabase

    Set docResult = db.CreateDocument

    If getVaultDocuments Then

        Call compareNABVaultDB

    End If

    Call docResult.ReplaceItemValue(IT_runTime, Round(Timer-tm, 2))

    Call docResult.Save(True, True)

    Print "scanVaults took"; Round(Timer-tm, 2); "seconds";

End Sub ' agScan

 




Running the scanVault agent


You can run the agent in any of the following three methods:

Method 1
1. Open the Vault Database Scanner on the Notes Client, and click expand IDVault Scanner, and click Scan ID Vault (see figure 1).

 

Figure 1. ID Vault Database Scanner

 

  • Upon successful creation of the list of ID Vault IDs, the agent will print an intermediate result (see figure 3)
  • When the agent is finished, you can find statistics in the status bar.  The numbers about the ID vault and comparison are also stored in the result document.  The execution speed is only printed to the status bar. (see figure 4)

Figure 3. Intermediate result

Figure 4. Statistics





Conclusion


The ID Vault Database Scanner automatically scans the Vault database and the Names.nsf file and reports IDs missing from the Vault database. This article provides the code for this tool and explains its architecture, so that you can deploy and configure the tool in your production environment and enjoy the full benefit of its automation.

Resources


developerworks® Lotus Notes and Domino product page:
http://www.ibm.com/developerworks/lotus/products/notesdomino/

Lotus Notes product documentation:
http://www.ibm.com/developerworks/lotus/documentation/notes/

Notes/Domino 8 Forum:
http://www-10.lotus.com/ldd/nd8forum.nsf?OpenDatabase

Notes/Domino 8.5 Forum:
http://www-10.lotus.com/ldd/nd85forum.nsf?OpenDatabase

Notes/Domino 9 Forum:
http://www-10.lotus.com/ldd/ndseforum.nsf?OpenDatabase

Bill Buchan's presentations: read them and learn!

http://www.billbuchan.com/presentations/

Nathan Freeman's Stuff: sometime loopy, frequently brilliant!

https://nathantfreeman.wordpress.com/


About the author


Lars Berntrop-Bos is a Senior Domino Developer and Administrator at Zeeman. This work was done entirely in his own time. He works on everything related to Domino and Notes. You can reach him at lars@planet.nl

Very useful suggestions were made by Nathan T Freeman of Red Pill Development.  And of course credits need to go to Bill Buchan of HADSL, the artist formerly known as 'Wild Bill', for teaching how to properly code LotusScript. Inspired by Gregg Eldredd by publishing a link to the original version of this article http://geldred.com/2015/07/13/not-my-code-advice-on-speeding-up-a-domino-application/ which was a total FUBAR. Please employ an adult filter when looking up the acronym.


  • Actions Show Menu▼


expanded Attachments (2)
collapsed Attachments (2)
Edit the article to add or modify attachments.
File TypeSizeFile NameCreated OnDelete file
application/pdf 171 KB VaultScanner-v1r4.zip.pdf 7/17/15, 7:17 PM
application/pdf 167 KB IDVaultScanner-v1r5.zip.pdf 7/17/15, 8:43 PM
expanded Versions (1)
collapsed Versions (1)
Version Comparison     
VersionDateChanged by              Summary of changes
This version (12)Jul 17, 2015, 9:24:06 PM~Tate Ekfreeteroopsi  cleaned up code in article
expanded Comments (0)
collapsed Comments (0)
Copy and paste this wiki markup to link to this article from another article in this wiki.
Go ElsewhereStay ConnectedAbout
  • HCL Software
  • HCL Digital Solutions community
  • HCL Software support
  • BlogsDigital Solutions blog
  • Community LinkHCL Software forums and blogs
  • About HCL Software
  • Privacy
  • Accessibility