1package models 2 3import ( 4 "crypto/x509" 5 "errors" 6 "fmt" 7 "net" 8 "strings" 9) 10 11// NewPCFCertificateFromx509 converts a x509 certificate to a valid, well-formed PCF certificate, 12// erroring if this isn't possible. 13func NewPCFCertificateFromx509(certificate *x509.Certificate) (*PCFCertificate, error) { 14 if len(certificate.IPAddresses) != 1 { 15 return nil, fmt.Errorf("valid PCF certs have one IP address, but this has %s", certificate.IPAddresses) 16 } 17 18 pcfCert := &PCFCertificate{ 19 InstanceID: certificate.Subject.CommonName, 20 IPAddress: certificate.IPAddresses[0], 21 } 22 23 spaces := 0 24 orgs := 0 25 apps := 0 26 for _, ou := range certificate.Subject.OrganizationalUnit { 27 if strings.HasPrefix(ou, "space:") { 28 pcfCert.SpaceID = strings.Split(ou, "space:")[1] 29 spaces++ 30 continue 31 } 32 if strings.HasPrefix(ou, "organization:") { 33 pcfCert.OrgID = strings.Split(ou, "organization:")[1] 34 orgs++ 35 continue 36 } 37 if strings.HasPrefix(ou, "app:") { 38 pcfCert.AppID = strings.Split(ou, "app:")[1] 39 apps++ 40 continue 41 } 42 } 43 if spaces > 1 { 44 return nil, fmt.Errorf("expected 1 space but received %d", spaces) 45 } 46 if orgs > 1 { 47 return nil, fmt.Errorf("expected 1 org but received %d", orgs) 48 } 49 if apps > 1 { 50 return nil, fmt.Errorf("expected 1 app but received %d", apps) 51 } 52 if err := pcfCert.validate(); err != nil { 53 return nil, err 54 } 55 return pcfCert, nil 56} 57 58// NewPCFCertificateFromx509 converts the given fields to a valid, well-formed PCF certificate, 59// erroring if this isn't possible. 60func NewPCFCertificate(instanceID, orgID, spaceID, appID, ipAddress string) (*PCFCertificate, error) { 61 pcfCert := &PCFCertificate{ 62 InstanceID: instanceID, 63 OrgID: orgID, 64 SpaceID: spaceID, 65 AppID: appID, 66 IPAddress: net.ParseIP(ipAddress), 67 } 68 if err := pcfCert.validate(); err != nil { 69 return nil, err 70 } 71 return pcfCert, nil 72} 73 74// PCFCertificate isn't intended to be instantiated directly; but rather through one of the New 75// methods, which contain logic validating that the expected fields exist. 76type PCFCertificate struct { 77 InstanceID, OrgID, SpaceID, AppID string 78 IPAddress net.IP 79} 80 81func (c *PCFCertificate) validate() error { 82 if c.InstanceID == "" { 83 return errors.New("no instance ID on given certificate") 84 } 85 if c.AppID == "" { 86 return errors.New("no app ID on given certificate") 87 } 88 if c.OrgID == "" { 89 return errors.New("no org ID on given certificate") 90 } 91 if c.SpaceID == "" { 92 return errors.New("no space ID on given certificate") 93 } 94 if c.IPAddress.IsUnspecified() { 95 return errors.New("ip address is unspecified") 96 } 97 return nil 98} 99