1package models 2 3import ( 4 "crypto/x509" 5 "errors" 6 "fmt" 7 "net" 8 "strings" 9) 10 11// NewCFCertificateFromx509 converts a x509 certificate to a valid, well-formed CF certificate, 12// erroring if this isn't possible. 13func NewCFCertificateFromx509(certificate *x509.Certificate) (*CFCertificate, error) { 14 if len(certificate.IPAddresses) != 1 { 15 return nil, fmt.Errorf("valid CF certs have one IP address, but this has %s", certificate.IPAddresses) 16 } 17 18 cfCert := &CFCertificate{ 19 InstanceID: certificate.Subject.CommonName, 20 IPAddress: certificate.IPAddresses[0].String(), 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 cfCert.SpaceID = strings.Split(ou, "space:")[1] 29 spaces++ 30 continue 31 } 32 if strings.HasPrefix(ou, "organization:") { 33 cfCert.OrgID = strings.Split(ou, "organization:")[1] 34 orgs++ 35 continue 36 } 37 if strings.HasPrefix(ou, "app:") { 38 cfCert.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 := cfCert.validate(); err != nil { 53 return nil, err 54 } 55 return cfCert, nil 56} 57 58// NewCFCertificateFromx509 converts the given fields to a valid, well-formed CF certificate, 59// erroring if this isn't possible. 60func NewCFCertificate(instanceID, orgID, spaceID, appID, ipAddress string) (*CFCertificate, error) { 61 cfCert := &CFCertificate{ 62 InstanceID: instanceID, 63 OrgID: orgID, 64 SpaceID: spaceID, 65 AppID: appID, 66 IPAddress: ipAddress, 67 } 68 if err := cfCert.validate(); err != nil { 69 return nil, err 70 } 71 return cfCert, nil 72} 73 74// CFCertificate 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 CFCertificate struct { 77 InstanceID, OrgID, SpaceID, AppID, IPAddress string 78} 79 80func (c *CFCertificate) validate() error { 81 if c.InstanceID == "" { 82 return errors.New("no instance ID on given certificate") 83 } 84 if c.AppID == "" { 85 return errors.New("no app ID on given certificate") 86 } 87 if c.OrgID == "" { 88 return errors.New("no org ID on given certificate") 89 } 90 if c.SpaceID == "" { 91 return errors.New("no space ID on given certificate") 92 } 93 if c.IPAddress == "" { 94 return errors.New("ip address is unspecified") 95 } 96 if net.ParseIP(c.IPAddress) == nil { 97 return fmt.Errorf("%q could not be parsed as a valid IP address", c.IPAddress) 98 } 99 return nil 100} 101