Skip to content

Commit

Permalink
use resolveContacts instead of the new resolveEmails
Browse files Browse the repository at this point in the history
- The tpp.Connector.resolveContacts() method was refactored so it can be
  user not only for SetPolicy purpose but also for Request Certificate.
- The structs related to Identity were moved from policy package to tpp
  package.
- The tpp.prepareRequest() function was converted in a tpp.Connector
  method and it also was added the management to resolve and set the
  Contacts to the TPP Certificate Request.
  • Loading branch information
marcos-albornoz authored and maelvls committed Jan 30, 2024
1 parent a143708 commit bbaf0ec
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 139 deletions.
10 changes: 5 additions & 5 deletions pkg/certificate/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,20 @@ type Request struct {
ValidityPeriod string //represents the validity of the certificate expressed as an ISO 8601 duration
IssuerHint util.IssuerHint

// ContactEmails is TPP-specific. It allows you to configure an email
// Contact is TPP-specific. It allows you to configure an email
// address to send notifications about the certificate to. When an email is
// used by multiple TPP identities, the first identity found is picked
// arbitrarily.
//
// The scope `configuration` is required. Since ContactEmails works by
// The scope `configuration` is required. Since Contact works by
// searching the emails in the same LDAP or AD as the user attached to the
// token, you must check that you are using a user in that same identity
// provider. ContactEmails doesn't work with the local TPP identities. Using
// ContactEmails requires adding `mail` to the list of fields searched when
// provider. Contact doesn't work with the local TPP identities. Using
// Contact requires adding `mail` to the list of fields searched when
// performing a user search, which can be configured in the Venafi
// Configuration Console by RDP'ing into the TPP VM. This configuration
// cannot be performed directly in the TPP UI.
ContactEmails []string
Contacts []string

// Deprecated: use ValidityDuration instead, this field is ignored if ValidityDuration is set
ValidityHours int
Expand Down
36 changes: 0 additions & 36 deletions pkg/policy/policyStructures.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,42 +155,6 @@ type TppPolicy struct {
WantRenewal *int
}

type BrowseIdentitiesRequest struct {
Filter string
Limit int
IdentityType int
}

type BrowseIdentitiesResponse struct {
Identities []IdentityEntry
}

type IdentitySelfResponse struct {
Identities []IdentityEntry
}

type ValidateIdentityRequest struct {
ID IdentityInformation
}

type ValidateIdentityResponse struct {
ID IdentityEntry
}

type IdentityInformation struct {
PrefixedUniversal string
}

type IdentityEntry struct {
FullName string
Name string
Prefix string
PrefixedName string
PrefixedUniversal string
Type int
Universal string
}

type LockedAttribute struct {
Value string
Locked bool
Expand Down
129 changes: 43 additions & 86 deletions pkg/venafi/tpp/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ func (c *Connector) setCertificateMetadata(metadataRequest metadataSetRequest) (
return result.Locked, nil
}

func prepareRequest(req *certificate.Request, zone string) (tppReq certificateRequest, err error) {
func (c *Connector) prepareRequest(req *certificate.Request, zone string) (tppReq certificateRequest, err error) {
switch req.CsrOrigin {
case certificate.LocalGeneratedCSR, certificate.UserProvidedCSR:
tppReq.PKCS10 = string(req.GetCSR())
Expand Down Expand Up @@ -582,6 +582,20 @@ func prepareRequest(req *certificate.Request, zone string) (tppReq certificateRe
}
}

//resolving Contacts if them were provide
var contacts []IdentityEntry
if req.Contacts != nil {
var err error
prefixedUniversals, err := c.resolvePrefixedUniversals(req.Contacts)
if err != nil {
return tppReq, fmt.Errorf("failed to find contact identities: %w", err)
}
for _, prefixedUniversal := range prefixedUniversals {
contacts = append(contacts, IdentityEntry{PrefixedUniversal: prefixedUniversal})
}
}
tppReq.Contacts = contacts

for name, value := range customFieldsMap {
tppReq.CustomFields = append(tppReq.CustomFields, customField{name, value})
}
Expand Down Expand Up @@ -695,20 +709,10 @@ func (c *Connector) RequestCertificate(req *certificate.Request) (requestID stri
}
}

var contacts []contactReq
if req.ContactEmails != nil {
var err error
contacts, err = c.resolveCertificateRequestContacts(req.ContactEmails)
if err != nil {
return "", fmt.Errorf("failed to find contact identities: %w", err)
}
}

tppCertificateRequest, err := prepareRequest(req, c.zone)
tppCertificateRequest, err := c.prepareRequest(req, c.zone)
if err != nil {
return "", err
}
tppCertificateRequest.Contacts = contacts

statusCode, status, body, err := c.request("POST", urlResourceCertificateRequest, tppCertificateRequest)
if err != nil {
Expand Down Expand Up @@ -778,66 +782,6 @@ func (c *Connector) RequestCertificate(req *certificate.Request) (requestID stri
return
}

// Unlike the resolveContacts func above that only works for usernames, this
// func works with emails. No error is returned when no identity is found.
//
// It is possible that the same email is used by multiple TPP identities, that's
// why multiple identities may be returned.
//
// The scope `configuration` is required. This function doesn't work with the
// local TPP identities. It also requires adding `mail` to the list of fields
// searched when performing a user search, which can be configured in the Venafi
// Configuration Console by RDP'ing into the TPP VM. This configuration cannot
// be performed directly in the TPP UI.
func (c *Connector) resolveEmail(email string) ([]identity, error) {
resp, err := c.browseIdentities(
policy.BrowseIdentitiesRequest{
Filter: email,
IdentityType: policy.AllIdentities,
})
if err != nil {
return nil, fmt.Errorf("failed to find email %s: %w", email, err)
}

var identities []identity
for _, id := range resp.Identities {
identities = append(identities, identity{
Name: id.Name,
FullName: id.FullName,
PrefixedUniversal: id.PrefixedUniversal,
Prefix: id.Prefix,
Universal: id.Universal,
PrefixedName: id.PrefixedName,
Type: id.Type,
})
}

return identities, nil
}

// Meant to be used to fill in the `Contacts` field.
//
// When an email resolves to two identities, the first identity is chosen
// arbitrarily.
func (c *Connector) resolveCertificateRequestContacts(emails []string) ([]contactReq, error) {
var contacts []contactReq
for _, email := range emails {
ids, err := c.resolveEmail(email)
if err != nil {
return nil, err
}
if len(ids) == 0 {
return nil, fmt.Errorf("email %s was not found", email)
}

// Arbitrarily choose the first identity when multiple are found.
contacts = append(contacts, contactReq{
PrefixedUniversal: ids[0].PrefixedUniversal,
})
}
return contacts, nil
}

// SynchronousRequestCertificate It's not supported yet in TPP
func (c *Connector) SynchronousRequestCertificate(_ *certificate.Request) (certificates *certificate.PEMCollection, err error) {
panic("operation is not supported yet")
Expand Down Expand Up @@ -963,8 +907,8 @@ func (c *Connector) retrieveUserNamesForPolicySpecification(policyName string) (
if values != nil {
var users []string
for _, prefixedUniversal := range values {
validateIdentityRequest := policy.ValidateIdentityRequest{
ID: policy.IdentityInformation{
validateIdentityRequest := ValidateIdentityRequest{
ID: IdentityInformation{
PrefixedUniversal: prefixedUniversal,
},
}
Expand All @@ -983,7 +927,7 @@ func (c *Connector) retrieveUserNamesForPolicySpecification(policyName string) (
return nil, nil
}

func (c *Connector) validateIdentity(validateIdentityRequest policy.ValidateIdentityRequest) (*policy.ValidateIdentityResponse, error) {
func (c *Connector) validateIdentity(validateIdentityRequest ValidateIdentityRequest) (*ValidateIdentityResponse, error) {

statusCode, status, body, err := c.request("POST", urlResourceValidateIdentity, validateIdentityRequest)
if err != nil {
Expand Down Expand Up @@ -1245,7 +1189,7 @@ func (c *Connector) SetPolicy(name string, ps *policy.PolicySpecification) (stri
func (c *Connector) setContact(tppPolicy *policy.TppPolicy) (status string, err error) {

if tppPolicy.Contact != nil {
contacts, err := c.resolveContacts(tppPolicy.Contact)
contacts, err := c.resolvePrefixedUniversals(tppPolicy.Contact)
if err != nil {
return "", fmt.Errorf("an error happened trying to resolve the contacts: %w", err)
}
Expand All @@ -1262,15 +1206,28 @@ func (c *Connector) setContact(tppPolicy *policy.TppPolicy) (status string, err
return status, nil
}

func (c *Connector) resolveContacts(contacts []string) ([]string, error) {
var identities []string
uniqueContacts := getUniqueStringSlice(contacts)
func (c *Connector) resolvePrefixedUniversals(filters []string) ([]string, error) {
var prefixedUniversals []string
identities, err := c.resolveIdentities(filters)
if err != nil {
return nil, err
}
for _, identityEntry := range identities {
prefixedUniversals = append(prefixedUniversals, identityEntry.PrefixedUniversal)
}

return prefixedUniversals, nil
}

func (c *Connector) resolveIdentities(filters []string) ([]*IdentityEntry, error) {
var identities []*IdentityEntry
uniqueContacts := getUniqueStringSlice(filters)
for _, contact := range uniqueContacts {
identity, err := c.getIdentity(contact)
identityEntry, err := c.getIdentity(contact)
if err != nil {
return nil, err
}
identities = append(identities, identity.PrefixedUniversal)
identities = append(identities, identityEntry)
}

return identities, nil
Expand All @@ -1288,12 +1245,12 @@ func getUniqueStringSlice(stringSlice []string) []string {
return list
}

func (c *Connector) getIdentity(userName string) (*policy.IdentityEntry, error) {
func (c *Connector) getIdentity(userName string) (*IdentityEntry, error) {
if userName == "" {
return nil, fmt.Errorf("identity string cannot be null")
}

req := policy.BrowseIdentitiesRequest{
req := BrowseIdentitiesRequest{
Filter: userName,
Limit: 2,
IdentityType: policy.AllIdentities,
Expand All @@ -1307,8 +1264,8 @@ func (c *Connector) getIdentity(userName string) (*policy.IdentityEntry, error)
return c.getIdentityMatching(resp.Identities, userName)
}

func (c *Connector) getIdentityMatching(identities []policy.IdentityEntry, identityName string) (*policy.IdentityEntry, error) {
var identityEntryMatching *policy.IdentityEntry
func (c *Connector) getIdentityMatching(identities []IdentityEntry, identityName string) (*IdentityEntry, error) {
var identityEntryMatching *IdentityEntry

if len(identities) > 0 {
for i := range identities {
Expand All @@ -1328,7 +1285,7 @@ func (c *Connector) getIdentityMatching(identities []policy.IdentityEntry, ident
}
}

func (c *Connector) browseIdentities(browseReq policy.BrowseIdentitiesRequest) (*policy.BrowseIdentitiesResponse, error) {
func (c *Connector) browseIdentities(browseReq BrowseIdentitiesRequest) (*BrowseIdentitiesResponse, error) {

statusCode, status, body, err := c.request("POST", urlResourceBrowseIdentities, browseReq)
if err != nil {
Expand Down
55 changes: 43 additions & 12 deletions pkg/venafi/tpp/tpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (

"github.com/Venafi/vcert/v5/pkg/certificate"
"github.com/Venafi/vcert/v5/pkg/endpoint"
"github.com/Venafi/vcert/v5/pkg/policy"
)

const defaultKeySize = 2048
Expand Down Expand Up @@ -73,7 +72,7 @@ type certificateRequest struct {
State string `json:",omitempty"`
Country string `json:",omitempty"`
SubjectAltNames []sanItem `json:",omitempty"`
Contacts []contactReq `json:",omitempty"`
Contacts []IdentityEntry `json:",omitempty"`
CASpecificAttributes []nameValuePair `json:",omitempty"`
Origin string `json:",omitempty"`
PKCS10 string `json:",omitempty"`
Expand Down Expand Up @@ -153,6 +152,42 @@ type certificateResetResponse struct {
Error string `json:"Error"`
}

type BrowseIdentitiesRequest struct {
Filter string
Limit int
IdentityType int
}

type BrowseIdentitiesResponse struct {
Identities []IdentityEntry
}

type IdentitySelfResponse struct {
Identities []IdentityEntry
}

type ValidateIdentityRequest struct {
ID IdentityInformation
}

type ValidateIdentityResponse struct {
ID IdentityEntry
}

type IdentityInformation struct {
PrefixedUniversal string
}

type IdentityEntry struct {
FullName string `json:",omitempty"`
Name string `json:",omitempty"`
Prefix string `json:",omitempty"`
PrefixedName string `json:",omitempty"`
PrefixedUniversal string `json:",omitempty"`
Type int `json:",omitempty"`
Universal string `json:",omitempty"`
}

type sanItem struct {
Type int `json:""`
Name string `json:""`
Expand Down Expand Up @@ -346,10 +381,6 @@ type identity struct {
Universal string `json:"Universal"`
}

type contactReq struct {
PrefixedUniversal string `json:"PrefixedUniversal"`
}

type systemStatusVersionResponse string

type urlResource string
Expand Down Expand Up @@ -721,8 +752,8 @@ func newPEMCollectionFromResponse(base64Response string, chainOrder certificate.
return nil, nil
}

func parseBrowseIdentitiesResult(httpStatusCode int, httpStatus string, body []byte) (policy.BrowseIdentitiesResponse, error) {
var browseIdentitiesResponse policy.BrowseIdentitiesResponse
func parseBrowseIdentitiesResult(httpStatusCode int, httpStatus string, body []byte) (BrowseIdentitiesResponse, error) {
var browseIdentitiesResponse BrowseIdentitiesResponse
switch httpStatusCode {
case http.StatusOK, http.StatusAccepted:
browseIdentitiesResponse, err := parseBrowseIdentitiesData(body)
Expand All @@ -735,13 +766,13 @@ func parseBrowseIdentitiesResult(httpStatusCode int, httpStatus string, body []b
}
}

func parseBrowseIdentitiesData(b []byte) (data policy.BrowseIdentitiesResponse, err error) {
func parseBrowseIdentitiesData(b []byte) (data BrowseIdentitiesResponse, err error) {
err = json.Unmarshal(b, &data)
return
}

func parseValidateIdentityResponse(httpStatusCode int, httpStatus string, body []byte) (policy.ValidateIdentityResponse, error) {
var validateIdentityResponse policy.ValidateIdentityResponse
func parseValidateIdentityResponse(httpStatusCode int, httpStatus string, body []byte) (ValidateIdentityResponse, error) {
var validateIdentityResponse ValidateIdentityResponse
switch httpStatusCode {
case http.StatusOK, http.StatusAccepted:
validateIdentityResponse, err := parseValidateIdentityData(body)
Expand All @@ -754,7 +785,7 @@ func parseValidateIdentityResponse(httpStatusCode int, httpStatus string, body [
}
}

func parseValidateIdentityData(b []byte) (data policy.ValidateIdentityResponse, err error) {
func parseValidateIdentityData(b []byte) (data ValidateIdentityResponse, err error) {
err = json.Unmarshal(b, &data)
return
}
Expand Down

0 comments on commit bbaf0ec

Please sign in to comment.