mirror of
https://github.com/outbackdingo/certificates.git
synced 2026-01-27 10:18:34 +00:00
Refactor preparation of test SCEP CAs
This commit is contained in:
@@ -2,6 +2,7 @@ package sceptest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -17,6 +19,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -25,14 +28,19 @@ import (
|
||||
|
||||
"github.com/smallstep/pkcs7"
|
||||
"github.com/smallstep/scep"
|
||||
"go.step.sm/crypto/keyutil"
|
||||
"go.step.sm/crypto/minica"
|
||||
"go.step.sm/crypto/pemutil"
|
||||
"go.step.sm/crypto/x509util"
|
||||
|
||||
"github.com/smallstep/certificates/authority/config"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/ca"
|
||||
"github.com/smallstep/certificates/cas/apiv1"
|
||||
)
|
||||
|
||||
func newCAClient(t *testing.T, caURL, rootFilepath string) *ca.Client {
|
||||
t.Helper()
|
||||
caClient, err := ca.NewClient(
|
||||
caURL,
|
||||
ca.WithRootFile(rootFilepath),
|
||||
@@ -72,6 +80,86 @@ func reservePort(t *testing.T) (host, port string) {
|
||||
return
|
||||
}
|
||||
|
||||
type testCA struct {
|
||||
ca *ca.CA
|
||||
caURL string
|
||||
rootFilepath string
|
||||
root *x509.Certificate
|
||||
}
|
||||
|
||||
func (t *testCA) run() error {
|
||||
return t.ca.Run()
|
||||
}
|
||||
|
||||
func (t *testCA) stop() error {
|
||||
return t.ca.Stop()
|
||||
}
|
||||
|
||||
func newTestCA(t *testing.T, name string) *testCA {
|
||||
t.Helper()
|
||||
|
||||
signer, err := keyutil.GenerateSigner("RSA", "", 2048)
|
||||
require.NoError(t, err)
|
||||
|
||||
dir := t.TempDir()
|
||||
m, err := minica.New(minica.WithName(name), minica.WithGetSignerFunc(func() (crypto.Signer, error) {
|
||||
return signer, nil
|
||||
}))
|
||||
require.NoError(t, err)
|
||||
|
||||
rootFilepath := filepath.Join(dir, "root.crt")
|
||||
_, err = pemutil.Serialize(m.Root, pemutil.WithFilename(rootFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateCertFilepath := filepath.Join(dir, "intermediate.crt")
|
||||
_, err = pemutil.Serialize(m.Intermediate, pemutil.WithFilename(intermediateCertFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateKeyFilepath := filepath.Join(dir, "intermediate.key")
|
||||
_, err = pemutil.Serialize(m.Signer, pemutil.WithFilename(intermediateKeyFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
// get a random address to listen on and connect to; currently no nicer way to get one before starting the server
|
||||
host, port := reservePort(t)
|
||||
|
||||
prov := &provisioner.SCEP{
|
||||
ID: "scep",
|
||||
Name: "scep",
|
||||
Type: "SCEP",
|
||||
ForceCN: false,
|
||||
ChallengePassword: "",
|
||||
EncryptionAlgorithmIdentifier: 2,
|
||||
MinimumPublicKeyLength: 2048,
|
||||
Claims: &config.GlobalProvisionerClaims,
|
||||
}
|
||||
|
||||
err = prov.Init(provisioner.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &config.Config{
|
||||
Root: []string{rootFilepath},
|
||||
IntermediateCert: intermediateCertFilepath,
|
||||
IntermediateKey: intermediateKeyFilepath,
|
||||
Address: net.JoinHostPort(host, port), // reuse the address that was just "reserved"
|
||||
DNSNames: []string{"127.0.0.1", "[::1]", "localhost"},
|
||||
AuthorityConfig: &config.AuthConfig{
|
||||
AuthorityID: "stepca-test-scep",
|
||||
DeploymentType: "standalone-test",
|
||||
Provisioners: provisioner.List{prov},
|
||||
},
|
||||
Logger: json.RawMessage(`{"format": "text"}`),
|
||||
}
|
||||
c, err := ca.New(cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return &testCA{
|
||||
ca: c,
|
||||
caURL: fmt.Sprintf("https://localhost:%s", port),
|
||||
rootFilepath: rootFilepath,
|
||||
root: m.Root,
|
||||
}
|
||||
}
|
||||
|
||||
type client struct {
|
||||
caURL string
|
||||
caCert *x509.Certificate
|
||||
@@ -90,7 +178,7 @@ func createSCEPClient(t *testing.T, caURL string, root *x509.Certificate) *clien
|
||||
Transport: transport,
|
||||
}
|
||||
return &client{
|
||||
caURL: caURL,
|
||||
caURL: fmt.Sprintf("%s/scep/scep", caURL),
|
||||
httpClient: httpClient,
|
||||
}
|
||||
}
|
||||
@@ -301,7 +389,7 @@ func (c *client) requestCertificateEmulatingWindowsClient(t *testing.T, commonNa
|
||||
h := sha1.Sum(publicKeyBytes)
|
||||
subjectKeyId := h[:]
|
||||
|
||||
// add subject key ID extension
|
||||
// create subject key ID extension
|
||||
value, err = asn1.Marshal(subjectKeyId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed marshaling subject key ID: %w", err)
|
||||
|
||||
@@ -1,106 +1,40 @@
|
||||
package sceptest
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.step.sm/crypto/keyutil"
|
||||
"go.step.sm/crypto/minica"
|
||||
"go.step.sm/crypto/pemutil"
|
||||
|
||||
"github.com/smallstep/certificates/authority/config"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/ca"
|
||||
)
|
||||
|
||||
func TestIssuesCertificateUsingRegularSCEPConfiguration(t *testing.T) {
|
||||
signer, err := keyutil.GenerateSigner("RSA", "", 2048)
|
||||
require.NoError(t, err)
|
||||
|
||||
dir := t.TempDir()
|
||||
m, err := minica.New(minica.WithName("Step E2E | SCEP Regular"), minica.WithGetSignerFunc(func() (crypto.Signer, error) {
|
||||
return signer, nil
|
||||
}))
|
||||
require.NoError(t, err)
|
||||
|
||||
rootFilepath := filepath.Join(dir, "root.crt")
|
||||
_, err = pemutil.Serialize(m.Root, pemutil.WithFilename(rootFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateCertFilepath := filepath.Join(dir, "intermediate.crt")
|
||||
_, err = pemutil.Serialize(m.Intermediate, pemutil.WithFilename(intermediateCertFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateKeyFilepath := filepath.Join(dir, "intermediate.key")
|
||||
_, err = pemutil.Serialize(m.Signer, pemutil.WithFilename(intermediateKeyFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
// get a random address to listen on and connect to; currently no nicer way to get one before starting the server
|
||||
// TODO(hs): find/implement a nicer way to expose the CA URL, similar to how e.g. httptest.Server exposes it?
|
||||
host, port := reservePort(t)
|
||||
|
||||
prov := &provisioner.SCEP{
|
||||
ID: "scep",
|
||||
Name: "scep",
|
||||
Type: "SCEP",
|
||||
ForceCN: false,
|
||||
ChallengePassword: "",
|
||||
EncryptionAlgorithmIdentifier: 2,
|
||||
MinimumPublicKeyLength: 2048,
|
||||
Claims: &config.GlobalProvisionerClaims,
|
||||
}
|
||||
|
||||
err = prov.Init(provisioner.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &config.Config{
|
||||
Root: []string{rootFilepath},
|
||||
IntermediateCert: intermediateCertFilepath,
|
||||
IntermediateKey: intermediateKeyFilepath,
|
||||
Address: net.JoinHostPort(host, port), // reuse the address that was just "reserved"
|
||||
DNSNames: []string{"127.0.0.1", "[::1]", "localhost"},
|
||||
AuthorityConfig: &config.AuthConfig{
|
||||
AuthorityID: "stepca-test-scep",
|
||||
DeploymentType: "standalone-test",
|
||||
Provisioners: provisioner.List{prov},
|
||||
},
|
||||
Logger: json.RawMessage(`{"format": "text"}`),
|
||||
}
|
||||
c, err := ca.New(cfg)
|
||||
require.NoError(t, err)
|
||||
c := newTestCA(t, "Step E2E | SCEP Regular")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err = c.Run()
|
||||
err := c.run()
|
||||
require.ErrorIs(t, err, http.ErrServerClosed)
|
||||
}()
|
||||
|
||||
// instantiate a client for the CA running at the random address
|
||||
caClient := newCAClient(t, fmt.Sprintf("https://localhost:%s", port), rootFilepath)
|
||||
caClient := newCAClient(t, c.caURL, c.rootFilepath)
|
||||
requireHealthyCA(t, caClient)
|
||||
|
||||
scepClient := createSCEPClient(t, fmt.Sprintf("https://localhost:%s/scep/scep", port), m.Root)
|
||||
scepClient := createSCEPClient(t, c.caURL, c.root)
|
||||
cert, err := scepClient.requestCertificate(t, "test.localhost", []string{"test.localhost"})
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, cert)
|
||||
|
||||
assert.Equal(t, "test.localhost", cert.Subject.CommonName)
|
||||
assert.Equal(t, "Step E2E | SCEP Regular Intermediate CA", cert.Issuer.CommonName)
|
||||
|
||||
// done testing; stop and wait for the server to quit
|
||||
err = c.Stop()
|
||||
err = c.stop()
|
||||
require.NoError(t, err)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
@@ -3,26 +3,15 @@
|
||||
package sceptest
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.step.sm/crypto/keyutil"
|
||||
"go.step.sm/crypto/minica"
|
||||
"go.step.sm/crypto/pemutil"
|
||||
|
||||
"github.com/smallstep/certificates/authority/config"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/ca"
|
||||
legacyx509 "github.com/smallstep/certificates/test/integration/scep/internal/x509"
|
||||
)
|
||||
|
||||
@@ -36,77 +25,24 @@ func legacyCertificateParser(der []byte) (*x509.Certificate, error) {
|
||||
}
|
||||
|
||||
func TestIssuesCertificateToEmulatedWindowsClientGo123(t *testing.T) {
|
||||
signer, err := keyutil.GenerateSigner("RSA", "", 2048)
|
||||
require.NoError(t, err)
|
||||
|
||||
dir := t.TempDir()
|
||||
m, err := minica.New(minica.WithName("Step E2E | SCEP Regular w/ Windows Client"), minica.WithGetSignerFunc(func() (crypto.Signer, error) {
|
||||
return signer, nil
|
||||
}))
|
||||
require.NoError(t, err)
|
||||
|
||||
rootFilepath := filepath.Join(dir, "root.crt")
|
||||
_, err = pemutil.Serialize(m.Root, pemutil.WithFilename(rootFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateCertFilepath := filepath.Join(dir, "intermediate.crt")
|
||||
_, err = pemutil.Serialize(m.Intermediate, pemutil.WithFilename(intermediateCertFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateKeyFilepath := filepath.Join(dir, "intermediate.key")
|
||||
_, err = pemutil.Serialize(m.Signer, pemutil.WithFilename(intermediateKeyFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
// get a random address to listen on and connect to; currently no nicer way to get one before starting the server
|
||||
// TODO(hs): find/implement a nicer way to expose the CA URL, similar to how e.g. httptest.Server exposes it?
|
||||
host, port := reservePort(t)
|
||||
|
||||
prov := &provisioner.SCEP{
|
||||
ID: "scep",
|
||||
Name: "scep",
|
||||
Type: "SCEP",
|
||||
ForceCN: false,
|
||||
ChallengePassword: "",
|
||||
EncryptionAlgorithmIdentifier: 2,
|
||||
MinimumPublicKeyLength: 2048,
|
||||
Claims: &config.GlobalProvisionerClaims,
|
||||
}
|
||||
|
||||
err = prov.Init(provisioner.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &config.Config{
|
||||
Root: []string{rootFilepath},
|
||||
IntermediateCert: intermediateCertFilepath,
|
||||
IntermediateKey: intermediateKeyFilepath,
|
||||
Address: net.JoinHostPort(host, port), // reuse the address that was just "reserved"
|
||||
DNSNames: []string{"127.0.0.1", "[::1]", "localhost"},
|
||||
AuthorityConfig: &config.AuthConfig{
|
||||
AuthorityID: "stepca-test-scep",
|
||||
DeploymentType: "standalone-test",
|
||||
Provisioners: provisioner.List{prov},
|
||||
},
|
||||
Logger: json.RawMessage(`{"format": "text"}`),
|
||||
}
|
||||
c, err := ca.New(cfg)
|
||||
require.NoError(t, err)
|
||||
c := newTestCA(t, "Step E2E | SCEP Regular w/ Windows Client")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err = c.Run()
|
||||
err := c.Run()
|
||||
require.ErrorIs(t, err, http.ErrServerClosed)
|
||||
}()
|
||||
|
||||
// instantiate a client for the CA running at the random address
|
||||
caClient := newCAClient(t, fmt.Sprintf("https://localhost:%s", port), rootFilepath)
|
||||
caClient := newCAClient(t, c.caURL, c.rootFilepath)
|
||||
requireHealthyCA(t, caClient)
|
||||
|
||||
scepClient := createSCEPClient(t, fmt.Sprintf("https://localhost:%s/scep/scep", port), m.Root)
|
||||
scepClient := createSCEPClient(t, c.caURL, c.root)
|
||||
cert, err := scepClient.requestCertificateEmulatingWindowsClient(t, "test.localhost", []string{"test.localhost"}, legacyCertificateParser)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, cert)
|
||||
|
||||
assert.Equal(t, "test.localhost", cert.Subject.CommonName)
|
||||
|
||||
@@ -3,107 +3,40 @@
|
||||
package sceptest
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.step.sm/crypto/keyutil"
|
||||
"go.step.sm/crypto/minica"
|
||||
"go.step.sm/crypto/pemutil"
|
||||
|
||||
"github.com/smallstep/certificates/authority/config"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/ca"
|
||||
)
|
||||
|
||||
func TestIssuesCertificateToEmulatedWindowsClient(t *testing.T) {
|
||||
signer, err := keyutil.GenerateSigner("RSA", "", 2048)
|
||||
require.NoError(t, err)
|
||||
|
||||
dir := t.TempDir()
|
||||
m, err := minica.New(minica.WithName("Step E2E | SCEP Regular w/ Windows Client"), minica.WithGetSignerFunc(func() (crypto.Signer, error) {
|
||||
return signer, nil
|
||||
}))
|
||||
require.NoError(t, err)
|
||||
|
||||
rootFilepath := filepath.Join(dir, "root.crt")
|
||||
_, err = pemutil.Serialize(m.Root, pemutil.WithFilename(rootFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateCertFilepath := filepath.Join(dir, "intermediate.crt")
|
||||
_, err = pemutil.Serialize(m.Intermediate, pemutil.WithFilename(intermediateCertFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
intermediateKeyFilepath := filepath.Join(dir, "intermediate.key")
|
||||
_, err = pemutil.Serialize(m.Signer, pemutil.WithFilename(intermediateKeyFilepath))
|
||||
require.NoError(t, err)
|
||||
|
||||
// get a random address to listen on and connect to; currently no nicer way to get one before starting the server
|
||||
// TODO(hs): find/implement a nicer way to expose the CA URL, similar to how e.g. httptest.Server exposes it?
|
||||
host, port := reservePort(t)
|
||||
|
||||
prov := &provisioner.SCEP{
|
||||
ID: "scep",
|
||||
Name: "scep",
|
||||
Type: "SCEP",
|
||||
ForceCN: false,
|
||||
ChallengePassword: "",
|
||||
EncryptionAlgorithmIdentifier: 2,
|
||||
MinimumPublicKeyLength: 2048,
|
||||
Claims: &config.GlobalProvisionerClaims,
|
||||
}
|
||||
|
||||
err = prov.Init(provisioner.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &config.Config{
|
||||
Root: []string{rootFilepath},
|
||||
IntermediateCert: intermediateCertFilepath,
|
||||
IntermediateKey: intermediateKeyFilepath,
|
||||
Address: net.JoinHostPort(host, port), // reuse the address that was just "reserved"
|
||||
DNSNames: []string{"127.0.0.1", "[::1]", "localhost"},
|
||||
AuthorityConfig: &config.AuthConfig{
|
||||
AuthorityID: "stepca-test-scep",
|
||||
DeploymentType: "standalone-test",
|
||||
Provisioners: provisioner.List{prov},
|
||||
},
|
||||
Logger: json.RawMessage(`{"format": "text"}`),
|
||||
}
|
||||
c, err := ca.New(cfg)
|
||||
require.NoError(t, err)
|
||||
c := newTestCA(t, "Step E2E | SCEP Regular w/ Windows Client")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err = c.Run()
|
||||
err := c.run()
|
||||
require.ErrorIs(t, err, http.ErrServerClosed)
|
||||
}()
|
||||
|
||||
// instantiate a client for the CA running at the random address
|
||||
caClient := newCAClient(t, fmt.Sprintf("https://localhost:%s", port), rootFilepath)
|
||||
caClient := newCAClient(t, c.caURL, c.rootFilepath)
|
||||
requireHealthyCA(t, caClient)
|
||||
|
||||
scepClient := createSCEPClient(t, fmt.Sprintf("https://localhost:%s/scep/scep", port), m.Root)
|
||||
scepClient := createSCEPClient(t, c.caURL, c.root)
|
||||
cert, err := scepClient.requestCertificateEmulatingWindowsClient(t, "test.localhost", []string{"test.localhost"}, x509.ParseCertificate)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, cert)
|
||||
|
||||
assert.Equal(t, "test.localhost", cert.Subject.CommonName)
|
||||
assert.Equal(t, "Step E2E | SCEP Regular w/ Windows Client Intermediate CA", cert.Issuer.CommonName)
|
||||
|
||||
// done testing; stop and wait for the server to quit
|
||||
err = c.Stop()
|
||||
err = c.stop()
|
||||
require.NoError(t, err)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
Reference in New Issue
Block a user