Files
Dušan Borovčanin 61d0427898 NOISSUE - Rename to Magistrala (#3427)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 15:23:42 +02:00

1033 lines
27 KiB
Go

// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package sdk_test
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/absmach/magistrala/certs"
httpapi "github.com/absmach/magistrala/certs/api/http"
"github.com/absmach/magistrala/certs/mocks"
mglog "github.com/absmach/magistrala/logger"
smqauthn "github.com/absmach/magistrala/pkg/authn"
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
"github.com/absmach/magistrala/pkg/errors"
"github.com/absmach/magistrala/pkg/sdk"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
const (
certsInstanceID = "5de9b29a-feb9-11ed-be56-0242ac120002"
certsContentType = "application/senml+json"
serialNum = "8e7a30c-bc9f-22de-ae67-1342bc139507"
certsID = "c333e6f-59bb-4c39-9e13-3a2766af8ba5"
ttl = "10h"
commonName = "test"
token = "token"
agentToken = "agent-token"
certsDomainID = "domain-certsID"
)
func setupCerts() (*httptest.Server, *mocks.Service, *authnmocks.Authentication) {
svc := new(mocks.Service)
logger := mglog.NewMock()
authn := new(authnmocks.Authentication)
am := smqauthn.NewAuthNMiddleware(authn, smqauthn.WithAllowUnverifiedUser(true))
handler := httpapi.MakeHandler(svc, am, logger, certsInstanceID, agentToken)
return httptest.NewServer(handler), svc, authn
}
func TestIssueCert(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
ipAddr := []string{"192.128.101.82"}
cases := []struct {
desc string
entityID string
ttl string
ipAddrs []string
commonName string
svcresp certs.Certificate
svcerr error
authenticateErr error
err errors.SDKError
sdkCert sdk.Certificate
domain string
token string
session smqauthn.Session
}{
{
desc: "IssueCert success",
entityID: certsID,
ttl: ttl,
ipAddrs: ipAddr,
commonName: commonName,
svcresp: certs.Certificate{
SerialNumber: serialNum,
},
sdkCert: sdk.Certificate{
SerialNumber: serialNum,
},
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "IssueCert failure",
entityID: certsID,
ttl: ttl,
ipAddrs: ipAddr,
commonName: commonName,
svcresp: certs.Certificate{},
svcerr: certs.ErrCreateEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrCreateEntity, http.StatusUnprocessableEntity),
domain: certsDomainID,
token: token,
},
{
desc: "IssueCert with empty entityID",
entityID: `""`,
ttl: ttl,
ipAddrs: ipAddr,
commonName: commonName,
svcresp: certs.Certificate{},
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
domain: certsDomainID,
token: token,
},
{
desc: "IssueCert with empty ipAddrs",
entityID: certsID,
ttl: ttl,
commonName: commonName,
svcresp: certs.Certificate{SerialNumber: serialNum},
sdkCert: sdk.Certificate{
SerialNumber: serialNum,
},
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "IssueCert with empty ttl",
entityID: certsID,
ttl: "",
ipAddrs: ipAddr,
commonName: commonName,
svcresp: certs.Certificate{SerialNumber: serialNum},
sdkCert: sdk.Certificate{
SerialNumber: serialNum,
},
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "IssueCert with empty commonName",
entityID: certsID,
ttl: ttl,
ipAddrs: ipAddr,
commonName: "",
svcresp: certs.Certificate{},
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
domain: certsDomainID,
token: token,
},
{
desc: "IssueCert with empty token",
entityID: certsID,
ttl: ttl,
ipAddrs: ipAddr,
commonName: commonName,
svcresp: certs.Certificate{},
svcerr: nil,
err: errors.NewSDKErrorWithStatus(errors.New("missing or invalid bearer user token"), http.StatusUnauthorized),
domain: certsDomainID,
token: "",
},
{
desc: "IssueCert with empty domain",
entityID: certsID,
ttl: ttl,
ipAddrs: ipAddr,
commonName: commonName,
svcresp: certs.Certificate{},
svcerr: nil,
err: errors.NewSDKErrorWithStatus(errors.New("missing domainID"), http.StatusBadRequest),
domain: "",
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("IssueCert", mock.Anything, tc.session, tc.entityID, tc.ttl, tc.ipAddrs, certs.SubjectOptions{CommonName: tc.commonName}).Return(tc.svcresp, tc.svcerr)
resp, err := ctsdk.IssueCert(context.Background(), tc.entityID, tc.ttl, tc.ipAddrs, sdk.Options{CommonName: tc.commonName}, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
assert.Equal(t, tc.sdkCert.SerialNumber, resp.SerialNumber)
ok := svcCall.Parent.AssertCalled(t, "IssueCert", mock.Anything, tc.session, tc.entityID, tc.ttl, tc.ipAddrs, certs.SubjectOptions{CommonName: tc.commonName})
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRevokeCert(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cases := []struct {
desc string
serial string
svcresp string
svcerr error
authenticateErr error
err errors.SDKError
domain string
token string
session smqauthn.Session
}{
{
desc: "RevokeCert success",
serial: serialNum,
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "RevokeCert failure",
serial: serialNum,
svcerr: certs.ErrUpdateEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrUpdateEntity, http.StatusUnprocessableEntity),
domain: certsDomainID,
token: token,
},
{
desc: "RevokeCert with empty serial",
serial: "",
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
domain: certsDomainID,
token: token,
},
{
desc: "RevokeCert with empty token",
serial: serialNum,
svcerr: nil,
err: errors.NewSDKErrorWithStatus(errors.New("missing or invalid bearer user token"), http.StatusUnauthorized),
domain: certsDomainID,
token: "",
},
{
desc: "RevokeCert with empty domain",
serial: serialNum,
svcerr: nil,
err: errors.NewSDKErrorWithStatus(errors.New("missing domainID"), http.StatusBadRequest),
domain: "",
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("RevokeBySerial", mock.Anything, tc.session, tc.serial).Return(tc.svcerr)
err := ctsdk.RevokeCert(context.Background(), tc.serial, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.desc != "RevokeCert with empty serial" && tc.desc != "RevokeCert with empty token" && tc.desc != "RevokeCert with empty domain" {
ok := svcCall.Parent.AssertCalled(t, "RevokeBySerial", mock.Anything, tc.session, tc.serial)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestDeleteCert(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cases := []struct {
desc string
entityID string
svcresp string
svcerr error
authenticateErr error
err errors.SDKError
domain string
token string
session smqauthn.Session
}{
{
desc: "DeleteCert success",
entityID: certsID,
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "DeleteCert failure",
entityID: certsID,
svcerr: certs.ErrUpdateEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrUpdateEntity, http.StatusUnprocessableEntity),
domain: certsDomainID,
token: token,
},
{
desc: "DeleteCert with empty entity certsID",
entityID: "",
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
domain: certsDomainID,
token: token,
},
{
desc: "DeleteCert with empty token",
entityID: certsID,
svcerr: nil,
err: errors.NewSDKErrorWithStatus(errors.New("missing or invalid bearer user token"), http.StatusUnauthorized),
domain: certsDomainID,
token: "",
},
{
desc: "DeleteCert with empty domain",
entityID: certsID,
svcerr: nil,
err: errors.NewSDKErrorWithStatus(errors.New("missing domainID"), http.StatusBadRequest),
domain: "",
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("RevokeAll", mock.Anything, tc.session, tc.entityID).Return(tc.svcerr)
err := ctsdk.DeleteCert(context.Background(), tc.entityID, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.desc != "DeleteCert with empty entity certsID" && tc.desc != "DeleteCert with empty token" && tc.desc != "DeleteCert with empty domain" {
ok := svcCall.Parent.AssertCalled(t, "RevokeAll", mock.Anything, tc.session, tc.entityID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRenewCert(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cases := []struct {
desc string
serial string
svcresp certs.Certificate
svcerr error
authenticateErr error
err errors.SDKError
expected sdk.Certificate
domain string
token string
session smqauthn.Session
}{
{
desc: "RenewCert success",
serial: serialNum,
svcresp: certs.Certificate{
SerialNumber: "new-serial-123",
EntityID: "test-entity",
},
svcerr: nil,
err: nil,
expected: sdk.Certificate{
SerialNumber: "new-serial-123",
EntityID: "test-entity",
},
domain: certsDomainID,
token: token,
},
{
desc: "RenewCert failure",
serial: serialNum,
svcresp: certs.Certificate{},
svcerr: certs.ErrUpdateEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrUpdateEntity, http.StatusUnprocessableEntity),
expected: sdk.Certificate{},
domain: certsDomainID,
token: token,
},
{
desc: "RenewCert with empty serial",
serial: "",
svcresp: certs.Certificate{},
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
expected: sdk.Certificate{},
domain: certsDomainID,
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("RenewCert", mock.Anything, tc.session, tc.serial).Return(tc.svcresp, tc.svcerr)
cert, err := ctsdk.RenewCert(context.Background(), tc.serial, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
assert.Equal(t, tc.expected, cert)
} else {
assert.Equal(t, sdk.Certificate{}, cert)
}
if tc.desc != "RenewCert with empty serial" {
ok := svcCall.Parent.AssertCalled(t, "RenewCert", mock.Anything, tc.session, tc.serial)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListCerts(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cases := []struct {
desc string
svcResp certs.CertificatePage
sdkPm sdk.PageMetadata
svcerr error
authenticateErr error
err errors.SDKError
domain string
token string
session smqauthn.Session
}{
{
desc: "ListCerts success",
sdkPm: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
svcResp: certs.CertificatePage{
PageMetadata: certs.PageMetadata{
Total: 1,
Offset: 0,
Limit: 10,
},
Certificates: []certs.Certificate{
{
SerialNumber: serialNum,
},
},
},
domain: certsDomainID,
token: token,
},
{
desc: "ListCerts success with entity certsID",
sdkPm: sdk.PageMetadata{
Offset: 0,
Limit: 10,
EntityID: certsID,
},
svcResp: certs.CertificatePage{
PageMetadata: certs.PageMetadata{
Total: 1,
Offset: 0,
Limit: 10,
},
Certificates: []certs.Certificate{
{
SerialNumber: serialNum,
EntityID: certsID,
},
},
},
domain: certsDomainID,
token: token,
},
{
desc: "ListCerts failure",
sdkPm: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
svcerr: certs.ErrViewEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrViewEntity, http.StatusUnprocessableEntity),
domain: certsDomainID,
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("ListCerts", mock.Anything, tc.session, mock.Anything).Return(tc.svcResp, tc.svcerr)
resp, err := ctsdk.ListCerts(context.Background(), tc.sdkPm, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
assert.Equal(t, tc.svcResp.Total, resp.Total)
assert.Equal(t, tc.svcResp.Certificates[0].SerialNumber, resp.Certificates[0].SerialNumber)
if tc.desc == "ListCerts success with entity certsID" {
assert.Equal(t, tc.svcResp.Certificates[0].EntityID, resp.Certificates[0].EntityID)
}
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestViewCert(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cert := sdk.Certificate{
SerialNumber: serialNum,
}
cases := []struct {
desc string
serial string
svcresp certs.Certificate
svcerr error
authenticateErr error
err errors.SDKError
sdkCert sdk.Certificate
domain string
token string
session smqauthn.Session
}{
{
desc: "ViewCert success",
serial: serialNum,
svcresp: certs.Certificate{
SerialNumber: serialNum,
},
sdkCert: cert,
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "ViewCert failure",
serial: serialNum,
svcresp: certs.Certificate{},
svcerr: certs.ErrViewEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrViewEntity, http.StatusUnprocessableEntity),
domain: certsDomainID,
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("ViewCert", mock.Anything, tc.session, tc.serial).Return(tc.svcresp, tc.svcerr)
c, err := ctsdk.ViewCert(context.Background(), tc.serial, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "ViewCert", mock.Anything, tc.session, tc.serial)
assert.True(t, ok)
}
assert.Equal(t, tc.sdkCert.SerialNumber, c.SerialNumber, fmt.Sprintf("expected: %v, got: %v", tc.sdkCert.SerialNumber, c.SerialNumber))
svcCall.Unset()
authCall.Unset()
})
}
}
func TestDownloadCACert(t *testing.T) {
ts, svc, _ := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cert := sdk.Certificate{
SerialNumber: serialNum,
}
cases := []struct {
desc string
svcresp certs.Certificate
svcerr error
err errors.SDKError
sdkCert sdk.Certificate
}{
{
desc: "Download CA successfully",
svcresp: certs.Certificate{
SerialNumber: serialNum,
Certificate: []byte("cert"),
Key: []byte("key"),
},
sdkCert: cert,
svcerr: nil,
err: nil,
},
{
desc: "Download CA failure",
svcresp: certs.Certificate{},
svcerr: certs.ErrViewEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrViewEntity, http.StatusUnprocessableEntity),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RetrieveCAChain", mock.Anything).Return(tc.svcresp, tc.svcerr)
_, err := ctsdk.DownloadCA(context.Background())
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RetrieveCAChain", mock.Anything)
assert.True(t, ok)
}
svcCall.Unset()
})
}
}
func TestViewCA(t *testing.T) {
ts, svc, _ := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cert := sdk.Certificate{
SerialNumber: serialNum,
Certificate: "cert",
Key: "Key",
}
cases := []struct {
desc string
svcresp certs.Certificate
svcerr error
err errors.SDKError
sdkCert sdk.Certificate
}{
{
desc: "ViewCA success",
svcresp: certs.Certificate{
Certificate: []byte("cert"),
},
sdkCert: cert,
svcerr: nil,
err: nil,
},
{
desc: "ViewCA failure",
svcresp: certs.Certificate{},
svcerr: certs.ErrViewEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrViewEntity, http.StatusUnprocessableEntity),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RetrieveCAChain", mock.Anything).Return(tc.svcresp, tc.svcerr)
c, err := ctsdk.ViewCA(context.Background())
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RetrieveCAChain", mock.Anything)
assert.True(t, ok)
}
assert.Equal(t, tc.sdkCert.Certificate, c.Certificate, fmt.Sprintf("expected: %v, got: %v", tc.sdkCert.Certificate, c.Certificate))
svcCall.Unset()
})
}
}
func TestGenerateCRL(t *testing.T) {
ts, svc, _ := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
crlData := []byte("mock-crl-data")
cases := []struct {
desc string
svcresp []byte
svcerr error
err errors.SDKError
}{
{
desc: "GenerateCRL success",
svcresp: crlData,
svcerr: nil,
err: nil,
},
{
desc: "GenerateCRL failure",
svcresp: nil,
svcerr: certs.ErrFailedCertCreation,
err: errors.NewSDKErrorWithStatus(certs.ErrFailedCertCreation, http.StatusUnprocessableEntity),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("GenerateCRL", mock.Anything).Return(tc.svcresp, tc.svcerr)
resp, err := ctsdk.GenerateCRL(context.Background())
assert.Equal(t, tc.err, err)
if tc.err == nil {
assert.Equal(t, tc.svcresp, resp)
ok := svcCall.Parent.AssertCalled(t, "GenerateCRL", mock.Anything)
assert.True(t, ok)
}
svcCall.Unset()
})
}
}
func TestRevokeAll(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cases := []struct {
desc string
entityID string
svcerr error
authenticateErr error
err errors.SDKError
domain string
token string
session smqauthn.Session
}{
{
desc: "RevokeAll success",
entityID: certsID,
svcerr: nil,
err: nil,
domain: certsDomainID,
token: token,
},
{
desc: "RevokeAll failure",
entityID: certsID,
svcerr: certs.ErrUpdateEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrUpdateEntity, http.StatusUnprocessableEntity),
domain: certsDomainID,
token: token,
},
{
desc: "RevokeAll with empty entityID",
entityID: "",
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
domain: certsDomainID,
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := svc.On("RevokeAll", mock.Anything, tc.session, tc.entityID).Return(tc.svcerr)
err := ctsdk.RevokeAll(context.Background(), tc.entityID, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
if tc.desc != "RevokeAll with empty entityID" {
ok := svcCall.Parent.AssertCalled(t, "RevokeAll", mock.Anything, tc.session, tc.entityID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestGetEntityID(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
entityID := "test-entity-certsID"
cases := []struct {
desc string
serial string
svcresp certs.Certificate
svcerr error
authenticateErr error
err errors.SDKError
expected string
domain string
token string
session smqauthn.Session
}{
{
desc: "GetEntityID success",
serial: serialNum,
svcresp: certs.Certificate{
SerialNumber: serialNum,
EntityID: entityID,
},
svcerr: nil,
err: nil,
expected: entityID,
domain: certsDomainID,
token: token,
},
{
desc: "GetEntityID failure",
serial: serialNum,
svcresp: certs.Certificate{},
svcerr: certs.ErrViewEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrViewEntity, http.StatusUnprocessableEntity),
expected: "",
domain: certsDomainID,
token: token,
},
{
desc: "GetEntityID with empty serial",
serial: "",
svcresp: certs.Certificate{},
svcerr: certs.ErrMalformedEntity,
err: errors.NewSDKErrorWithStatus(certs.ErrMalformedEntity, http.StatusBadRequest),
expected: "",
domain: certsDomainID,
token: token,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == token {
tc.session = smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
var svcCall *mock.Call
if tc.desc == "GetEntityID with empty serial" {
// Empty serial routes to ListCerts endpoint instead of ViewCert
svcCall = svc.On("ListCerts", mock.Anything, tc.session, mock.Anything).Return(certs.CertificatePage{}, tc.svcerr)
} else {
svcCall = svc.On("ViewCert", mock.Anything, tc.session, tc.serial).Return(tc.svcresp, tc.svcerr)
}
resp, err := ctsdk.EntityID(context.Background(), tc.serial, tc.domain, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.expected, resp)
if tc.desc != "GetEntityID with empty serial" {
ok := svcCall.Parent.AssertCalled(t, "ViewCert", mock.Anything, tc.session, tc.serial)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestIssueFromCSRInternal(t *testing.T) {
ts, svc, auth := setupCerts()
defer ts.Close()
sdkConfig := sdk.Config{
CertsURL: ts.URL,
MsgContentType: certsContentType,
TLSVerification: false,
}
ctsdk := sdk.NewSDK(sdkConfig)
cert := sdk.Certificate{
SerialNumber: serialNum,
}
cases := []struct {
desc string
entityID string
ttl string
csr string
svcresp certs.Certificate
svcerr error
err errors.SDKError
sdkCert sdk.Certificate
}{
{
desc: "IssueFromCSRInternal success",
entityID: certsID,
ttl: ttl,
csr: "valid-csr-content",
svcresp: certs.Certificate{
SerialNumber: serialNum,
Certificate: []byte("cert"),
Key: []byte("key"),
},
sdkCert: cert,
svcerr: nil,
err: nil,
},
{
desc: "IssueFromCSRInternal failure",
entityID: certsID,
ttl: ttl,
csr: "invalid-csr-content",
svcresp: certs.Certificate{},
svcerr: certs.ErrFailedCertCreation,
err: errors.NewSDKErrorWithStatus(certs.ErrFailedCertCreation, http.StatusUnprocessableEntity),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
agentSession := smqauthn.Session{DomainUserID: certsID, UserID: certsID, DomainID: certsDomainID}
authCall := auth.On("Authenticate", mock.Anything, agentToken).Return(agentSession, nil)
svcCall := svc.On("IssueFromCSRInternal", mock.Anything, tc.entityID, tc.ttl, mock.Anything).Return(tc.svcresp, tc.svcerr)
c, err := ctsdk.IssueFromCSRInternal(context.Background(), tc.entityID, tc.ttl, tc.csr, agentToken)
assert.Equal(t, tc.err, err)
if tc.err == nil {
assert.Equal(t, tc.sdkCert.SerialNumber, c.SerialNumber)
ok := svcCall.Parent.AssertCalled(t, "IssueFromCSRInternal", mock.Anything, tc.entityID, tc.ttl, mock.Anything)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}