debian-forge-composer/cmd/osbuild-auth-tests/certificates.go
Ondřej Budai 19271a542b test/auth: rework the test to use the new openssl setup
Previous commits introduces a new way to generate all X.509 certificates
needed for testing. This commit reuses the same method for auth tests.

This has two benefits:

1) The new code generates certificates with Subject Alternative Name which
   means we can use it on systems with Go 1.15 (Fedora 33, RHEL 8.4).

2) The new code generates much saner certificates.
2020-11-05 13:48:48 +01:00

187 lines
3.9 KiB
Go

package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
)
const (
opensslConfig = "/usr/share/tests/osbuild-composer/x509/openssl.cnf"
osbuildCAExt = "osbuild_ca_ext"
osbuildClientExt = "osbuild_client_ext"
)
type certificateKeyPair struct {
baseDir string
}
func (ckp certificateKeyPair) remove() {
err := os.RemoveAll(ckp.baseDir)
if err != nil {
log.Printf("cannot delete the certificate key pair: %v", err)
}
}
func (ckp certificateKeyPair) certificate() string {
return path.Join(ckp.baseDir, "crt")
}
func (ckp certificateKeyPair) key() string {
return path.Join(ckp.baseDir, "key")
}
func newSelfSignedCertificateKeyPair(subj string) (*certificateKeyPair, error) {
dir, err := ioutil.TempDir("", "osbuild-auth-tests-")
if err != nil {
return nil, fmt.Errorf("cannot create a temporary directory for the certificate: %v", err)
}
ckp := certificateKeyPair{baseDir: dir}
cmd := exec.Command(
"openssl", "req", "-nodes", "-x509",
"-subj", subj,
"-out", ckp.certificate(),
"-keyout", ckp.key(),
)
err = cmd.Run()
if err != nil {
return nil, fmt.Errorf("cannot generate a self-signed certificate: %v", err)
}
return &ckp, nil
}
type ca struct {
BaseDir string
}
func (c ca) remove() {
err := os.RemoveAll(c.BaseDir)
if err != nil {
log.Printf("cannot delete the ca: %v", err)
}
}
func (c ca) certificate() string {
return path.Join(c.BaseDir, "ca.cert.pem")
}
func (c ca) key() string {
return path.Join(c.BaseDir, "private", "ca.key.pem")
}
func newCA(subj string) (*ca, error) {
baseDir, err := ioutil.TempDir("", "osbuild-auth-tests-ca")
if err != nil {
return nil, fmt.Errorf("cannot create a temporary dir for a new CA: %v", err)
}
err = os.Mkdir(path.Join(baseDir, "certs"), 0700)
if err != nil {
innerErr := os.RemoveAll(baseDir)
if innerErr != nil {
log.Print(innerErr)
}
return nil, fmt.Errorf("cannot create certs dir for the new CA: %v", err)
}
err = os.Mkdir(path.Join(baseDir, "private"), 0700)
if err != nil {
innerErr := os.RemoveAll(baseDir)
if innerErr != nil {
log.Print(innerErr)
}
return nil, fmt.Errorf("cannot create private dir for the new CA: %v", err)
}
f, err := os.Create(path.Join(baseDir, "index.txt"))
if err != nil {
innerErr := os.RemoveAll(baseDir)
if innerErr != nil {
log.Print(innerErr)
}
return nil, fmt.Errorf("cannot create index file for the new CA: %v", err)
}
f.Close()
c := ca{
BaseDir: baseDir,
}
cmd := exec.Command(
"openssl", "req",
"-config", opensslConfig,
"-new", "-nodes", "-x509", "-extensions", osbuildCAExt,
"-subj", subj,
"-keyout", c.key(),
"-out", c.certificate(),
)
err = cmd.Run()
if err != nil {
innerErr := os.RemoveAll(baseDir)
if innerErr != nil {
log.Print(innerErr)
}
return nil, fmt.Errorf("cannot create the CA: %v", err)
}
return &c, nil
}
func (c ca) newCertificateKeyPair(subj, extensions, addext string) (*certificateKeyPair, error) {
dir, err := ioutil.TempDir("", "osbuild-auth-tests-")
if err != nil {
return nil, fmt.Errorf("cannot create a temporary directory for the certificate: %v", err)
}
ckp := certificateKeyPair{baseDir: dir}
certificateRequest := path.Join(dir, "csr")
args := []string{
"req", "-new", "-nodes",
"-subj", subj,
"-keyout", ckp.key(),
"-out", certificateRequest,
"-config", opensslConfig,
}
if addext != "" {
args = append(args, "-addext", addext)
}
cmd := exec.Command(
"openssl",
args...,
)
err = cmd.Run()
if err != nil {
return nil, fmt.Errorf("cannot generate a private key and a certificate request: %v", err)
}
defer os.Remove(certificateRequest)
cmd = exec.Command(
"openssl", "ca",
"-batch",
"-config", opensslConfig,
"-extensions", extensions,
"-in", certificateRequest,
"-out", ckp.certificate(),
)
// this command must be run in the CA base directory
cmd.Dir = c.BaseDir
err = cmd.Run()
if err != nil {
return nil, fmt.Errorf("cannot sign the certificate: %v", err)
}
return &ckp, nil
}