277 lines
9.2 KiB
Go
277 lines
9.2 KiB
Go
package models
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/jmoiron/jsonq"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// LeafCertExtensions extends the LeafCert object.
|
|
type LeafCertExtensions struct {
|
|
gorm.Model
|
|
KeyUsage string `json:"keyUsage"`
|
|
ExtendedKeyUsage string `json:"extendedKeyUsage"`
|
|
BasicConstrains string `json:"basicConstrains"`
|
|
SubjectKeyIdentifier string `json:"subjectKeyIdentifier"`
|
|
AuthorityInfoAccess string `json:"authorityInfoAccess"`
|
|
SubjectAltName string `json:"subjectAltName"`
|
|
CertificatePolicies string `json:"certificatePolicies"`
|
|
}
|
|
|
|
// LeafCertSubject is the subject of the LeafCert object.
|
|
type LeafCertSubject struct {
|
|
gorm.Model
|
|
Aggregated string `json:"aggregated"`
|
|
C string `json:"C"`
|
|
ST string `json:"ST"`
|
|
L string `json:"L"`
|
|
O string `json:"O"`
|
|
OU string `json:"OU"`
|
|
CN string `json:"CN"`
|
|
}
|
|
|
|
// LeafCertStruct represents the LeafCert object.
|
|
type LeafCertStruct struct {
|
|
gorm.Model
|
|
Subject LeafCertSubject `json:"subject"`
|
|
Extensions LeafCertExtensions `json:"extensions"`
|
|
NotBefore int `json:"not_before"`
|
|
NotAfter int `json:"not_after"`
|
|
SerialNumber string `json:"serial_number"`
|
|
Fingerprint string `json:"fingerprint"`
|
|
AsDer string `json:"as_der"`
|
|
// AllDomains []string `json:"all_domains"`
|
|
}
|
|
|
|
// Source is the object ofr the URL and its name.
|
|
type Source struct {
|
|
gorm.Model
|
|
URL string `json:"url"`
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
// CertStreamData is the data contained in a CertStream payload.
|
|
type CertStreamData struct {
|
|
gorm.Model
|
|
UpdateType string `json:"update_type"`
|
|
LeafCert LeafCertStruct `json:"leaf_cert"`
|
|
Chain []LeafCertStruct `json:"chain"`
|
|
CertIndex int `json:"cert_index"`
|
|
Seen int `json:"seen"`
|
|
Source Source `json:"source"`
|
|
CertStreamStruct uint
|
|
}
|
|
|
|
// CertStreamStruct reprensts a payload received from CertStream. It has a type
|
|
// and the content is stored in Data.
|
|
type CertStreamStruct struct {
|
|
gorm.Model
|
|
MessageType string
|
|
Data CertStreamData `json:"data"`
|
|
}
|
|
|
|
// Certificate is the main model saved and exposed to the API.
|
|
type Certificate struct {
|
|
gorm.Model
|
|
Aggregated string `json:"aggregated"`
|
|
C string `json:"C"`
|
|
ST string `json:"ST"`
|
|
L string `json:"L"`
|
|
O string `json:"O"`
|
|
OU string `json:"OU"`
|
|
CN string `json:"CN"`
|
|
Fingerprint string `json:"fingerprint"`
|
|
}
|
|
|
|
// ExtractCertFromStream builds the structures before saving them. It uses the
|
|
// power of jsonq to parse quickly the json stream.
|
|
// The base structure is coming from : https://github.com/CaliDog/certstream-go#example-data-structure
|
|
func ExtractCertFromStream(input jsonq.JsonQuery) (*Certificate, error) {
|
|
// LeafCertStruct
|
|
leafCertStruct, err := extractLeafCertStruct(input)
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
|
|
// CertStreamData > Source
|
|
url, err := input.String("data", "source", "url")
|
|
name, err := input.String("data", "source", "name")
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
|
|
source := Source{
|
|
URL: url,
|
|
Name: name,
|
|
}
|
|
|
|
// CertStreamData
|
|
updateType, err := input.String("data", "update_type")
|
|
certIndex, err := input.Int("data", "cert_index")
|
|
seen, err := input.Int("data", "seen")
|
|
chain, err := input.ArrayOfObjects("data", "chain")
|
|
chainSlice := []LeafCertStruct{}
|
|
for i := 0; i < len(chain); i++ {
|
|
c, err := extractLeafCertChainStruct(input, strconv.Itoa(i))
|
|
if err != nil {
|
|
logrus.Error("error extractLeafCertChainStruct: ", err)
|
|
}
|
|
chainSlice = append(chainSlice, c)
|
|
}
|
|
|
|
csd := CertStreamData{
|
|
UpdateType: updateType,
|
|
LeafCert: leafCertStruct,
|
|
Chain: chainSlice,
|
|
CertIndex: certIndex,
|
|
Seen: seen,
|
|
Source: source,
|
|
}
|
|
|
|
// CertStreamStruct
|
|
messageType, err := input.String("message_type")
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
|
|
certStruct := CertStreamStruct{
|
|
MessageType: messageType,
|
|
Data: csd,
|
|
}
|
|
|
|
res := Certificate{
|
|
Aggregated: certStruct.Data.LeafCert.Subject.Aggregated,
|
|
C: certStruct.Data.LeafCert.Subject.C,
|
|
ST: certStruct.Data.LeafCert.Subject.ST,
|
|
L: certStruct.Data.LeafCert.Subject.L,
|
|
O: certStruct.Data.LeafCert.Subject.O,
|
|
OU: certStruct.Data.LeafCert.Subject.OU,
|
|
CN: certStruct.Data.LeafCert.Subject.CN,
|
|
Fingerprint: certStruct.Data.LeafCert.Fingerprint,
|
|
}
|
|
|
|
return &res, nil
|
|
|
|
}
|
|
|
|
func extractLeafCertChainStruct(input jsonq.JsonQuery, index string) (LeafCertStruct, error) {
|
|
// LeafCertStruct > Subject
|
|
aggregated, _ := input.String("data", "chain", index, "subject", "aggregated")
|
|
c, _ := input.String("data", "chain", index, "subject", "C")
|
|
st, _ := input.String("data", "chain", index, "subject", "ST")
|
|
l, _ := input.String("data", "chain", index, "subject", "L")
|
|
o, _ := input.String("data", "chain", index, "subject", "O")
|
|
ou, _ := input.String("data", "chain", index, "subject", "OU")
|
|
cn, _ := input.String("data", "chain", index, "subject", "CN")
|
|
|
|
subject := LeafCertSubject{
|
|
Aggregated: aggregated,
|
|
C: c,
|
|
ST: st,
|
|
L: l,
|
|
O: o,
|
|
OU: ou,
|
|
CN: cn,
|
|
}
|
|
|
|
// LeafCertStruct > Extensions
|
|
keyUsage, _ := input.String("data", "chain", index, "extensions", "keyUsage")
|
|
extendedKeyUsage, _ := input.String("data", "chain", index, "extensions", "extendedKeyUsage")
|
|
basicConstrains, _ := input.String("data", "chain", index, "extensions", "basicConstrains")
|
|
subjectKeyIdentifier, _ := input.String("data", "chain", index, "extensions", "subjectKeyIdentifier")
|
|
authorityInfoAccess, _ := input.String("data", "chain", index, "extensions", "authorityInfoAccess")
|
|
subjectAltName, _ := input.String("data", "chain", index, "extensions", "subjectAltName")
|
|
certificatePolicies, _ := input.String("data", "chain", index, "extensions", "certificatePolicies")
|
|
|
|
extensions := LeafCertExtensions{
|
|
KeyUsage: keyUsage,
|
|
ExtendedKeyUsage: extendedKeyUsage,
|
|
BasicConstrains: basicConstrains,
|
|
SubjectKeyIdentifier: subjectKeyIdentifier,
|
|
AuthorityInfoAccess: authorityInfoAccess,
|
|
SubjectAltName: subjectAltName,
|
|
CertificatePolicies: certificatePolicies,
|
|
}
|
|
|
|
notBefore, _ := input.Int("data", "chain", "not_before")
|
|
notAfter, _ := input.Int("data", "chain", "not_after")
|
|
serialNumber, _ := input.String("data", "chain", "serialNumber")
|
|
fingerprint, _ := input.String("data", "chain", "fingerprint")
|
|
asDer, _ := input.String("data", "chain", "as_der")
|
|
// allDomains, _ := input.ArrayOfStrings("data", "chain", "all_domains")
|
|
|
|
return LeafCertStruct{
|
|
Subject: subject,
|
|
Extensions: extensions,
|
|
NotBefore: notBefore,
|
|
NotAfter: notAfter,
|
|
SerialNumber: serialNumber,
|
|
Fingerprint: fingerprint,
|
|
AsDer: asDer,
|
|
// AllDomains: allDomains,
|
|
}, nil
|
|
|
|
}
|
|
func extractLeafCertStruct(input jsonq.JsonQuery) (LeafCertStruct, error) {
|
|
// LeafCertStruct > Subject
|
|
aggregated, err := input.String("data", "leaf_cert", "subject", "aggregated")
|
|
c, err := input.String("data", "leaf_cert", "subject", "C")
|
|
st, err := input.String("data", "leaf_cert", "subject", "ST")
|
|
l, err := input.String("data", "leaf_cert", "subject", "L")
|
|
o, err := input.String("data", "leaf_cert", "subject", "O")
|
|
ou, err := input.String("data", "leaf_cert", "subject", "OU")
|
|
cn, err := input.String("data", "leaf_cert", "subject", "CN")
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
|
|
subject := LeafCertSubject{
|
|
Aggregated: aggregated,
|
|
C: c,
|
|
ST: st,
|
|
L: l,
|
|
O: o,
|
|
OU: ou,
|
|
CN: cn,
|
|
}
|
|
|
|
// LeafCertStruct > Extensions
|
|
keyUsage, _ := input.String("data", "leaf_cert", "extensions", "keyUsage")
|
|
extendedKeyUsage, _ := input.String("data", "leaf_cert", "extensions", "extendedKeyUsage")
|
|
basicConstrains, _ := input.String("data", "leaf_cert", "extensions", "basicConstrains")
|
|
subjectKeyIdentifier, _ := input.String("data", "leaf_cert", "extensions", "subjectKeyIdentifier")
|
|
authorityInfoAccess, _ := input.String("data", "leaf_cert", "extensions", "authorityInfoAccess")
|
|
subjectAltName, _ := input.String("data", "leaf_cert", "extensions", "subjectAltName")
|
|
certificatePolicies, _ := input.String("data", "leaf_cert", "extensions", "certificatePolicies")
|
|
|
|
extensions := LeafCertExtensions{
|
|
KeyUsage: keyUsage,
|
|
ExtendedKeyUsage: extendedKeyUsage,
|
|
BasicConstrains: basicConstrains,
|
|
SubjectKeyIdentifier: subjectKeyIdentifier,
|
|
AuthorityInfoAccess: authorityInfoAccess,
|
|
SubjectAltName: subjectAltName,
|
|
CertificatePolicies: certificatePolicies,
|
|
}
|
|
|
|
notBefore, _ := input.Int("data", "leaf_cert", "not_before")
|
|
notAfter, _ := input.Int("data", "leaf_cert", "not_after")
|
|
serialNumber, _ := input.String("data", "leaf_cert", "serialNumber")
|
|
fingerprint, _ := input.String("data", "leaf_cert", "fingerprint")
|
|
asDer, _ := input.String("data", "leaf_cert", "as_der")
|
|
// allDomains, _ := input.ArrayOfStrings("data", "leaf_cert", "all_domains")
|
|
|
|
return LeafCertStruct{
|
|
Subject: subject,
|
|
Extensions: extensions,
|
|
NotBefore: notBefore,
|
|
NotAfter: notAfter,
|
|
SerialNumber: serialNumber,
|
|
Fingerprint: fingerprint,
|
|
AsDer: asDer,
|
|
// AllDomains: allDomains,
|
|
}, nil
|
|
|
|
}
|