go fmt
This commit is contained in:
@@ -30,24 +30,24 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Log struct {
|
type Log struct {
|
||||||
ShortName string `yaml:"shortname"`
|
ShortName string `yaml:"shortname"`
|
||||||
Inception string `yaml:"inception"`
|
Inception string `yaml:"inception"`
|
||||||
Period int `yaml:"period"`
|
Period int `yaml:"period"`
|
||||||
PoolSize int `yaml:"poolsize"`
|
PoolSize int `yaml:"poolsize"`
|
||||||
SubmissionPrefix string `yaml:"submissionprefix"`
|
SubmissionPrefix string `yaml:"submissionprefix"`
|
||||||
MonitoringPrefix string `yaml:"monitoringprefix"`
|
MonitoringPrefix string `yaml:"monitoringprefix"`
|
||||||
CCadbRoots string `yaml:"ccadbroots"`
|
CCadbRoots string `yaml:"ccadbroots"`
|
||||||
ExtraRoots string `yaml:"extraroots"`
|
ExtraRoots string `yaml:"extraroots"`
|
||||||
Secret string `yaml:"secret"`
|
Secret string `yaml:"secret"`
|
||||||
Cache string `yaml:"cache"`
|
Cache string `yaml:"cache"`
|
||||||
LocalDirectory string `yaml:"localdirectory"`
|
LocalDirectory string `yaml:"localdirectory"`
|
||||||
NotAfterStart time.Time `yaml:"notafterstart"`
|
NotAfterStart time.Time `yaml:"notafterstart"`
|
||||||
NotAfterLimit time.Time `yaml:"notafterlimit"`
|
NotAfterLimit time.Time `yaml:"notafterlimit"`
|
||||||
// Computed fields
|
// Computed fields
|
||||||
LogID string
|
LogID string
|
||||||
PublicKeyPEM string
|
PublicKeyPEM string
|
||||||
PublicKeyDERB64 string
|
PublicKeyDERB64 string
|
||||||
PublicKeyBase64 string
|
PublicKeyBase64 string
|
||||||
}
|
}
|
||||||
|
|
||||||
const htmlTemplate = `<!DOCTYPE html>
|
const htmlTemplate = `<!DOCTYPE html>
|
||||||
@@ -188,23 +188,23 @@ func showConfig(yamlFile string) {
|
|||||||
fmt.Printf("Listen addresses: %v\n", config.Listen)
|
fmt.Printf("Listen addresses: %v\n", config.Listen)
|
||||||
fmt.Printf("Checkpoints: %s\n", config.Checkpoints)
|
fmt.Printf("Checkpoints: %s\n", config.Checkpoints)
|
||||||
fmt.Printf("Number of logs: %d\n", len(config.Logs))
|
fmt.Printf("Number of logs: %d\n", len(config.Logs))
|
||||||
|
|
||||||
for i, logEntry := range config.Logs {
|
for i, logEntry := range config.Logs {
|
||||||
fmt.Printf("Log %d: %s (Period: %d, Pool size: %d)\n",
|
fmt.Printf("Log %d: %s (Period: %d, Pool size: %d)\n",
|
||||||
i+1, logEntry.ShortName, logEntry.Period, logEntry.PoolSize)
|
i+1, logEntry.ShortName, logEntry.Period, logEntry.PoolSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateHTML(yamlFile string) {
|
func generateHTML(yamlFile string) {
|
||||||
config := loadConfig(yamlFile)
|
config := loadConfig(yamlFile)
|
||||||
|
|
||||||
// Check that all local directories exist
|
// Check that all local directories exist
|
||||||
for _, logEntry := range config.Logs {
|
for _, logEntry := range config.Logs {
|
||||||
if _, err := os.Stat(logEntry.LocalDirectory); os.IsNotExist(err) {
|
if _, err := os.Stat(logEntry.LocalDirectory); os.IsNotExist(err) {
|
||||||
log.Fatalf("User is required to create %s", logEntry.LocalDirectory)
|
log.Fatalf("User is required to create %s", logEntry.LocalDirectory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute key information for each log
|
// Compute key information for each log
|
||||||
for i := range config.Logs {
|
for i := range config.Logs {
|
||||||
err := computeKeyInfo(&config.Logs[i])
|
err := computeKeyInfo(&config.Logs[i])
|
||||||
@@ -212,30 +212,30 @@ func generateHTML(yamlFile string) {
|
|||||||
log.Fatalf("Failed to compute key info for %s: %v", config.Logs[i].ShortName, err)
|
log.Fatalf("Failed to compute key info for %s: %v", config.Logs[i].ShortName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpl, err := template.New("html").Parse(htmlTemplate)
|
tmpl, err := template.New("html").Parse(htmlTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to parse template: %v", err)
|
log.Fatalf("Failed to parse template: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write HTML file to each log's local directory
|
// Write HTML file to each log's local directory
|
||||||
for _, logEntry := range config.Logs {
|
for _, logEntry := range config.Logs {
|
||||||
indexPath := fmt.Sprintf("%s/index.html", logEntry.LocalDirectory)
|
indexPath := fmt.Sprintf("%s/index.html", logEntry.LocalDirectory)
|
||||||
|
|
||||||
file, err := os.Create(indexPath)
|
file, err := os.Create(indexPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to create %s: %v", indexPath, err)
|
log.Fatalf("Failed to create %s: %v", indexPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tmpl.Execute(file, config)
|
err = tmpl.Execute(file, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
file.Close()
|
file.Close()
|
||||||
log.Fatalf("Failed to write HTML to %s: %v", indexPath, err)
|
log.Fatalf("Failed to write HTML to %s: %v", indexPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
fmt.Printf("Generated %s\n", indexPath)
|
fmt.Printf("Generated %s\n", indexPath)
|
||||||
|
|
||||||
// Generate log.v3.json for this log
|
// Generate log.v3.json for this log
|
||||||
jsonPath := filepath.Join(logEntry.LocalDirectory, "log.v3.json")
|
jsonPath := filepath.Join(logEntry.LocalDirectory, "log.v3.json")
|
||||||
err = generateLogJSON(logEntry, jsonPath)
|
err = generateLogJSON(logEntry, jsonPath)
|
||||||
@@ -252,58 +252,58 @@ func computeKeyInfo(logEntry *Log) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read key file: %v", err)
|
return fmt.Errorf("failed to read key file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse PEM block
|
// Parse PEM block
|
||||||
block, _ := pem.Decode(keyData)
|
block, _ := pem.Decode(keyData)
|
||||||
if block == nil {
|
if block == nil {
|
||||||
return fmt.Errorf("failed to decode PEM block")
|
return fmt.Errorf("failed to decode PEM block")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse EC private key
|
// Parse EC private key
|
||||||
privKey, err := x509.ParseECPrivateKey(block.Bytes)
|
privKey, err := x509.ParseECPrivateKey(block.Bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse EC private key: %v", err)
|
return fmt.Errorf("failed to parse EC private key: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract public key
|
// Extract public key
|
||||||
pubKey := &privKey.PublicKey
|
pubKey := &privKey.PublicKey
|
||||||
|
|
||||||
// Convert public key to DER format
|
// Convert public key to DER format
|
||||||
pubKeyDER, err := x509.MarshalPKIXPublicKey(pubKey)
|
pubKeyDER, err := x509.MarshalPKIXPublicKey(pubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal public key: %v", err)
|
return fmt.Errorf("failed to marshal public key: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PEM format
|
// Create PEM format
|
||||||
pubKeyPEM := pem.EncodeToMemory(&pem.Block{
|
pubKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||||
Type: "PUBLIC KEY",
|
Type: "PUBLIC KEY",
|
||||||
Bytes: pubKeyDER,
|
Bytes: pubKeyDER,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Compute Log ID (SHA-256 of the DER-encoded public key)
|
// Compute Log ID (SHA-256 of the DER-encoded public key)
|
||||||
logIDBytes := sha256.Sum256(pubKeyDER)
|
logIDBytes := sha256.Sum256(pubKeyDER)
|
||||||
logID := base64.StdEncoding.EncodeToString(logIDBytes[:])
|
logID := base64.StdEncoding.EncodeToString(logIDBytes[:])
|
||||||
|
|
||||||
// Base64 encode DER for download link
|
// Base64 encode DER for download link
|
||||||
pubKeyDERB64 := base64.StdEncoding.EncodeToString(pubKeyDER)
|
pubKeyDERB64 := base64.StdEncoding.EncodeToString(pubKeyDER)
|
||||||
|
|
||||||
// Set computed fields
|
// Set computed fields
|
||||||
logEntry.LogID = logID
|
logEntry.LogID = logID
|
||||||
logEntry.PublicKeyPEM = string(pubKeyPEM)
|
logEntry.PublicKeyPEM = string(pubKeyPEM)
|
||||||
logEntry.PublicKeyDERB64 = pubKeyDERB64
|
logEntry.PublicKeyDERB64 = pubKeyDERB64
|
||||||
logEntry.PublicKeyBase64 = pubKeyDERB64 // Same as DER base64 for JSON
|
logEntry.PublicKeyBase64 = pubKeyDERB64 // Same as DER base64 for JSON
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogV3JSON struct {
|
type LogV3JSON struct {
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
SubmissionURL string `json:"submission_url"`
|
SubmissionURL string `json:"submission_url"`
|
||||||
MonitoringURL string `json:"monitoring_url"`
|
MonitoringURL string `json:"monitoring_url"`
|
||||||
TemporalInterval TemporalInterval `json:"temporal_interval"`
|
TemporalInterval TemporalInterval `json:"temporal_interval"`
|
||||||
LogID string `json:"log_id"`
|
LogID string `json:"log_id"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
MMD int `json:"mmd"`
|
MMD int `json:"mmd"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TemporalInterval struct {
|
type TemporalInterval struct {
|
||||||
@@ -324,34 +324,34 @@ func generateLogJSON(logEntry Log, outputPath string) error {
|
|||||||
Key: logEntry.PublicKeyBase64,
|
Key: logEntry.PublicKeyBase64,
|
||||||
MMD: 60, // Default MMD of 60 seconds
|
MMD: 60, // Default MMD of 60 seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonData, err := json.MarshalIndent(logJSON, "", " ")
|
jsonData, err := json.MarshalIndent(logJSON, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal JSON: %v", err)
|
return fmt.Errorf("failed to marshal JSON: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.WriteFile(outputPath, jsonData, 0644)
|
err = os.WriteFile(outputPath, jsonData, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write JSON file: %v", err)
|
return fmt.Errorf("failed to write JSON file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateEnv(yamlFile string) {
|
func generateEnv(yamlFile string) {
|
||||||
config := loadConfig(yamlFile)
|
config := loadConfig(yamlFile)
|
||||||
|
|
||||||
// Check that all local directories exist
|
// Check that all local directories exist
|
||||||
for _, logEntry := range config.Logs {
|
for _, logEntry := range config.Logs {
|
||||||
if _, err := os.Stat(logEntry.LocalDirectory); os.IsNotExist(err) {
|
if _, err := os.Stat(logEntry.LocalDirectory); os.IsNotExist(err) {
|
||||||
log.Fatalf("User is required to create %s", logEntry.LocalDirectory)
|
log.Fatalf("User is required to create %s", logEntry.LocalDirectory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate .env file for each log
|
// Generate .env file for each log
|
||||||
for _, logEntry := range config.Logs {
|
for _, logEntry := range config.Logs {
|
||||||
envPath := filepath.Join(logEntry.LocalDirectory, ".env")
|
envPath := filepath.Join(logEntry.LocalDirectory, ".env")
|
||||||
|
|
||||||
// Create combined roots.pem file
|
// Create combined roots.pem file
|
||||||
rootsPemPath := filepath.Join(logEntry.LocalDirectory, "roots.pem")
|
rootsPemPath := filepath.Join(logEntry.LocalDirectory, "roots.pem")
|
||||||
err := createCombinedRootsPem(config.Roots, logEntry.ExtraRoots, rootsPemPath)
|
err := createCombinedRootsPem(config.Roots, logEntry.ExtraRoots, rootsPemPath)
|
||||||
@@ -359,7 +359,7 @@ func generateEnv(yamlFile string) {
|
|||||||
log.Fatalf("Failed to create %s: %v", rootsPemPath, err)
|
log.Fatalf("Failed to create %s: %v", rootsPemPath, err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Generated %s\n", rootsPemPath)
|
fmt.Printf("Generated %s\n", rootsPemPath)
|
||||||
|
|
||||||
// Build TESSERACT_ARGS string
|
// Build TESSERACT_ARGS string
|
||||||
args := []string{
|
args := []string{
|
||||||
fmt.Sprintf("--private_key=%s", logEntry.Secret),
|
fmt.Sprintf("--private_key=%s", logEntry.Secret),
|
||||||
@@ -367,15 +367,15 @@ func generateEnv(yamlFile string) {
|
|||||||
fmt.Sprintf("--storage_dir=%s", logEntry.LocalDirectory),
|
fmt.Sprintf("--storage_dir=%s", logEntry.LocalDirectory),
|
||||||
fmt.Sprintf("--roots_pem_file=%s", rootsPemPath),
|
fmt.Sprintf("--roots_pem_file=%s", rootsPemPath),
|
||||||
}
|
}
|
||||||
|
|
||||||
tesseractArgs := strings.Join(args, " ")
|
tesseractArgs := strings.Join(args, " ")
|
||||||
envContent := fmt.Sprintf("TESSERACT_ARGS=\"%s\"\n", tesseractArgs)
|
envContent := fmt.Sprintf("TESSERACT_ARGS=\"%s\"\n", tesseractArgs)
|
||||||
|
|
||||||
err = os.WriteFile(envPath, []byte(envContent), 0644)
|
err = os.WriteFile(envPath, []byte(envContent), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to write %s: %v", envPath, err)
|
log.Fatalf("Failed to write %s: %v", envPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Generated %s\n", envPath)
|
fmt.Printf("Generated %s\n", envPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +387,7 @@ func createCombinedRootsPem(rootsFile, extraRootsFile, outputPath string) error
|
|||||||
return fmt.Errorf("failed to create output file: %v", err)
|
return fmt.Errorf("failed to create output file: %v", err)
|
||||||
}
|
}
|
||||||
defer outputFile.Close()
|
defer outputFile.Close()
|
||||||
|
|
||||||
// Copy main roots file
|
// Copy main roots file
|
||||||
if rootsFile != "" {
|
if rootsFile != "" {
|
||||||
rootsData, err := os.Open(rootsFile)
|
rootsData, err := os.Open(rootsFile)
|
||||||
@@ -395,13 +395,13 @@ func createCombinedRootsPem(rootsFile, extraRootsFile, outputPath string) error
|
|||||||
return fmt.Errorf("failed to open roots file %s: %v", rootsFile, err)
|
return fmt.Errorf("failed to open roots file %s: %v", rootsFile, err)
|
||||||
}
|
}
|
||||||
defer rootsData.Close()
|
defer rootsData.Close()
|
||||||
|
|
||||||
_, err = io.Copy(outputFile, rootsData)
|
_, err = io.Copy(outputFile, rootsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to copy roots file: %v", err)
|
return fmt.Errorf("failed to copy roots file: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append extra roots file if it exists
|
// Append extra roots file if it exists
|
||||||
if extraRootsFile != "" {
|
if extraRootsFile != "" {
|
||||||
extraRootsData, err := os.Open(extraRootsFile)
|
extraRootsData, err := os.Open(extraRootsFile)
|
||||||
@@ -409,19 +409,19 @@ func createCombinedRootsPem(rootsFile, extraRootsFile, outputPath string) error
|
|||||||
return fmt.Errorf("failed to open extra roots file %s: %v", extraRootsFile, err)
|
return fmt.Errorf("failed to open extra roots file %s: %v", extraRootsFile, err)
|
||||||
}
|
}
|
||||||
defer extraRootsData.Close()
|
defer extraRootsData.Close()
|
||||||
|
|
||||||
_, err = io.Copy(outputFile, extraRootsData)
|
_, err = io.Copy(outputFile, extraRootsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to copy extra roots file: %v", err)
|
return fmt.Errorf("failed to copy extra roots file: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateKeys(yamlFile string) {
|
func generateKeys(yamlFile string) {
|
||||||
config := loadConfig(yamlFile)
|
config := loadConfig(yamlFile)
|
||||||
|
|
||||||
// Generate keys for each log
|
// Generate keys for each log
|
||||||
for _, logEntry := range config.Logs {
|
for _, logEntry := range config.Logs {
|
||||||
// Check if key already exists
|
// Check if key already exists
|
||||||
@@ -429,36 +429,36 @@ func generateKeys(yamlFile string) {
|
|||||||
fmt.Printf("Key already exists: %s (skipped)\n", logEntry.Secret)
|
fmt.Printf("Key already exists: %s (skipped)\n", logEntry.Secret)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate new prime256v1 key
|
// Generate new prime256v1 key
|
||||||
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to generate key for %s: %v", logEntry.ShortName, err)
|
log.Fatalf("Failed to generate key for %s: %v", logEntry.ShortName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal private key to DER format
|
// Marshal private key to DER format
|
||||||
privKeyDER, err := x509.MarshalECPrivateKey(privKey)
|
privKeyDER, err := x509.MarshalECPrivateKey(privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to marshal private key for %s: %v", logEntry.ShortName, err)
|
log.Fatalf("Failed to marshal private key for %s: %v", logEntry.ShortName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PEM block
|
// Create PEM block
|
||||||
privKeyPEM := pem.EncodeToMemory(&pem.Block{
|
privKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||||
Type: "EC PRIVATE KEY",
|
Type: "EC PRIVATE KEY",
|
||||||
Bytes: privKeyDER,
|
Bytes: privKeyDER,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Ensure directory exists
|
// Ensure directory exists
|
||||||
if err := os.MkdirAll(filepath.Dir(logEntry.Secret), 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(logEntry.Secret), 0755); err != nil {
|
||||||
log.Fatalf("Failed to create directory for %s: %v", logEntry.Secret, err)
|
log.Fatalf("Failed to create directory for %s: %v", logEntry.Secret, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write key to file
|
// Write key to file
|
||||||
err = os.WriteFile(logEntry.Secret, privKeyPEM, 0600)
|
err = os.WriteFile(logEntry.Secret, privKeyPEM, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to write key file %s: %v", logEntry.Secret, err)
|
log.Fatalf("Failed to write key file %s: %v", logEntry.Secret, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Generated %s\n", logEntry.Secret)
|
fmt.Printf("Generated %s\n", logEntry.Secret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user