refactor: Split large main file
This commit is contained in:
130
ca_loader.go
Normal file
130
ca_loader.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"ocspcrl/internal/ocsp_source"
|
||||
)
|
||||
|
||||
const (
|
||||
crlFileName = "crl.pem"
|
||||
keyFileName = "key.pem"
|
||||
responderFileName = "responder.crt"
|
||||
caFileName = "ca.crt"
|
||||
)
|
||||
|
||||
type caFiles struct {
|
||||
key string
|
||||
responder string
|
||||
ca string
|
||||
crl string
|
||||
}
|
||||
|
||||
func newCaFiles(directory string) caFiles {
|
||||
return caFiles{
|
||||
key: filepath.Join(directory, keyFileName),
|
||||
responder: filepath.Join(directory, responderFileName),
|
||||
ca: filepath.Join(directory, caFileName),
|
||||
crl: filepath.Join(directory, crlFileName),
|
||||
}
|
||||
}
|
||||
|
||||
func (f caFiles) ensureExist(caName string) error {
|
||||
for _, path := range []string{f.key, f.responder, f.ca, f.crl} {
|
||||
if _, statError := os.Stat(path); statError != nil {
|
||||
return fmt.Errorf("ca %q: %w", caName, statError)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyResponderIssuedByCa(responder tls.Certificate, ca *x509.Certificate) error {
|
||||
if responder.Leaf == nil {
|
||||
return fmt.Errorf("responder leaf certificate could not be parsed")
|
||||
}
|
||||
if !bytes.Equal(ca.RawSubject, responder.Leaf.RawIssuer) {
|
||||
return fmt.Errorf("responder certificate issuer does not match ca certificate subject; %+q != %+q",
|
||||
ca.Subject.String(), responder.Leaf.Issuer.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadCa(name, directory string) (*caInstance, error) {
|
||||
files := newCaFiles(directory)
|
||||
if existsError := files.ensureExist(name); existsError != nil {
|
||||
return nil, existsError
|
||||
}
|
||||
|
||||
responderKeyPair, loadResponderError := tls.LoadX509KeyPair(files.responder, files.key)
|
||||
if loadResponderError != nil {
|
||||
return nil, fmt.Errorf("ca %q: failed to load responder key pair: %w", name, loadResponderError)
|
||||
}
|
||||
|
||||
caCertificate, loadCaError := loadCertificateFromFile(files.ca)
|
||||
if loadCaError != nil {
|
||||
return nil, fmt.Errorf("ca %q: failed to load ca certificate: %w", name, loadCaError)
|
||||
}
|
||||
|
||||
if verifyError := verifyResponderIssuedByCa(responderKeyPair, caCertificate); verifyError != nil {
|
||||
return nil, fmt.Errorf("ca %q: %w", name, verifyError)
|
||||
}
|
||||
|
||||
instance := &caInstance{
|
||||
name: name,
|
||||
crlPath: files.crl,
|
||||
caCertificate: caCertificate,
|
||||
source: ocsp_source.NewCrlSource(caCertificate, responderKeyPair),
|
||||
}
|
||||
|
||||
if reloadError := instance.reloadCrl(); reloadError != nil {
|
||||
return nil, fmt.Errorf("ca %q: failed to load crl: %w", name, reloadError)
|
||||
}
|
||||
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
func listCaSubdirectories(rootDir string) ([]string, error) {
|
||||
entries, readDirError := os.ReadDir(rootDir)
|
||||
if readDirError != nil {
|
||||
return nil, fmt.Errorf("failed to read cas directory: %w", readDirError)
|
||||
}
|
||||
names := []string{}
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(entry.Name(), ".") {
|
||||
continue
|
||||
}
|
||||
names = append(names, entry.Name())
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func discoverCas(rootDir string) ([]*caInstance, error) {
|
||||
names, listError := listCaSubdirectories(rootDir)
|
||||
if listError != nil {
|
||||
return nil, listError
|
||||
}
|
||||
if len(names) == 0 {
|
||||
return nil, fmt.Errorf("no ca subdirectories found in %s", rootDir)
|
||||
}
|
||||
|
||||
cas := make([]*caInstance, 0, len(names))
|
||||
for _, name := range names {
|
||||
instance, loadError := loadCa(name, filepath.Join(rootDir, name))
|
||||
if loadError != nil {
|
||||
return nil, loadError
|
||||
}
|
||||
cas = append(cas, instance)
|
||||
}
|
||||
return cas, nil
|
||||
}
|
||||
Reference in New Issue
Block a user