diff --git a/tesseract/genconf/env.go b/tesseract/genconf/env.go index 935e5fa..2ae2ef5 100644 --- a/tesseract/genconf/env.go +++ b/tesseract/genconf/env.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io" "log" "os" "path/filepath" @@ -25,11 +24,10 @@ func generateEnv(yamlFile string) { // Create combined roots.pem file rootsPemPath := filepath.Join(logEntry.LocalDirectory, "roots.pem") - err := createCombinedRootsPem(config.Roots, logEntry.ExtraRoots, rootsPemPath) + err := createCombinedRootsPemWithStatus(config.Roots, logEntry.ExtraRoots, rootsPemPath) if err != nil { log.Fatalf("Failed to create %s: %v", rootsPemPath, err) } - fmt.Printf("Generated %s\n", rootsPemPath) // Build TESSERACT_ARGS string args := []string{ @@ -47,50 +45,32 @@ func generateEnv(yamlFile string) { tesseractArgs := strings.Join(args, " ") envContent := fmt.Sprintf("TESSERACT_ARGS=\"%s\"\nOTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318\n", tesseractArgs) - err = os.WriteFile(envPath, []byte(envContent), 0644) + err = writeFileWithStatus(envPath, []byte(envContent)) if err != nil { log.Fatalf("Failed to write %s: %v", envPath, err) } - - fmt.Printf("Generated %s\n", envPath) } } -func createCombinedRootsPem(rootsFile, extraRootsFile, outputPath string) error { - // Create output file - outputFile, err := os.Create(outputPath) - if err != nil { - return fmt.Errorf("failed to create output file: %v", err) - } - defer outputFile.Close() - - // Copy main roots file +func createCombinedRootsPemWithStatus(rootsFile, extraRootsFile, outputPath string) error { + // Read main roots file + var combinedContent []byte if rootsFile != "" { - rootsData, err := os.Open(rootsFile) + rootsData, err := os.ReadFile(rootsFile) if err != nil { - return fmt.Errorf("failed to open roots file %s: %v", rootsFile, err) - } - defer rootsData.Close() - - _, err = io.Copy(outputFile, rootsData) - if err != nil { - return fmt.Errorf("failed to copy roots file: %v", err) + return fmt.Errorf("failed to read roots file %s: %v", rootsFile, err) } + combinedContent = append(combinedContent, rootsData...) } // Append extra roots file if it exists if extraRootsFile != "" { - extraRootsData, err := os.Open(extraRootsFile) + extraRootsData, err := os.ReadFile(extraRootsFile) if err != nil { - return fmt.Errorf("failed to open extra roots file %s: %v", extraRootsFile, err) - } - defer extraRootsData.Close() - - _, err = io.Copy(outputFile, extraRootsData) - if err != nil { - return fmt.Errorf("failed to copy extra roots file: %v", err) + return fmt.Errorf("failed to read extra roots file %s: %v", extraRootsFile, err) } + combinedContent = append(combinedContent, extraRootsData...) } - return nil + return writeFileWithStatus(outputPath, combinedContent) } diff --git a/tesseract/genconf/html.go b/tesseract/genconf/html.go index 4738299..4426629 100644 --- a/tesseract/genconf/html.go +++ b/tesseract/genconf/html.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "crypto/sha256" "crypto/x509" "encoding/base64" @@ -136,27 +137,25 @@ func generateHTML(yamlFile string) { for _, logEntry := range config.Logs { indexPath := fmt.Sprintf("%s/index.html", logEntry.LocalDirectory) - file, err := os.Create(indexPath) + // Execute template to buffer + var buf bytes.Buffer + err := tmpl.Execute(&buf, config) if err != nil { - log.Fatalf("Failed to create %s: %v", indexPath, err) + log.Fatalf("Failed to execute HTML template for %s: %v", indexPath, err) } - err = tmpl.Execute(file, config) + // Write file with status + err = writeFileWithStatus(indexPath, buf.Bytes()) if err != nil { - file.Close() log.Fatalf("Failed to write HTML to %s: %v", indexPath, err) } - file.Close() - fmt.Printf("Generated %s\n", indexPath) - // Generate log.v3.json for this log jsonPath := filepath.Join(logEntry.LocalDirectory, "log.v3.json") - err = generateLogJSON(logEntry, jsonPath) + err = generateLogJSONWithStatus(logEntry, jsonPath) if err != nil { log.Fatalf("Failed to generate %s: %v", jsonPath, err) } - fmt.Printf("Generated %s\n", jsonPath) } } @@ -210,7 +209,7 @@ func computeKeyInfo(logEntry *Log) error { return nil } -func generateLogJSON(logEntry Log, outputPath string) error { +func generateLogJSONWithStatus(logEntry Log, outputPath string) error { logJSON := LogV3JSON{ Description: fmt.Sprintf("%s.log.ct.ipng.ch", logEntry.ShortName), SubmissionURL: fmt.Sprintf("%s/", logEntry.SubmissionPrefix), @@ -229,10 +228,5 @@ func generateLogJSON(logEntry Log, outputPath string) error { return fmt.Errorf("failed to marshal JSON: %v", err) } - err = os.WriteFile(outputPath, jsonData, 0644) - if err != nil { - return fmt.Errorf("failed to write JSON file: %v", err) - } - - return nil + return writeFileWithStatus(outputPath, jsonData) } diff --git a/tesseract/genconf/main.go b/tesseract/genconf/main.go index 404e1d7..b872806 100644 --- a/tesseract/genconf/main.go +++ b/tesseract/genconf/main.go @@ -97,6 +97,26 @@ func loadConfig(yamlFile string) Config { return config } +func writeFileWithStatus(filename string, content []byte) error { + existingContent, err := os.ReadFile(filename) + if os.IsNotExist(err) { + fmt.Printf("Creating %s\n", filename) + } else if err != nil { + return fmt.Errorf("failed to read existing file %s: %v", filename, err) + } else if string(existingContent) == string(content) { + fmt.Printf("Unchanged %s\n", filename) + return nil + } else { + fmt.Printf("Updating %s\n", filename) + } + + err = os.WriteFile(filename, content, 0644) + if err != nil { + return fmt.Errorf("failed to write file %s: %v", filename, err) + } + return nil +} + func showHelp() { fmt.Printf("Usage: %s [options] \n\n", os.Args[0]) fmt.Printf("Options:\n") diff --git a/tesseract/genconf/nginx.go b/tesseract/genconf/nginx.go index 19c69e2..090eac7 100644 --- a/tesseract/genconf/nginx.go +++ b/tesseract/genconf/nginx.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "net/url" "os" @@ -113,22 +114,20 @@ func generateNginx(yamlFile string) { outputFilename := fmt.Sprintf("%s.conf", hostname) outputPath := filepath.Join(log.LocalDirectory, outputFilename) - // Create output file - file, err := os.Create(outputPath) - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to create nginx config file %s: %v\n", outputPath, err) - continue - } - defer file.Close() - - // Execute template - err = tmpl.Execute(file, data) + // Execute template to buffer + var buf bytes.Buffer + err = tmpl.Execute(&buf, data) if err != nil { fmt.Fprintf(os.Stderr, "Failed to execute nginx template for %s: %v\n", outputPath, err) continue } - fmt.Printf("Generated nginx config: %s\n", outputPath) + // Write file with status + err = writeFileWithStatus(outputPath, buf.Bytes()) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to write nginx config file %s: %v\n", outputPath, err) + continue + } } } diff --git a/tesseract/genconf/roots.go b/tesseract/genconf/roots.go index 3a46ae4..89a1c4c 100644 --- a/tesseract/genconf/roots.go +++ b/tesseract/genconf/roots.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "crypto/x509" "encoding/base64" "encoding/json" @@ -8,7 +9,6 @@ import ( "fmt" "log" "net/http" - "os" "strings" ) @@ -67,15 +67,10 @@ func generateRoots(args []string) { log.Fatalf("Failed to parse JSON response: %v", err) } - // Create output file - outFile, err := os.Create(outputFile) - if err != nil { - log.Fatalf("Failed to create output file %s: %v", outputFile, err) - } - defer outFile.Close() - - // Write each certificate as PEM + // Collect all valid certificates in a buffer + var pemBuffer bytes.Buffer validCertCount := 0 + for _, certBase64 := range rootsResp.Certificates { // Decode base64 certificate certBytes, err := base64.StdEncoding.DecodeString(certBase64) @@ -102,14 +97,20 @@ func generateRoots(args []string) { Bytes: certBytes, } - // Write PEM to file - err = pem.Encode(outFile, pemBlock) + // Write PEM to buffer + err = pem.Encode(&pemBuffer, pemBlock) if err != nil { - log.Fatalf("Failed to write PEM certificate: %v", err) + log.Fatalf("Failed to encode PEM certificate: %v", err) } validCertCount++ } + // Write all certificates to file with status + err = writeFileWithStatus(outputFile, pemBuffer.Bytes()) + if err != nil { + log.Fatalf("Failed to write output file %s: %v", outputFile, err) + } + fmt.Printf("Successfully wrote %d certificates to %s (out of %d total)\n", validCertCount, outputFile, len(rootsResp.Certificates)) }