From 859f3606b189020357060d64bd6980024ee46fce Mon Sep 17 00:00:00 2001 From: Slawek Koszewski Date: Sun, 27 Jul 2025 14:44:06 +0200 Subject: [PATCH] Renamed struct types. --- ca.go | 79 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/ca.go b/ca.go index 0f9ae95..195c265 100644 --- a/ca.go +++ b/ca.go @@ -16,46 +16,45 @@ import ( hclparse "github.com/hashicorp/hcl/v2/hclparse" ) -type PathsConfig struct { +type Paths struct { Certificates string `hcl:"certificates"` PrivateKeys string `hcl:"private_keys"` } -type CAConfig struct { - Label string `hcl:",label"` - Name string `hcl:"name"` - Country string `hcl:"country"` - Organization string `hcl:"organization"` - SerialType string `hcl:"serial_type"` - Paths PathsConfig `hcl:"paths,block"` +type CA struct { + Label string `hcl:",label"` + Name string `hcl:"name"` + Country string `hcl:"country"` + Organization string `hcl:"organization"` + SerialType string `hcl:"serial_type"` + Paths Paths `hcl:"paths,block"` } -type ConfigFile struct { - CAs []CAConfig `hcl:"ca,block"` +type Configuration struct { + CA CA `hcl:"ca,block"` } -func LoadCAConfig(path string) (*CAConfig, error) { +func LoadCA(path string) (*CA, error) { parser := hclparse.NewParser() file, diags := parser.ParseHCLFile(path) if diags.HasErrors() { return nil, fmt.Errorf("failed to parse HCL: %s", diags.Error()) } - var configFile ConfigFile - diags = gohcl.DecodeBody(file.Body, nil, &configFile) + var config Configuration + diags = gohcl.DecodeBody(file.Body, nil, &config) if diags.HasErrors() { return nil, fmt.Errorf("failed to decode HCL: %s", diags.Error()) } - if len(configFile.CAs) == 0 { + if (CA{}) == config.CA { return nil, fmt.Errorf("no 'ca' block found in config file") } - ca := &configFile.CAs[0] - if err := ca.Validate(); err != nil { + if err := config.CA.Validate(); err != nil { return nil, err } - return ca, nil + return &config.CA, nil } -func GenerateCA(config *CAConfig) ([]byte, []byte, error) { +func GenerateCA(ca *CA) ([]byte, []byte, error) { priv, err := rsa.GenerateKey(rand.Reader, 4096) if err != nil { return nil, nil, err @@ -68,9 +67,9 @@ func GenerateCA(config *CAConfig) ([]byte, []byte, error) { tmpl := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ - Country: []string{config.Country}, - Organization: []string{config.Organization}, - CommonName: config.Name, + Country: []string{ca.Country}, + Organization: []string{ca.Organization}, + CommonName: ca.Name, }, NotBefore: time.Now(), NotAfter: time.Now().AddDate(10, 0, 0), @@ -103,7 +102,7 @@ func SavePEM(filename string, data []byte, secure bool, overwrite bool) error { } } -func (p *PathsConfig) Validate() error { +func (p *Paths) Validate() error { if p.Certificates == "" { return fmt.Errorf("paths.certificates is required") } @@ -113,7 +112,7 @@ func (p *PathsConfig) Validate() error { return nil } -func (c *CAConfig) Validate() error { +func (c *CA) Validate() error { if c.Name == "" { return fmt.Errorf("CA 'name' is required") } @@ -136,34 +135,36 @@ func (c *CAConfig) Validate() error { } func InitCA(configPath string, overwrite bool) { - config, err := LoadCAConfig(configPath) + ca, err := LoadCA(configPath) if err != nil { fmt.Println("Error loading config:", err) return } - // Create directories for certificates and private keys if they don't exist - dirs := []string{config.Paths.Certificates, config.Paths.PrivateKeys} - for _, dir := range dirs { - if dir == "" { - continue + // Create certificates directory with 0755, private keys with 0700 + if ca.Paths.Certificates != "" { + if err := os.MkdirAll(ca.Paths.Certificates, 0755); err != nil { + fmt.Printf("Error creating certificates directory '%s': %v\n", ca.Paths.Certificates, err) + return } - if err := os.MkdirAll(dir, 0700); err != nil { - fmt.Printf("Error creating directory '%s': %v\n", dir, err) + } + if ca.Paths.PrivateKeys != "" { + if err := os.MkdirAll(ca.Paths.PrivateKeys, 0700); err != nil { + fmt.Printf("Error creating private keys directory '%s': %v\n", ca.Paths.PrivateKeys, err) return } } - certPEM, keyPEM, err := GenerateCA(config) + certPEM, keyPEM, err := GenerateCA(ca) if err != nil { fmt.Println("Error generating CA:", err) return } - if err := SavePEM(filepath.Join(config.Paths.Certificates, "ca_cert.pem"), certPEM, false, overwrite); err != nil { + if err := SavePEM(filepath.Join(ca.Paths.Certificates, "ca_cert.pem"), certPEM, false, overwrite); err != nil { fmt.Println("Error saving CA certificate:", err) return } - if err := SavePEM(filepath.Join(config.Paths.PrivateKeys, "ca_key.pem"), keyPEM, true, overwrite); err != nil { + if err := SavePEM(filepath.Join(ca.Paths.PrivateKeys, "ca_key.pem"), keyPEM, true, overwrite); err != nil { fmt.Println("Error saving CA key:", err) return } @@ -171,14 +172,14 @@ func InitCA(configPath string, overwrite bool) { } func IssueCertificate(configPath, subject string, overwrite bool) { - config, err := LoadCAConfig(configPath) + ca, err := LoadCA(configPath) if err != nil { fmt.Println("Error loading config:", err) return } - caCertPath := filepath.Join(config.Paths.Certificates, "ca_cert.pem") - caKeyPath := filepath.Join(config.Paths.PrivateKeys, "ca_key.pem") + caCertPath := filepath.Join(ca.Paths.Certificates, "ca_cert.pem") + caKeyPath := filepath.Join(ca.Paths.PrivateKeys, "ca_key.pem") caCertPEM, err := os.ReadFile(caCertPath) if err != nil { @@ -241,8 +242,8 @@ func IssueCertificate(configPath, subject string, overwrite bool) { certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) - certFile := filepath.Join(config.Paths.Certificates, subject+".crt.pem") - keyFile := filepath.Join(config.Paths.PrivateKeys, subject+".key.pem") + certFile := filepath.Join(ca.Paths.Certificates, subject+".crt.pem") + keyFile := filepath.Join(ca.Paths.PrivateKeys, subject+".key.pem") if err := SavePEM(certFile, certPEM, false, overwrite); err != nil { fmt.Println("Error saving certificate:", err) return