alaska/models/certstream.go

278 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
}