Moving add client in keycloak from security to invoker api
Issue-ID: NONRTRIC-861
Signed-off-by: ychacon <yennifer.chacon@est.tech>
Change-Id: I0d9ceedc2f23f2d5fa5233f6075f3ecd56d3fc08
diff --git a/capifcore/internal/invokermanagement/invokermanagement.go b/capifcore/internal/invokermanagement/invokermanagement.go
index 43bdc02..ee7030a 100644
--- a/capifcore/internal/invokermanagement/invokermanagement.go
+++ b/capifcore/internal/invokermanagement/invokermanagement.go
@@ -27,6 +27,7 @@
"sync"
"oransc.org/nonrtric/capifcore/internal/eventsapi"
+ "oransc.org/nonrtric/capifcore/internal/keycloak"
"oransc.org/nonrtric/capifcore/internal/common29122"
invokerapi "oransc.org/nonrtric/capifcore/internal/invokermanagementapi"
@@ -53,16 +54,18 @@
onboardedInvokers map[string]invokerapi.APIInvokerEnrolmentDetails
publishRegister publishservice.PublishRegister
nextId int64
+ keycloak keycloak.AccessManagement
eventChannel chan<- eventsapi.EventNotification
lock sync.Mutex
}
// Creates a manager that implements both the InvokerRegister and the invokermanagementapi.ServerInterface interfaces.
-func NewInvokerManager(publishRegister publishservice.PublishRegister, eventChannel chan<- eventsapi.EventNotification) *InvokerManager {
+func NewInvokerManager(publishRegister publishservice.PublishRegister, km keycloak.AccessManagement, eventChannel chan<- eventsapi.EventNotification) *InvokerManager {
return &InvokerManager{
onboardedInvokers: make(map[string]invokerapi.APIInvokerEnrolmentDetails),
publishRegister: publishRegister,
nextId: 1000,
+ keycloak: km,
eventChannel: eventChannel,
}
}
@@ -147,9 +150,24 @@
newInvoker.PrepareNewInvoker()
+ im.addClientInKeycloak(newInvoker)
+
im.onboardedInvokers[*newInvoker.ApiInvokerId] = *newInvoker
}
+func (im *InvokerManager) addClientInKeycloak(newInvoker *invokerapi.APIInvokerEnrolmentDetails) error {
+ if err := im.keycloak.AddClient(*newInvoker.ApiInvokerId, "invokerrealm"); err != nil {
+ return err
+ }
+
+ if body, err := im.keycloak.GetClientRepresentation(*newInvoker.ApiInvokerId, "invokerrealm"); err != nil {
+ return err
+ } else {
+ newInvoker.OnboardingInformation.OnboardingSecret = body.Secret
+ }
+ return nil
+}
+
// Deletes an individual API Invoker.
func (im *InvokerManager) DeleteOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
if _, ok := im.onboardedInvokers[onboardingId]; ok {
diff --git a/capifcore/internal/invokermanagement/invokermanagement_test.go b/capifcore/internal/invokermanagement/invokermanagement_test.go
index 4365eb3..7b92972 100644
--- a/capifcore/internal/invokermanagement/invokermanagement_test.go
+++ b/capifcore/internal/invokermanagement/invokermanagement_test.go
@@ -29,12 +29,14 @@
"oransc.org/nonrtric/capifcore/internal/eventsapi"
"oransc.org/nonrtric/capifcore/internal/invokermanagementapi"
+ "oransc.org/nonrtric/capifcore/internal/keycloak"
"github.com/labstack/echo/v4"
"oransc.org/nonrtric/capifcore/internal/common29122"
"oransc.org/nonrtric/capifcore/internal/publishserviceapi"
+ keycloackmocks "oransc.org/nonrtric/capifcore/internal/keycloak/mocks"
"oransc.org/nonrtric/capifcore/internal/publishservice"
publishmocks "oransc.org/nonrtric/capifcore/internal/publishservice/mocks"
@@ -42,6 +44,7 @@
"github.com/deepmap/oapi-codegen/pkg/testutil"
echomiddleware "github.com/labstack/echo/v4/middleware"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
)
func TestOnboardInvoker(t *testing.T) {
@@ -55,11 +58,20 @@
AefProfiles: &aefProfiles,
},
}
- publishRegisterMock := publishmocks.PublishRegister{}
- publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
- invokerUnderTest, eventChannel, requestHandler := getEcho(&publishRegisterMock)
invokerInfo := "invoker a"
+ wantedInvokerSecret := "onboarding_secret_" + strings.Replace(invokerInfo, " ", "_", 1)
+ var client keycloak.Client
+ client.Secret = &wantedInvokerSecret
+ publishRegisterMock := publishmocks.PublishRegister{}
+ publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
+
+ accessMgmMock := keycloackmocks.AccessManagement{}
+ accessMgmMock.On("AddClient", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(nil)
+ accessMgmMock.On("GetClientRepresentation", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(&client, nil)
+
+ invokerUnderTest, eventChannel, requestHandler := getEcho(&publishRegisterMock, &accessMgmMock)
+
newInvoker := getInvoker(invokerInfo)
// Onboard a valid invoker
@@ -73,7 +85,7 @@
assert.Equal(t, wantedInvokerId, *resultInvoker.ApiInvokerId)
assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
- wantedInvokerSecret := "onboarding_secret_" + strings.Replace(invokerInfo, " ", "_", 1)
+
assert.Equal(t, wantedInvokerSecret, *resultInvoker.OnboardingInformation.OnboardingSecret)
assert.Equal(t, "http://example.com/onboardedInvokers/"+*resultInvoker.ApiInvokerId, result.Recorder.Header().Get(echo.HeaderLocation))
assert.True(t, invokerUnderTest.IsInvokerRegistered(wantedInvokerId))
@@ -128,7 +140,7 @@
}
func TestDeleteInvoker(t *testing.T) {
- invokerUnderTest, eventChannel, requestHandler := getEcho(nil)
+ invokerUnderTest, eventChannel, requestHandler := getEcho(nil, nil)
invokerId := "invokerId"
newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
@@ -157,7 +169,7 @@
func TestUpdateInvoker(t *testing.T) {
publishRegisterMock := publishmocks.PublishRegister{}
publishRegisterMock.On("GetAllPublishedServices").Return([]publishserviceapi.ServiceAPIDescription{})
- serviceUnderTest, _, requestHandler := getEcho(&publishRegisterMock)
+ serviceUnderTest, _, requestHandler := getEcho(&publishRegisterMock, nil)
invokerId := "invokerId"
invoker := invokermanagementapi.APIInvokerEnrolmentDetails{
@@ -261,7 +273,7 @@
})
publishRegisterMock := publishmocks.PublishRegister{}
publishRegisterMock.On("GetAllPublishedServices").Return(apiList)
- invokerUnderTest, _, _ := getEcho(&publishRegisterMock)
+ invokerUnderTest, _, _ := getEcho(&publishRegisterMock, nil)
invokerInfo := "invoker a"
newInvoker := getInvoker(invokerInfo)
@@ -280,7 +292,7 @@
assert.Equal(t, apiId, *(*wantedApiList)[0].ApiId)
}
-func getEcho(publishRegister publishservice.PublishRegister) (*InvokerManager, chan eventsapi.EventNotification, *echo.Echo) {
+func getEcho(publishRegister publishservice.PublishRegister, keycloakMgm keycloak.AccessManagement) (*InvokerManager, chan eventsapi.EventNotification, *echo.Echo) {
swagger, err := invokermanagementapi.GetSwagger()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
@@ -290,7 +302,7 @@
swagger.Servers = nil
eventChannel := make(chan eventsapi.EventNotification)
- im := NewInvokerManager(publishRegister, eventChannel)
+ im := NewInvokerManager(publishRegister, keycloakMgm, eventChannel)
e := echo.New()
e.Use(echomiddleware.Logger())
diff --git a/capifcore/internal/invokermanagementapi/typeupdate.go b/capifcore/internal/invokermanagementapi/typeupdate.go
index 1de6280..abd399e 100644
--- a/capifcore/internal/invokermanagementapi/typeupdate.go
+++ b/capifcore/internal/invokermanagementapi/typeupdate.go
@@ -30,8 +30,6 @@
func (ied *APIInvokerEnrolmentDetails) PrepareNewInvoker() {
ied.createId()
- ied.getOnboardingSecret()
-
}
func (ied *APIInvokerEnrolmentDetails) createId() {
diff --git a/capifcore/internal/invokermanagementapi/typeupdate_test.go b/capifcore/internal/invokermanagementapi/typeupdate_test.go
index 5128d5f..f04a13d 100644
--- a/capifcore/internal/invokermanagementapi/typeupdate_test.go
+++ b/capifcore/internal/invokermanagementapi/typeupdate_test.go
@@ -34,11 +34,9 @@
invokerUnderTest.PrepareNewInvoker()
assert.Equal(t, "api_invoker_id_1", *invokerUnderTest.ApiInvokerId)
- assert.Equal(t, "onboarding_secret_api_invoker_id_1", *invokerUnderTest.OnboardingInformation.OnboardingSecret)
invokerInfo := "invoker info"
invokerUnderTest.ApiInvokerInformation = &invokerInfo
invokerUnderTest.PrepareNewInvoker()
assert.Equal(t, "api_invoker_id_invoker_info", *invokerUnderTest.ApiInvokerId)
- assert.Equal(t, "onboarding_secret_invoker_info", *invokerUnderTest.OnboardingInformation.OnboardingSecret)
}
diff --git a/capifcore/internal/keycloak/keycloak.go b/capifcore/internal/keycloak/keycloak.go
index 3646516..200f8d4 100644
--- a/capifcore/internal/keycloak/keycloak.go
+++ b/capifcore/internal/keycloak/keycloak.go
@@ -39,6 +39,8 @@
GetToken(realm string, data map[string][]string) (Jwttoken, error)
// Add new client in keycloak
AddClient(clientId string, realm string) error
+ // Returns information about client including secret
+ GetClientRepresentation(clientId string, realm string) (*Client, error)
}
type AdminUser struct {
@@ -83,7 +85,6 @@
func (km *KeycloakManager) GetToken(realm string, data map[string][]string) (Jwttoken, error) {
var jwt Jwttoken
getTokenUrl := km.keycloakServerUrl + "/realms/" + realm + "/protocol/openid-connect/token"
-
resp, err := http.PostForm(getTokenUrl, data)
if err != nil {
@@ -96,6 +97,7 @@
if err != nil {
return jwt, err
}
+
if resp.StatusCode != http.StatusOK {
return jwt, errors.New(string(body))
}
@@ -105,16 +107,20 @@
}
type Client struct {
- AdminURL string `json:"adminUrl,omitempty"`
- BearerOnly bool `json:"bearerOnly,omitempty"`
- ClientID string `json:"clientId,omitempty"`
- Enabled bool `json:"enabled,omitempty"`
- PublicClient bool `json:"publicClient,omitempty"`
- RootURL string `json:"rootUrl,omitempty"`
- ServiceAccountsEnabled bool `json:"serviceAccountsEnabled,omitempty"`
+ AdminURL string `json:"adminUrl,omitempty"`
+ AuthorizationServicesEnabled *bool `json:"authorizationServicesEnabled,omitempty"`
+ BearerOnly bool `json:"bearerOnly,omitempty"`
+ ClientID string `json:"clientId,omitempty"`
+ Enabled bool `json:"enabled,omitempty"`
+ ID *string `json:"id,omitempty"`
+ PublicClient bool `json:"publicClient,omitempty"`
+ RootURL string `json:"rootUrl,omitempty"`
+ Secret *string `json:"secret,omitempty"`
+ ServiceAccountsEnabled bool `json:"serviceAccountsEnabled,omitempty"`
}
func (km *KeycloakManager) AddClient(clientId string, realm string) error {
+
data := url.Values{"grant_type": {"password"}, "username": {km.admin.User}, "password": {km.admin.Password}, "client_id": {"admin-cli"}}
token, err := km.GetToken("master", data)
if err != nil {
@@ -123,22 +129,56 @@
}
createClientUrl := km.keycloakServerUrl + "/admin/realms/" + realm + "/clients"
- newClient := Client{
- ClientID: clientId,
- Enabled: true,
- ServiceAccountsEnabled: true,
- BearerOnly: false,
- PublicClient: false,
- }
+ newClient := map[string]interface{}{"clientId": clientId, "serviceAccountsEnabled": true}
- body, _ := json.Marshal(newClient)
- var headers = map[string]string{"Content-Type": "application/json", "Authorization": "Bearer " + token.AccessToken}
- if error := restclient.Post(createClientUrl, body, headers, km.client); error != nil {
- log.Errorf("error with http request: %+v\n", err)
+ body, err := json.Marshal(newClient)
+ if err != nil {
return err
}
- log.Info("Created new client")
+ var headers = map[string]string{"Content-Type": "application/json", "Authorization": "Bearer " + token.AccessToken}
+ if err := restclient.Post(createClientUrl, body, headers, km.client); err != nil {
+ log.Errorf("addClient - error with http request: %+v\n", err)
+ return err
+ }
+
+ log.Debug("Created new client")
return nil
}
+
+func (km *KeycloakManager) GetClientRepresentation(clientId string, realm string) (*Client, error) {
+
+ data := url.Values{"grant_type": {"password"}, "username": {km.admin.User}, "password": {km.admin.Password}, "client_id": {"admin-cli"}}
+ token, err := km.GetToken("master", data)
+ if err != nil {
+ log.Errorf("error wrong credentials or url %v\n", err)
+ return nil, err
+ }
+
+ createClientUrl, _ := url.Parse(km.keycloakServerUrl + "/admin/realms/" + realm + "/clients")
+ q := createClientUrl.Query()
+ q.Add("clientId", clientId)
+ createClientUrl.RawQuery = q.Encode()
+
+ var headers = map[string]string{"Content-Type": "application/json", "Authorization": "Bearer " + token.AccessToken}
+
+ if resp, err := restclient.Get(createClientUrl.String(), headers, km.client); err == nil {
+ var client []Client
+
+ if err = json.Unmarshal(resp, &client); err != nil {
+ log.Errorf("error unmarshal keycloak client object: %+v\n", err)
+ return nil, err
+ }
+
+ if len(client) > 0 {
+ return &client[0], nil
+ }
+ return nil, nil
+
+ } else {
+ log.Errorf("error with http request: %+v\n", err)
+ return nil, err
+ }
+
+}
diff --git a/capifcore/internal/keycloak/mocks/AccessManagement.go b/capifcore/internal/keycloak/mocks/AccessManagement.go
index 59b914a..35086d4 100644
--- a/capifcore/internal/keycloak/mocks/AccessManagement.go
+++ b/capifcore/internal/keycloak/mocks/AccessManagement.go
@@ -26,6 +26,32 @@
return r0
}
+// GetClientRepresentation provides a mock function with given fields: clientId, realm
+func (_m *AccessManagement) GetClientRepresentation(clientId string, realm string) (*keycloak.Client, error) {
+ ret := _m.Called(clientId, realm)
+
+ var r0 *keycloak.Client
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, string) (*keycloak.Client, error)); ok {
+ return rf(clientId, realm)
+ }
+ if rf, ok := ret.Get(0).(func(string, string) *keycloak.Client); ok {
+ r0 = rf(clientId, realm)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*keycloak.Client)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, string) error); ok {
+ r1 = rf(clientId, realm)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// GetToken provides a mock function with given fields: realm, data
func (_m *AccessManagement) GetToken(realm string, data map[string][]string) (keycloak.Jwttoken, error) {
ret := _m.Called(realm, data)
diff --git a/capifcore/internal/providermanagement/mocks/ServiceRegister.go b/capifcore/internal/providermanagement/mocks/ServiceRegister.go
index c795ed1..a1f9c41 100644
--- a/capifcore/internal/providermanagement/mocks/ServiceRegister.go
+++ b/capifcore/internal/providermanagement/mocks/ServiceRegister.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.14.0. DO NOT EDIT.
+// Code generated by mockery v2.20.0. DO NOT EDIT.
package mocks
@@ -39,6 +39,20 @@
return r0
}
+// IsPublishingFunctionRegistered provides a mock function with given fields: apiProvFuncId
+func (_m *ServiceRegister) IsPublishingFunctionRegistered(apiProvFuncId string) bool {
+ ret := _m.Called(apiProvFuncId)
+
+ var r0 bool
+ if rf, ok := ret.Get(0).(func(string) bool); ok {
+ r0 = rf(apiProvFuncId)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ return r0
+}
+
type mockConstructorTestingTNewServiceRegister interface {
mock.TestingT
Cleanup(func())
diff --git a/capifcore/internal/providermanagement/providermanagement.go b/capifcore/internal/providermanagement/providermanagement.go
index d5e7a63..2d6bd61 100644
--- a/capifcore/internal/providermanagement/providermanagement.go
+++ b/capifcore/internal/providermanagement/providermanagement.go
@@ -38,6 +38,7 @@
type ServiceRegister interface {
IsFunctionRegistered(functionId string) bool
GetAefsForPublisher(apfId string) []string
+ IsPublishingFunctionRegistered(apiProvFuncId string) bool
}
type ProviderManager struct {
@@ -69,6 +70,15 @@
return nil
}
+func (pm *ProviderManager) IsPublishingFunctionRegistered(apiProvFuncId string) bool {
+ for _, provider := range pm.registeredProviders {
+ if provider.IsPublishingFunctionRegistered(apiProvFuncId) {
+ return true
+ }
+ }
+ return false
+}
+
func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
var newProvider provapi.APIProviderEnrolmentDetails
errMsg := "Unable to register provider due to %s"
diff --git a/capifcore/internal/providermanagementapi/typeaccess.go b/capifcore/internal/providermanagementapi/typeaccess.go
index 5257701..b1894d4 100644
--- a/capifcore/internal/providermanagementapi/typeaccess.go
+++ b/capifcore/internal/providermanagementapi/typeaccess.go
@@ -48,7 +48,16 @@
return false
}
-func (fd APIProviderFunctionDetails) isProvidingFunction() bool {
+func (ed APIProviderEnrolmentDetails) IsPublishingFunctionRegistered(functionId string) bool {
+ for _, registeredFunc := range *ed.ApiProvFuncs {
+ if *registeredFunc.ApiProvFuncId == functionId && registeredFunc.isPublishingFunction() {
+ return true
+ }
+ }
+ return false
+}
+
+func (fd APIProviderFunctionDetails) isPublishingFunction() bool {
return fd.ApiProvFuncRole == ApiProviderFuncRoleAPF
}
diff --git a/capifcore/internal/publishservice/publishservice.go b/capifcore/internal/publishservice/publishservice.go
index 7960f12..2fe5b2e 100644
--- a/capifcore/internal/publishservice/publishservice.go
+++ b/capifcore/internal/publishservice/publishservice.go
@@ -118,6 +118,10 @@
return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errorMsg, "invalid format for service "+apfId))
}
+ if !ps.serviceRegister.IsPublishingFunctionRegistered(apfId) {
+ return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errorMsg, "api is only available for publishers "+apfId))
+ }
+
if err := ps.isServicePublished(newServiceAPIDescription); err != nil {
return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errorMsg, err))
}
diff --git a/capifcore/internal/publishservice/publishservice_test.go b/capifcore/internal/publishservice/publishservice_test.go
index b69b956..8de1e9f 100644
--- a/capifcore/internal/publishservice/publishservice_test.go
+++ b/capifcore/internal/publishservice/publishservice_test.go
@@ -52,6 +52,7 @@
aefId := "aefId"
serviceRegisterMock := serviceMocks.ServiceRegister{}
serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId"})
+ serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
helmManagerMock := helmMocks.HelmManager{}
helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
serviceUnderTest, eventChannel, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
@@ -71,7 +72,6 @@
// Publish a service for provider
result = testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
-
assert.Equal(t, http.StatusCreated, result.Code())
var resultService publishapi.ServiceAPIDescription
err := result.UnmarshalBodyToObject(&resultService)
@@ -136,6 +136,7 @@
aefId := "aefId"
serviceRegisterMock := serviceMocks.ServiceRegister{}
serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{"otherAefId"})
+ serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
_, _, requestHandler := getEcho(&serviceRegisterMock, nil)
newServiceDescription := getServiceAPIDescription(aefId, "apiName", "description")
@@ -157,6 +158,7 @@
aefId := "aefId"
serviceRegisterMock := serviceMocks.ServiceRegister{}
serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId})
+ serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
_, _, requestHandler := getEcho(&serviceRegisterMock, nil)
// Check no services published for provider
@@ -212,6 +214,7 @@
serviceRegisterMock := serviceMocks.ServiceRegister{}
serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"})
+ serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
helmManagerMock := helmMocks.HelmManager{}
helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
serviceUnderTest, eventChannel, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
@@ -285,6 +288,7 @@
description := "description"
serviceRegisterMock := serviceMocks.ServiceRegister{}
+ serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"})
helmManagerMock := helmMocks.HelmManager{}
helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
@@ -367,7 +371,11 @@
}
func TestPublishInvalidService(t *testing.T) {
- _, _, requestHandler := getEcho(nil, nil)
+ apfId := "apfId"
+ serviceRegisterMock := serviceMocks.ServiceRegister{}
+ serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
+
+ _, _, requestHandler := getEcho(&serviceRegisterMock, nil)
newServiceDescription := getServiceAPIDescription("aefId", " ", "description")
// Publish a service
diff --git a/capifcore/internal/publishserviceapi/typevalidation.go b/capifcore/internal/publishserviceapi/typevalidation.go
index 287a07d..5e8a8fc 100644
--- a/capifcore/internal/publishserviceapi/typevalidation.go
+++ b/capifcore/internal/publishserviceapi/typevalidation.go
@@ -21,7 +21,6 @@
import (
"errors"
- //"fmt"
"strings"
)
diff --git a/capifcore/internal/restclient/HTTPClient.go b/capifcore/internal/restclient/HTTPClient.go
index c771a54..e9d3469 100644
--- a/capifcore/internal/restclient/HTTPClient.go
+++ b/capifcore/internal/restclient/HTTPClient.go
@@ -33,6 +33,7 @@
//go:generate mockery --name HTTPClient
type HTTPClient interface {
Do(*http.Request) (*http.Response, error)
+ Get(url string) (*http.Response, error)
}
type RequestError struct {
@@ -44,31 +45,49 @@
return fmt.Sprintf("Request failed due to error response with status: %v and body: %v", pe.StatusCode, string(pe.Body))
}
+func Get(url string, header map[string]string, client HTTPClient) ([]byte, error) {
+ return do(http.MethodGet, url, nil, header, client)
+}
+
func Put(url string, body []byte, client HTTPClient) error {
var header = map[string]string{"Content-Type": ContentTypeJSON}
- return do(http.MethodPut, url, body, header, client)
+ _, err := do(http.MethodPut, url, body, header, client)
+ return err
}
func Post(url string, body []byte, header map[string]string, client HTTPClient) error {
- return do(http.MethodPost, url, body, header, client)
+ _, err := do(http.MethodPost, url, body, header, client)
+ return err
}
-func do(method string, url string, body []byte, header map[string]string, client HTTPClient) error {
- if req, reqErr := http.NewRequest(method, url, bytes.NewBuffer(body)); reqErr == nil {
+func do(method string, url string, body []byte, header map[string]string, client HTTPClient) ([]byte, error) {
+ if req, reqErr := http.NewRequest(method, url, nil); reqErr == nil {
if len(header) > 0 {
setHeader(req, header)
}
+ if body != nil {
+ req.Body = io.NopCloser(bytes.NewReader(body))
+ }
+
if response, respErr := client.Do(req); respErr == nil {
if isResponseSuccess(response.StatusCode) {
- return nil
+ fmt.Printf("HTTP client:: response statuscode:: %v body:: %v\n", response.StatusCode, response.Body)
+ defer response.Body.Close()
+
+ // Read the response body
+ respBody, err := io.ReadAll(response.Body)
+ if err != nil {
+ return nil, err
+ }
+ return respBody, nil
} else {
- return getRequestError(response)
+ return nil, getRequestError(response)
}
} else {
- return respErr
+ return nil, respErr
}
} else {
- return reqErr
+ return nil, reqErr
}
}
diff --git a/capifcore/internal/restclient/HTTPClient_test.go b/capifcore/internal/restclient/HTTPClient_test.go
index e390686..47cf8b7 100644
--- a/capifcore/internal/restclient/HTTPClient_test.go
+++ b/capifcore/internal/restclient/HTTPClient_test.go
@@ -47,6 +47,7 @@
clientMock.On("Do", mock.Anything).Return(&http.Response{
StatusCode: http.StatusOK,
+ Body: io.NopCloser(bytes.NewReader([]byte("body"))),
}, nil)
if err := Put("http://localhost:9990", []byte("body"), &clientMock); err != nil {
@@ -67,6 +68,36 @@
clientMock.AssertNumberOfCalls(t, "Do", 1)
}
+func TestPostOk(t *testing.T) {
+ assertions := require.New(t)
+ clientMock := mocks.HTTPClient{}
+
+ clientMock.On("Do", mock.Anything).Return(&http.Response{
+ StatusCode: http.StatusOK,
+ Body: io.NopCloser(bytes.NewReader([]byte("body"))),
+ }, nil)
+
+ headers := map[string]string{
+ "Content-Type": "application/json",
+ }
+ if err := Post("http://localhost:9990", []byte("body"), headers, &clientMock); err != nil {
+ t.Errorf("Post() error = %v, did not want error", err)
+ }
+ var actualRequest *http.Request
+ clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool {
+ actualRequest = req
+ return true
+ }))
+ assertions.Equal(http.MethodPost, actualRequest.Method)
+ assertions.Equal("http", actualRequest.URL.Scheme)
+ assertions.Equal("localhost:9990", actualRequest.URL.Host)
+ assertions.Equal("application/json", actualRequest.Header.Get("Content-Type"))
+ body, _ := io.ReadAll(actualRequest.Body)
+ expectedBody := []byte("body")
+ assertions.Equal(expectedBody, body)
+ clientMock.AssertNumberOfCalls(t, "Do", 1)
+}
+
func Test_doErrorCases(t *testing.T) {
assertions := require.New(t)
type args struct {
@@ -109,7 +140,7 @@
StatusCode: tt.args.mockReturnStatus,
Body: io.NopCloser(bytes.NewReader(tt.args.mockReturnBody)),
}, tt.args.mockReturnError)
- err := do("PUT", tt.args.url, nil, map[string]string{}, &clientMock)
+ _, err := do("PUT", tt.args.url, nil, map[string]string{}, &clientMock)
assertions.Equal(tt.wantErr, err, tt.name)
})
}
diff --git a/capifcore/internal/restclient/mocks/HTTPClient.go b/capifcore/internal/restclient/mocks/HTTPClient.go
index 7627c4b..7d0064a 100644
--- a/capifcore/internal/restclient/mocks/HTTPClient.go
+++ b/capifcore/internal/restclient/mocks/HTTPClient.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.14.0. DO NOT EDIT.
+// Code generated by mockery v2.20.0. DO NOT EDIT.
package mocks
@@ -18,6 +18,10 @@
ret := _m.Called(_a0)
var r0 *http.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(*http.Request) (*http.Response, error)); ok {
+ return rf(_a0)
+ }
if rf, ok := ret.Get(0).(func(*http.Request) *http.Response); ok {
r0 = rf(_a0)
} else {
@@ -26,7 +30,6 @@
}
}
- var r1 error
if rf, ok := ret.Get(1).(func(*http.Request) error); ok {
r1 = rf(_a0)
} else {
@@ -36,6 +39,32 @@
return r0, r1
}
+// Get provides a mock function with given fields: url
+func (_m *HTTPClient) Get(url string) (*http.Response, error) {
+ ret := _m.Called(url)
+
+ var r0 *http.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) (*http.Response, error)); ok {
+ return rf(url)
+ }
+ if rf, ok := ret.Get(0).(func(string) *http.Response); ok {
+ r0 = rf(url)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*http.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(url)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
type mockConstructorTestingTNewHTTPClient interface {
mock.TestingT
Cleanup(func())
diff --git a/capifcore/internal/securityapi/typeupdate.go b/capifcore/internal/securityapi/typeupdate.go
index 3402b8e..3adb836 100644
--- a/capifcore/internal/securityapi/typeupdate.go
+++ b/capifcore/internal/securityapi/typeupdate.go
@@ -59,7 +59,6 @@
}
func addSecurityMethodsFromInterfaceDetails(methodsFromInterface *[]publishserviceapi.SecurityMethod, prefMethods *[]publishserviceapi.SecurityMethod) {
-
if methodsFromInterface != nil {
securityMethods = append(securityMethods, *methodsFromInterface...)
}
@@ -68,9 +67,9 @@
}
}
-func addSecurityMethodsFromAefProfile(afpProfile *publishserviceapi.AefProfile) {
- if afpProfile.SecurityMethods != nil {
- securityMethods = append(securityMethods, *afpProfile.SecurityMethods...)
+func addSecurityMethodsFromAefProfile(aefProfile *publishserviceapi.AefProfile) {
+ if aefProfile.SecurityMethods != nil {
+ securityMethods = append(securityMethods, *aefProfile.SecurityMethods...)
}
}
diff --git a/capifcore/internal/securityservice/security.go b/capifcore/internal/securityservice/security.go
index e211f67..ddedc85 100644
--- a/capifcore/internal/securityservice/security.go
+++ b/capifcore/internal/securityservice/security.go
@@ -192,11 +192,6 @@
return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
}
- err = s.keycloak.AddClient(apiInvokerId, "invokerrealm")
- if err != nil {
- return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
- }
-
uri := ctx.Request().Host + ctx.Request().URL.String()
ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiInvokerId))
diff --git a/capifcore/internal/securityservice/security_test.go b/capifcore/internal/securityservice/security_test.go
index 1dda127..ea0fbe6 100644
--- a/capifcore/internal/securityservice/security_test.go
+++ b/capifcore/internal/securityservice/security_test.go
@@ -263,10 +263,7 @@
publishRegisterMock := publishmocks.PublishRegister{}
publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
- accessMgmMock := keycloackmocks.AccessManagement{}
- accessMgmMock.On("AddClient", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(nil)
-
- requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
+ requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
invokerId := "invokerId"
serviceSecurityUnderTest := getServiceSecurity(aefId, apiId)
@@ -285,8 +282,6 @@
assert.Equal(t, *security.SelSecurityMethod, publishserviceapi.SecurityMethodPKI)
}
invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", invokerId)
- accessMgmMock.AssertCalled(t, "AddClient", invokerId, "invokerrealm")
-
}
func TestPutTrustedInkoverNotRegistered(t *testing.T) {
@@ -354,10 +349,7 @@
publishRegisterMock := publishmocks.PublishRegister{}
publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
- accessMgmMock := keycloackmocks.AccessManagement{}
- accessMgmMock.On("AddClient", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(nil)
-
- requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
+ requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
invokerId := "invokerId"
serviceSecurityUnderTest := getServiceSecurity(aefId, apiId)
@@ -386,7 +378,6 @@
assert.Equal(t, publishserviceapi.SecurityMethodPSK, *security.SelSecurityMethod)
}
invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", invokerId)
- accessMgmMock.AssertCalled(t, "AddClient", invokerId, "invokerrealm")
}
func TestPutTrustedInvokerNotFoundSecurityMethod(t *testing.T) {
diff --git a/capifcore/main.go b/capifcore/main.go
index 5ba3923..93c0626 100644
--- a/capifcore/main.go
+++ b/capifcore/main.go
@@ -137,7 +137,7 @@
log.Fatalf("Error loading InvokerManagement swagger spec\n: %s", err)
}
invokerManagerSwagger.Servers = nil
- invokerManager := invokermanagement.NewInvokerManager(publishService, eventChannel)
+ invokerManager := invokermanagement.NewInvokerManager(publishService, km, eventChannel)
group = e.Group("/api-invoker-management/v1")
group.Use(middleware.OapiRequestValidator(invokerManagerSwagger))
invokermanagementapi.RegisterHandlersWithBaseURL(e, invokerManager, "/api-invoker-management/v1")