87 lines
1.9 KiB
Go
87 lines
1.9 KiB
Go
|
package ca
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"crypto/rsa"
|
||
|
"crypto/x509"
|
||
|
"crypto/x509/pkix"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"os"
|
||
|
"time"
|
||
|
|
||
|
"github.com/spf13/cobra"
|
||
|
"src.lwithers.me.uk/go/rsa/pkg/ca"
|
||
|
)
|
||
|
|
||
|
// Init a new certificate authority from scratch.
|
||
|
func Init(cmd *cobra.Command, args []string) {
|
||
|
desc := args[0]
|
||
|
|
||
|
template := createCATemplate(desc)
|
||
|
key, err := rsa.GenerateKey(rand.Reader, bits)
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "Failed to generate new key (%d bits): %v\n", bits, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
_, err = ca.Create(dir, template, key)
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "Failed to initialise new certificate authority: %v\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func createCATemplate(desc string) *x509.Certificate {
|
||
|
from, until := signingDates(30 * 365 * 24 * time.Hour)
|
||
|
|
||
|
hasTargetRules := len(permittedDomains) > 0 || len(excludedDomains) > 0
|
||
|
var permittedIP, excludedIP []*net.IPNet
|
||
|
if len(permittedIPs) > 0 {
|
||
|
hasTargetRules = true
|
||
|
for _, ipr := range permittedIPs {
|
||
|
permittedIP = append(permittedIP, parseCIDR(ipr))
|
||
|
}
|
||
|
}
|
||
|
if len(excludedIPs) > 0 {
|
||
|
hasTargetRules = true
|
||
|
for _, ipr := range permittedIPs {
|
||
|
excludedIP = append(excludedIP, parseCIDR(ipr))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return &x509.Certificate{
|
||
|
Subject: pkix.Name{
|
||
|
CommonName: desc,
|
||
|
},
|
||
|
NotBefore: from,
|
||
|
NotAfter: until,
|
||
|
|
||
|
BasicConstraintsValid: true,
|
||
|
IsCA: true,
|
||
|
MaxPathLen: maxPathLen,
|
||
|
MaxPathLenZero: (maxPathLen == 0),
|
||
|
|
||
|
PermittedDNSDomains: permittedDomains,
|
||
|
ExcludedDNSDomains: excludedDomains,
|
||
|
PermittedIPRanges: permittedIP,
|
||
|
ExcludedIPRanges: excludedIP,
|
||
|
PermittedDNSDomainsCritical: hasTargetRules,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func parseCIDR(s string) *net.IPNet {
|
||
|
ip, ipnet, err := net.ParseCIDR(s)
|
||
|
if err != nil {
|
||
|
fmt.Fprintln(os.Stderr, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if !ip.Equal(ipnet.IP) {
|
||
|
fmt.Fprintf(os.Stderr, "%s: invalid IP range (did you mean %s?)\n", s, ipnet.String())
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
return ipnet
|
||
|
}
|