mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
61d0427898
Signed-off-by: dusan <borovcanindusan1@gmail.com>
1033 lines
27 KiB
Go
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()
|
|
})
|
|
}
|
|
}
|