Example Integration CertMgr with HashiCorp
The following example shows how an external CA could be integrated leveraging the manual flow on Domino side. In this integration uses HashiCorp as an example integration. But similar flows would work with other CAs as well. This example shows the principle how an integration could look like
It is leveraging the manual flow. The integration hooks in when the CSR is already created. The CSR itself could be also be created automatically, by
- Creating the document
- Setting the fields for manual flow
- Save the document with
doc.status="O"to submit it - Wait until CertMgr processed the request.
The current example uses the already created CSR. The example script is started from the open TLS Credentials document with the CSR already present.
- Send CSR to HashiCorp
- Get back the certificate
- Submit the TLS Credentials document to let it be processed by CertMgr to merge the certificates.
Note: All integration flows for ACME, Manual and Import perform the following steps automatically:
- Sort and filter certificate chains
- Auto complete the certificate chain with root or intermediate CA certs from Trusted Roots.
This means when the root is not part of the certificates returned, it is auto complected with certificates stored as Trusted Root certstore.nsf.
Main function sending a CSR request to HashiCorp and get back a certificate
- Main function to send the CSR to HashiCorp and return the certificate
- Gets the CSR from document
- Uses the Lotus Script HTTP function to talk to HashiCorp over HTTPS using their API
- Stores certificates in PEM in TLS Credentials document
- Invokes a final server side operation to merge certificates and set status
Notes
The following is for educational purposes only and just shows the general path how to integrate. The functionality stores the the credentials in notes.ini. It is using the main access token. For a production style integration OIDC or other types of authentication should be used to create a vault token with a short lifetime.
Function HashiCorpReqeust (URL As String, Token As String, doc As NotesDocument) As String
Dim Session As New NotesSession
Dim data As NotesJSONNavigator
Dim jsonNav As NotesJSONNavigator
Dim e As NotesJSONElement
Dim a As NotesJSONArray
Dim ePEM As NotesJSONElement
Dim ret As Variant
Dim webRequest As NotesHTTPRequest
Dim CertPEM As String
Dim ChainPEM As String
Dim bUseFullChain As Boolean
Set webRequest = session.createhttprequest()
webRequest.maxredirects= 5
webRequest.PreferJSONNavigator = True
Call webRequest.Setheaderfield ("X-Vault-Token", Token)
Call webRequest.Setheaderfield ("Accept", "application/json")
Set data = session.CreateJSONNavigator ("")
Call data.AppendElement (doc.CSR(0), "csr")
Call data.AppendElement ("240h", "ttl")
Set JsonNav = webrequest.Post (URL, data.Stringify)
If (JsonNav Is Nothing) Then
HashiCorpReqeust = "No JSON returned"
Exit Function
End If
Set e = JsonNav.GetElementByPointer ("/data/certificate")
If (e Is Nothing) Then
HashiCorpReqeust = "No Certificate returned"
Exit Function
End If
' Read the certificate chain
If (bUseFullChain) Then
Set e = JsonNav.GetElementByPointer ("/data/ca_chain")
If Not (e Is Nothing) Then
If e.Type = 2 Then
Set a = e.Value
Set ePEM = a.GetFirstElement()
While Not (ePEM Is Nothing)
chainPEM = chainPEM & ePEM.Value & Chr(10)
Set ePEM = a.GetNextElement
Wend
Else
Print "Unexpected JSON type for ca_chain: " & e.Type
End If
End If
' User only Intermediate
Else
CertPEM = e.Value
Set e = JsonNav.GetElementByPointer ("/data/issuing_ca")
If (Not e Is Nothing) Then
ChainPEM = e.Value
End If
End If
doc.PastedPem = CertPEM + ChainPEM
End Function
Function to search for requests and process them
- Searches for documents in the right status
- Invokes
HashiCorpReqeust()to process the request
Sub HashiCorpCertRequest (Url As String, Token As String)
Dim session As New NotesSession
Dim db As NotesDatabase
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Dim CertStr As String
Dim ErrorText As String
Dim nid As String
Dim ReqNoteUNID As String
Dim count As Integer
Set db = session.CurrentDatabase
Set uidoc = workspace.CurrentDocument
If (uidoc Is Nothing) Then
Messagebox "Please submit request from TLS Credentials document!",48, "CertMgr"
Exit Sub
End If
Set doc = uidoc.Document
If ("" = doc.CSR(0)) Then
Messagebox "Please submit manual request first to create a CSR!",48, "CertMgr"
Exit Sub
End If
uidoc.Editmode = True
ErrorText = HashiCorpReqeust (URL, Token, doc)
If (ErrorText <> "") Then
Messagebox "ERROR: " + ErrorText
Exit Sub
End If
'Set submitted status to import certificate, intermediates and auto complete root
doc.Status = "O"
Call doc.save(True, False)
ReqNoteUNID = doc.Universalid
doc.SaveOptions = "0"
Call uidoc.Reload()
Call uidoc.Close(True)
End Sub
Main function to get URL and Token
Sub Initialize
Dim session As New NotesSession
Dim Token As String
Dim EndPoint As String
EndPoint = session.GetEnvironmentString ("HashiCorp_PKI_URL")
Token = session.GetEnvironmentString ("HashiCorp_PKI_Token")
If ("" = EndPoint) Then
EndPoint = Inputbox ("Specifiy HashiCorp PKI Endpoint URL")
Call session.SetEnvironmentVar ("HashiCorp_PKI_URL", EndPoint)
End If
If ("" = Token) Then
Token = Inputbox ("Specifiy HashiCorp PKI Token")
Call session.SetEnvironmentVar ("HashiCorp_PKI_Token", Token)
End If
Call HashiCorpCertRequest (EndPoint, Token)
End Sub