Implement configuration support for CA profiles

This commit is contained in:
Jan Dittberner 2022-11-30 18:42:40 +01:00
parent f98840bf9e
commit 1031ee3118
3 changed files with 99 additions and 3 deletions

View file

@ -31,6 +31,8 @@ import (
"gopkg.in/yaml.v3"
"git.cacert.org/cacert-gosigner/pkg/messages"
"git.cacert.org/cacert-gosigner/internal/x509/openssl"
"git.cacert.org/cacert-gosigner/internal/x509/revoking"
"git.cacert.org/cacert-gosigner/internal/x509/signing"
@ -540,6 +542,7 @@ type CaCertificateEntry struct {
KeyPair crypto.Signer
Parent string
Storage string
Profiles []messages.CAProfile
}
func (c *CaCertificateEntry) UnmarshalYAML(value *yaml.Node) error {
@ -551,6 +554,10 @@ func (c *CaCertificateEntry) UnmarshalYAML(value *yaml.Node) error {
ExtKeyUsage []string `yaml:"ext-key-usages,omitempty"`
Parent string `yaml:"parent"`
Storage string `yaml:"storage"`
Profiles []struct {
Name string `yaml:"name"`
UseFor string `yaml:"use-for"`
} `yaml:"profiles"`
}
err := value.Decode(&m)
@ -590,6 +597,22 @@ func (c *CaCertificateEntry) UnmarshalYAML(value *yaml.Node) error {
c.Storage = "default"
}
if m.Profiles != nil {
c.Profiles = make([]messages.CAProfile, len(m.Profiles))
for i, prof := range m.Profiles {
usage, err := messages.ParseUsage(prof.UseFor)
if err != nil {
return fmt.Errorf("config error: %w", err)
}
c.Profiles[i] = messages.CAProfile{
Name: prof.Name,
UseFor: usage,
}
}
}
return nil
}

View file

@ -37,6 +37,8 @@ import (
"github.com/ThalesIgnite/crypto11"
"github.com/sirupsen/logrus"
"git.cacert.org/cacert-gosigner/pkg/messages"
"git.cacert.org/cacert-gosigner/internal/config"
"git.cacert.org/cacert-gosigner/internal/health"
)
@ -68,7 +70,7 @@ func (a *Access) Healthy() (*health.Info, error) {
moreInfo := make(map[string]string)
const checkFailed = "failed"
var checkFailed = messages.CertificateInfo{Status: "failed", Signing: false}.String()
for _, ca := range a.signerConfig.RootCAs() {
infoKey := fmt.Sprintf("root-%s", ca)
@ -82,7 +84,12 @@ func (a *Access) Healthy() (*health.Info, error) {
continue
}
moreInfo[infoKey] = fmt.Sprintf("ok, valid until %s", cert.NotAfter.UTC().Format(time.RFC3339))
moreInfo[infoKey] = messages.CertificateInfo{
Status: "ok",
Signing: false,
Profiles: []messages.CAProfile{},
ValidUntil: cert.NotAfter.UTC(),
}.String()
}
for _, ca := range a.signerConfig.SubordinateCAs() {
@ -115,7 +122,12 @@ func (a *Access) Healthy() (*health.Info, error) {
continue
}
moreInfo[infoKey] = fmt.Sprintf("ok, valid until %s", cert.NotAfter.UTC().Format(time.RFC3339))
moreInfo[infoKey] = messages.CertificateInfo{
Status: "ok",
Signing: true,
Profiles: def.Profiles,
ValidUntil: cert.NotAfter.UTC(),
}.String()
}
return &health.Info{

View file

@ -22,6 +22,7 @@ package messages
import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"math/big"
@ -144,6 +145,66 @@ func (i *HealthInfo) String() string {
return builder.String()
}
type ProfileUsage string
const (
UsageOcsp ProfileUsage = "ocsp"
UsagePerson ProfileUsage = "person"
UsageClient ProfileUsage = "client"
UsageCode ProfileUsage = "code"
UsageServer ProfileUsage = "server"
)
var validProfileUsages = map[string]ProfileUsage{
"ocsp": UsageOcsp,
"person": UsagePerson,
"client": UsageClient,
"code": UsageCode,
"server": UsageServer,
}
func ParseUsage(u string) (ProfileUsage, error) {
usage, ok := validProfileUsages[u]
if !ok {
return "", fmt.Errorf("unsupported profile usage: %s", u)
}
return usage, nil
}
type CAProfile struct {
Name string `json:"name"`
UseFor ProfileUsage `json:"use-for"`
}
func (p CAProfile) String() string {
return fmt.Sprintf("profile['%s': '%s']", p.Name, p.UseFor)
}
type CertificateInfo struct {
Status string `json:"status"`
Signing bool `json:"signing"`
Profiles []CAProfile `json:"profiles"`
ValidUntil time.Time `json:"valid-until"`
}
func (i CertificateInfo) String() string {
marshal, _ := json.Marshal(i)
return string(marshal)
}
func (i *HealthInfo) ParseCertificateInfo(info string) (*CertificateInfo, error) {
certInfo := CertificateInfo{}
err := json.Unmarshal([]byte(info), &certInfo)
if err != nil {
return nil, fmt.Errorf("could not parse certificate information: %w", err)
}
return &certInfo, nil
}
type HealthResponse struct {
Version string `msgpack:"version"`
Healthy bool `msgpack:"healthy"`