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