Files
certman/certificate/certificate_test.go
Björn Benouarets d9726d9204 feat: add certificate service and utility functions
- 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
2025-09-30 11:45:05 +02:00

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)
}
}
}