Files
pinniped/test/testlib/supervisor_issuer.go
2024-11-27 13:53:02 -06:00

106 lines
2.4 KiB
Go

// Copyright 2024 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package testlib
import (
"net"
"net/url"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.pinniped.dev/internal/certauthority"
)
type SupervisorIssuer struct {
issuerURL *url.URL
ip net.IP
alternativeNames []string
}
func NewSupervisorIssuer(t *testing.T, issuer string) *SupervisorIssuer {
t.Helper()
t.Logf("NewSupervisorIssuer: %s", issuer)
issuerURL, err := url.Parse(issuer)
require.NoError(t, err)
require.NotEmpty(t, issuerURL.Hostname(), "hostname cannot be empty, usually this happens when the scheme is empty. issuer=%q", issuer)
ip := net.ParseIP(issuerURL.Hostname())
return &SupervisorIssuer{
issuerURL: issuerURL,
ip: ip,
}
}
func (s *SupervisorIssuer) AddPathSuffix(path string) {
s.issuerURL.Path += path
}
// AddAlternativeName adds a SAN for the cert. It is not intended to take an IP address as its argument.
func (s *SupervisorIssuer) AddAlternativeName(san string) {
s.alternativeNames = append(s.alternativeNames, san)
}
func (s *SupervisorIssuer) Issuer() string {
return s.issuerURL.String()
}
func (s *SupervisorIssuer) Address() string {
return s.issuerURL.Host
}
func (s *SupervisorIssuer) Hostname() string {
return s.issuerURL.Hostname()
}
func (s *SupervisorIssuer) Port(defaultPort string) string {
port := s.issuerURL.Port()
if port == "" {
return defaultPort
}
return s.issuerURL.Port()
}
func (s *SupervisorIssuer) hostnamesForCert() []string {
var hostnames []string
if !s.IsIPAddress() {
hostnames = append(hostnames, s.issuerURL.Hostname())
}
if s.alternativeNames != nil {
hostnames = append(hostnames, s.alternativeNames...)
}
return hostnames
}
func (s *SupervisorIssuer) ipsForCert() []net.IP {
if !s.IsIPAddress() {
return nil
}
return []net.IP{s.ip}
}
func (s *SupervisorIssuer) IssuerServerCert(
t *testing.T,
ca *certauthority.CA,
) ([]byte, []byte) {
t.Helper()
cert, err := ca.IssueServerCert(s.hostnamesForCert(), s.ipsForCert(), 24*time.Hour)
require.NoError(t, err)
certPEM, keyPEM, err := certauthority.ToPEM(cert)
require.NoError(t, err)
t.Logf("issued server cert for Supervisor: hostname=%+v, ips=%+v\n%s",
s.hostnamesForCert(), s.ipsForCert(),
certPEM)
return certPEM, keyPEM
}
func (s *SupervisorIssuer) IsIPAddress() bool {
return s.ip != nil
}