certspotter/loglist/schema.go

117 lines
3.2 KiB
Go

// Copyright (C) 2020 Opsmate, Inc.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License, v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// This software is distributed WITHOUT A WARRANTY OF ANY KIND.
// See the Mozilla Public License for details.
package loglist
import (
"time"
"software.sslmate.com/src/certspotter/ct"
)
type List struct {
Version string `json:"version"`
LogListTimestamp time.Time `json:"log_list_timestamp"` // Only present in v3 of schema
Operators []Operator `json:"operators"`
}
type Operator struct {
Name string `json:"name"`
Email []string `json:"email"`
Logs []Log `json:"logs"`
TiledLogs []Log `json:"tiled_logs"`
}
type Log struct {
Key []byte `json:"key"`
LogID ct.SHA256Hash `json:"log_id"`
MMD int `json:"mmd"`
URL string `json:"url,omitempty"` // only for rfc6962 logs
SubmissionURL string `json:"submission_url,omitempty"` // only for static-ct-api logs
MonitoringURL string `json:"monitoring_url,omitempty"` // only for static-ct-api logs
Description string `json:"description"`
State State `json:"state"`
DNS string `json:"dns"`
LogType LogType `json:"log_type"`
TemporalInterval *struct {
StartInclusive time.Time `json:"start_inclusive"`
EndExclusive time.Time `json:"end_exclusive"`
} `json:"temporal_interval"`
// TODO: add previous_operators
}
func (log *Log) IsRFC6962() bool { return log.URL != "" }
func (log *Log) IsStaticCTAPI() bool { return log.SubmissionURL != "" && log.MonitoringURL != "" }
// Return URL prefix for submission using the RFC6962 protocol
func (log *Log) GetSubmissionURL() string {
if log.SubmissionURL != "" {
return log.SubmissionURL
} else {
return log.URL
}
}
// Return URL prefix for monitoring.
// Since the protocol understood by the URL might be either RFC6962 or static-ct-api, this URL is
// only useful for informational purposes.
func (log *Log) GetMonitoringURL() string {
if log.MonitoringURL != "" {
return log.MonitoringURL
} else {
return log.URL
}
}
type State struct {
Pending *struct {
Timestamp time.Time `json:"timestamp"`
} `json:"pending"`
Qualified *struct {
Timestamp time.Time `json:"timestamp"`
} `json:"qualified"`
Usable *struct {
Timestamp time.Time `json:"timestamp"`
} `json:"usable"`
Readonly *struct {
Timestamp time.Time `json:"timestamp"`
FinalTreeHead struct {
TreeSize int64 `json:"tree_size"`
SHA256RootHash []byte `json:"sha256_root_hash"`
} `json:"final_tree_head"`
} `json:"readonly"`
Retired *struct {
Timestamp time.Time `json:"timestamp"`
} `json:"retired"`
Rejected *struct {
Timestamp time.Time `json:"timestamp"`
} `json:"rejected"`
}
func (state *State) IsApproved() bool {
return state.Qualified != nil || state.Usable != nil || state.Readonly != nil
}
func (state *State) WasApprovedAt(t time.Time) bool {
return state.Retired != nil && t.Before(state.Retired.Timestamp)
}
type LogType string
const (
LogTypeProd = "prod"
LogTypeTest = "test"
)