
- Implement CertificateService for end-to-end certificate management - Add support for various certificate types (web, client, email, etc.) - Include certificate generation, validation, and revocation - Add utility functions for certificate operations and validation - Implement comprehensive test coverage for certificate operations - Support SAN (Subject Alternative Name) and IP address extensions - Add proper error handling and validation for certificate requests
404 lines
11 KiB
Go
404 lines
11 KiB
Go
package certificate
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.secnex.io/secnex/certman/models"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func TestCreateCertificateRequest(t *testing.T) {
|
|
service := &CertificateService{}
|
|
|
|
tests := []struct {
|
|
name string
|
|
req *CreateCertificateRequest
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid web certificate request",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test Web Certificate",
|
|
CommonName: "example.com",
|
|
Organization: "Test Org",
|
|
Country: "DE",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid client certificate request",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test Client Certificate",
|
|
CommonName: "user@example.com",
|
|
Organization: "Test Org",
|
|
Country: "DE",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeClient,
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid IoT certificate request",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test IoT Certificate",
|
|
CommonName: "device.example.com",
|
|
Organization: "Test Org",
|
|
Country: "DE",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeIoT,
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "missing name",
|
|
req: &CreateCertificateRequest{
|
|
CommonName: "example.com",
|
|
Organization: "Test Org",
|
|
Country: "DE",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing common name",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test Certificate",
|
|
Organization: "Test Org",
|
|
Country: "DE",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing organization",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test Certificate",
|
|
CommonName: "example.com",
|
|
Country: "DE",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing country",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test Certificate",
|
|
CommonName: "example.com",
|
|
Organization: "Test Org",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing CA ID",
|
|
req: &CreateCertificateRequest{
|
|
Name: "Test Certificate",
|
|
CommonName: "example.com",
|
|
Organization: "Test Org",
|
|
Country: "DE",
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
err := service.validateCreateCertificateRequest(test.req)
|
|
if (err != nil) != test.wantErr {
|
|
t.Errorf("validateCreateCertificateRequest() error = %v, wantErr %v", err, test.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCreateCertificateFromCSRRequest(t *testing.T) {
|
|
service := &CertificateService{}
|
|
|
|
tests := []struct {
|
|
name string
|
|
req *CreateCertificateFromCSRRequest
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid CSR request",
|
|
req: &CreateCertificateFromCSRRequest{
|
|
Name: "Test Certificate from CSR",
|
|
CSRID: uuid.New(),
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "missing name",
|
|
req: &CreateCertificateFromCSRRequest{
|
|
CSRID: uuid.New(),
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing CSR ID",
|
|
req: &CreateCertificateFromCSRRequest{
|
|
Name: "Test Certificate from CSR",
|
|
CertificateAuthorityID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing CA ID",
|
|
req: &CreateCertificateFromCSRRequest{
|
|
Name: "Test Certificate from CSR",
|
|
CSRID: uuid.New(),
|
|
Type: models.CertificateTypeWeb,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
err := service.validateCreateCertificateFromCSRRequest(test.req)
|
|
if (err != nil) != test.wantErr {
|
|
t.Errorf("validateCreateCertificateFromCSRRequest() error = %v, wantErr %v", err, test.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCertificateRequestStructures(t *testing.T) {
|
|
// Test CreateCertificateRequest structure
|
|
req := &CreateCertificateRequest{
|
|
Name: "Test Certificate",
|
|
Description: "Test Description",
|
|
CommonName: "test.example.com",
|
|
Organization: "Test Organization",
|
|
OrganizationalUnit: "Test Unit",
|
|
Country: "DE",
|
|
State: "Bavaria",
|
|
Locality: "Munich",
|
|
Street: "Test Street",
|
|
Address: "Test Address",
|
|
PostalCode: "80331",
|
|
Email: "test@example.com",
|
|
Type: models.CertificateTypeWeb,
|
|
CertificateAuthorityID: uuid.New(),
|
|
NotAfter: func() *time.Time { t := time.Now().AddDate(1, 0, 0); return &t }(),
|
|
DNSNames: []string{"test.example.com", "www.test.example.com"},
|
|
IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
|
|
EmailAddresses: []string{"test@example.com"},
|
|
URIs: []string{"https://test.example.com"},
|
|
KeyType: "rsa",
|
|
KeySize: 2048,
|
|
Curve: "P-256",
|
|
KeyUsage: &KeyUsageConfig{
|
|
DigitalSignature: true,
|
|
KeyEncipherment: true,
|
|
},
|
|
ExtendedKeyUsage: &ExtendedKeyUsageConfig{
|
|
ServerAuth: true,
|
|
},
|
|
}
|
|
|
|
if req.Name == "" {
|
|
t.Error("Certificate request name should not be empty")
|
|
}
|
|
if req.CommonName == "" {
|
|
t.Error("Certificate request common name should not be empty")
|
|
}
|
|
if req.CertificateAuthorityID == uuid.Nil {
|
|
t.Error("Certificate request CA ID should not be nil")
|
|
}
|
|
if req.Type == "" {
|
|
t.Error("Certificate request type should not be empty")
|
|
}
|
|
if len(req.DNSNames) == 0 {
|
|
t.Error("Certificate request should have DNS names")
|
|
}
|
|
if len(req.IPAddresses) == 0 {
|
|
t.Error("Certificate request should have IP addresses")
|
|
}
|
|
if req.KeyUsage == nil {
|
|
t.Error("Certificate request should have key usage")
|
|
}
|
|
if req.ExtendedKeyUsage == nil {
|
|
t.Error("Certificate request should have extended key usage")
|
|
}
|
|
}
|
|
|
|
func TestKeyUsageConfig(t *testing.T) {
|
|
keyUsage := &KeyUsageConfig{
|
|
DigitalSignature: true,
|
|
KeyEncipherment: true,
|
|
}
|
|
|
|
if !keyUsage.DigitalSignature {
|
|
t.Error("Digital signature should be enabled")
|
|
}
|
|
if !keyUsage.KeyEncipherment {
|
|
t.Error("Key encipherment should be enabled")
|
|
}
|
|
}
|
|
|
|
func TestExtendedKeyUsageConfig(t *testing.T) {
|
|
extKeyUsage := &ExtendedKeyUsageConfig{
|
|
ServerAuth: true,
|
|
ClientAuth: false,
|
|
}
|
|
|
|
if !extKeyUsage.ServerAuth {
|
|
t.Error("Server auth should be enabled")
|
|
}
|
|
if extKeyUsage.ClientAuth {
|
|
t.Error("Client auth should be disabled")
|
|
}
|
|
}
|
|
|
|
func TestCertificateServiceCreation(t *testing.T) {
|
|
// Test that we can create a service instance
|
|
service := NewCertificateService(nil, "/tmp/certs", "/tmp/private", nil)
|
|
|
|
if service == nil {
|
|
t.Error("CertificateService should not be nil")
|
|
}
|
|
|
|
if service.certDir != "/tmp/certs" {
|
|
t.Errorf("Expected certDir to be /tmp/certs, got %s", service.certDir)
|
|
}
|
|
|
|
if service.privateDir != "/tmp/private" {
|
|
t.Errorf("Expected privateDir to be /tmp/private, got %s", service.privateDir)
|
|
}
|
|
}
|
|
|
|
func TestCertificateTypes(t *testing.T) {
|
|
// Test that all certificate types are defined
|
|
certTypes := []models.CertificateType{
|
|
models.CertificateTypeWeb,
|
|
models.CertificateTypeServer,
|
|
models.CertificateTypeClient,
|
|
models.CertificateTypeUser,
|
|
models.CertificateTypeEmail,
|
|
models.CertificateTypeCode,
|
|
models.CertificateTypeCA,
|
|
models.CertificateTypeIoT,
|
|
models.CertificateTypeDevice,
|
|
models.CertificateTypeSensor,
|
|
models.CertificateTypeVPN,
|
|
models.CertificateTypeOpenVPN,
|
|
models.CertificateTypeWireGuard,
|
|
models.CertificateTypeDatabase,
|
|
models.CertificateTypeMySQL,
|
|
models.CertificateTypePostgreSQL,
|
|
models.CertificateTypeMongoDB,
|
|
models.CertificateTypeAPI,
|
|
models.CertificateTypeService,
|
|
models.CertificateTypeMicroservice,
|
|
models.CertificateTypeDocker,
|
|
models.CertificateTypeKubernetes,
|
|
models.CertificateTypeContainer,
|
|
models.CertificateTypeCloud,
|
|
models.CertificateTypeAWS,
|
|
models.CertificateTypeAzure,
|
|
models.CertificateTypeGCP,
|
|
models.CertificateTypeNetwork,
|
|
models.CertificateTypeFirewall,
|
|
models.CertificateTypeProxy,
|
|
models.CertificateTypeLoadBalancer,
|
|
models.CertificateTypeMobile,
|
|
models.CertificateTypeAndroid,
|
|
models.CertificateTypeiOS,
|
|
models.CertificateTypeApp,
|
|
models.CertificateTypeDocument,
|
|
models.CertificateTypePDF,
|
|
models.CertificateTypeOffice,
|
|
models.CertificateTypeTimestamp,
|
|
models.CertificateTypeOCSP,
|
|
models.CertificateTypeCustom,
|
|
models.CertificateTypeSpecial,
|
|
}
|
|
|
|
for _, certType := range certTypes {
|
|
if certType == "" {
|
|
t.Errorf("Certificate type should not be empty")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCertificateTypeCategories(t *testing.T) {
|
|
// Test web certificates
|
|
webTypes := []models.CertificateType{
|
|
models.CertificateTypeWeb,
|
|
models.CertificateTypeServer,
|
|
}
|
|
|
|
for _, certType := range webTypes {
|
|
if certType == "" {
|
|
t.Errorf("Web certificate type should not be empty: %s", certType)
|
|
}
|
|
}
|
|
|
|
// Test client certificates
|
|
clientTypes := []models.CertificateType{
|
|
models.CertificateTypeClient,
|
|
models.CertificateTypeUser,
|
|
}
|
|
|
|
for _, certType := range clientTypes {
|
|
if certType == "" {
|
|
t.Errorf("Client certificate type should not be empty: %s", certType)
|
|
}
|
|
}
|
|
|
|
// Test IoT certificates
|
|
iotTypes := []models.CertificateType{
|
|
models.CertificateTypeIoT,
|
|
models.CertificateTypeDevice,
|
|
models.CertificateTypeSensor,
|
|
}
|
|
|
|
for _, certType := range iotTypes {
|
|
if certType == "" {
|
|
t.Errorf("IoT certificate type should not be empty: %s", certType)
|
|
}
|
|
}
|
|
|
|
// Test VPN certificates
|
|
vpnTypes := []models.CertificateType{
|
|
models.CertificateTypeVPN,
|
|
models.CertificateTypeOpenVPN,
|
|
models.CertificateTypeWireGuard,
|
|
}
|
|
|
|
for _, certType := range vpnTypes {
|
|
if certType == "" {
|
|
t.Errorf("VPN certificate type should not be empty: %s", certType)
|
|
}
|
|
}
|
|
|
|
// Test database certificates
|
|
dbTypes := []models.CertificateType{
|
|
models.CertificateTypeDatabase,
|
|
models.CertificateTypeMySQL,
|
|
models.CertificateTypePostgreSQL,
|
|
models.CertificateTypeMongoDB,
|
|
}
|
|
|
|
for _, certType := range dbTypes {
|
|
if certType == "" {
|
|
t.Errorf("Database certificate type should not be empty: %s", certType)
|
|
}
|
|
}
|
|
}
|