Implementation for GET/DELETE trustedInvokers endpoint 93/10693/2
authorychacon <yennifer.chacon@est.tech>
Tue, 7 Mar 2023 20:59:08 +0000 (21:59 +0100)
committerychacon <yennifer.chacon@est.tech>
Wed, 8 Mar 2023 13:06:50 +0000 (14:06 +0100)
Issue-ID: NONRTRIC-848
Signed-off-by: ychacon <yennifer.chacon@est.tech>
Change-Id: I7c3c8c484afa2b56cfabe7d82d47255f91fd726a

capifcore/internal/securityservice/security.go
capifcore/internal/securityservice/security_test.go
capifcore/main_test.go

index 52d28ce..d3d9026 100644 (file)
@@ -28,7 +28,7 @@ import (
        "sync"
 
        "github.com/labstack/echo/v4"
-
+       copystructure "github.com/mitchellh/copystructure"
        "oransc.org/nonrtric/capifcore/internal/common29122"
        securityapi "oransc.org/nonrtric/capifcore/internal/securityapi"
 
@@ -110,11 +110,63 @@ func (s *Security) PostSecuritiesSecurityIdToken(ctx echo.Context, securityId st
 }
 
 func (s *Security) DeleteTrustedInvokersApiInvokerId(ctx echo.Context, apiInvokerId string) error {
-       return ctx.NoContent(http.StatusNotImplemented)
+       if _, ok := s.trustedInvokers[apiInvokerId]; ok {
+               s.deleteTrustedInvoker(apiInvokerId)
+       }
+
+       return ctx.NoContent(http.StatusNoContent)
+}
+
+func (s *Security) deleteTrustedInvoker(apiInvokerId string) {
+       s.lock.Lock()
+       defer s.lock.Unlock()
+       delete(s.trustedInvokers, apiInvokerId)
 }
 
 func (s *Security) GetTrustedInvokersApiInvokerId(ctx echo.Context, apiInvokerId string, params securityapi.GetTrustedInvokersApiInvokerIdParams) error {
-       return ctx.NoContent(http.StatusNotImplemented)
+
+       if trustedInvoker, ok := s.trustedInvokers[apiInvokerId]; ok {
+               updatedInvoker := s.checkParams(trustedInvoker, params)
+               if updatedInvoker != nil {
+                       err := ctx.JSON(http.StatusOK, updatedInvoker)
+                       if err != nil {
+                               return err
+                       }
+               }
+       } else {
+               return sendCoreError(ctx, http.StatusNotFound, fmt.Sprintf("invoker %s not registered as trusted invoker", apiInvokerId))
+       }
+
+       return nil
+}
+
+func (s *Security) checkParams(trustedInvoker securityapi.ServiceSecurity, params securityapi.GetTrustedInvokersApiInvokerIdParams) *securityapi.ServiceSecurity {
+       emptyString := ""
+
+       var sendAuthenticationInfo = (params.AuthenticationInfo != nil) && *params.AuthenticationInfo
+       var sendAuthorizationInfo = (params.AuthorizationInfo != nil) && *params.AuthorizationInfo
+
+       if sendAuthenticationInfo && sendAuthorizationInfo {
+               return &trustedInvoker
+       }
+
+       data, _ := copystructure.Copy(trustedInvoker)
+       updatedInvoker, ok := data.(securityapi.ServiceSecurity)
+       if !ok {
+               return nil
+       }
+
+       if !sendAuthenticationInfo {
+               for i := range updatedInvoker.SecurityInfo {
+                       updatedInvoker.SecurityInfo[i].AuthenticationInfo = &emptyString
+               }
+       }
+       if !sendAuthorizationInfo {
+               for i := range updatedInvoker.SecurityInfo {
+                       updatedInvoker.SecurityInfo[i].AuthorizationInfo = &emptyString
+               }
+       }
+       return &updatedInvoker
 }
 
 func (s *Security) PutTrustedInvokersApiInvokerId(ctx echo.Context, apiInvokerId string) error {
index d31ff6e..1abb8ae 100644 (file)
@@ -68,7 +68,7 @@ func TestPostSecurityIdTokenInvokerRegistered(t *testing.T) {
        accessMgmMock := keycloackmocks.AccessManagement{}
        accessMgmMock.On("GetToken", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(jwt, nil)
 
-       requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
+       requestHandler, _ := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
 
        data := url.Values{}
        clientId := "id"
@@ -101,7 +101,7 @@ func TestPostSecurityIdTokenInvokerNotRegistered(t *testing.T) {
        invokerRegisterMock := invokermocks.InvokerRegister{}
        invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(false)
 
-       requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, nil, &invokerRegisterMock, nil)
 
        data := url.Values{}
        data.Set("client_id", "id")
@@ -126,7 +126,7 @@ func TestPostSecurityIdTokenInvokerSecretNotValid(t *testing.T) {
        invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
        invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(false)
 
-       requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, nil, &invokerRegisterMock, nil)
 
        data := url.Values{}
        data.Set("client_id", "id")
@@ -153,7 +153,7 @@ func TestPostSecurityIdTokenFunctionNotRegistered(t *testing.T) {
        serviceRegisterMock := servicemocks.ServiceRegister{}
        serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(false)
 
-       requestHandler := getEcho(&serviceRegisterMock, nil, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(&serviceRegisterMock, nil, &invokerRegisterMock, nil)
 
        data := url.Values{}
        data.Set("client_id", "id")
@@ -182,7 +182,7 @@ func TestPostSecurityIdTokenAPINotPublished(t *testing.T) {
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(false)
 
-       requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, nil)
 
        data := url.Values{}
        data.Set("client_id", "id")
@@ -215,7 +215,7 @@ func TestPostSecurityIdTokenInvokerInvalidCredentials(t *testing.T) {
        accessMgmMock := keycloackmocks.AccessManagement{}
        accessMgmMock.On("GetToken", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(jwt, errors.New("invalid_credentials"))
 
-       requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
+       requestHandler, _ := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
 
        data := url.Values{}
        clientId := "id"
@@ -263,7 +263,7 @@ func TestPutTrustedInvokerSuccessfully(t *testing.T) {
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
 
-       requestHandler := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
 
        invokerId := "invokerId"
        serviceSecurityUnderTest := getServiceSecurity(aefId, apiId)
@@ -289,7 +289,7 @@ func TestPutTrustedInkoverNotRegistered(t *testing.T) {
        invokerRegisterMock := invokermocks.InvokerRegister{}
        invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(false)
 
-       requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, nil, &invokerRegisterMock, nil)
 
        invokerId := "invokerId"
        serviceSecurityUnderTest := getServiceSecurity("aefId", "apiId")
@@ -310,7 +310,7 @@ func TestPutTrustedInkoverInvalidInputServiceSecurity(t *testing.T) {
        invokerRegisterMock := invokermocks.InvokerRegister{}
        invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
 
-       requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, nil, &invokerRegisterMock, nil)
 
        invokerId := "invokerId"
        notificationUrl := "url"
@@ -350,7 +350,7 @@ func TestPutTrustedInvokerInterfaceDetailsNotNil(t *testing.T) {
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
 
-       requestHandler := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
 
        invokerId := "invokerId"
        serviceSecurityUnderTest := getServiceSecurity(aefId, apiId)
@@ -399,7 +399,7 @@ func TestPutTrustedInvokerNotFoundSecurityMethod(t *testing.T) {
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
 
-       requestHandler := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
+       requestHandler, _ := getEcho(nil, &publishRegisterMock, &invokerRegisterMock, nil)
 
        invokerId := "invokerId"
        serviceSecurityUnderTest := getServiceSecurity("aefId", "apiId")
@@ -417,7 +417,78 @@ func TestPutTrustedInvokerNotFoundSecurityMethod(t *testing.T) {
        invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", invokerId)
 }
 
-func getEcho(serviceRegister providermanagement.ServiceRegister, publishRegister publishservice.PublishRegister, invokerRegister invokermanagement.InvokerRegister, keycloakMgm keycloak.AccessManagement) *echo.Echo {
+func TestDeleteSecurityContext(t *testing.T) {
+
+       requestHandler, securityUnderTest := getEcho(nil, nil, nil, nil)
+
+       aefId := "aefId"
+       apiId := "apiId"
+       serviceSecurityUnderTest := getServiceSecurity(aefId, apiId)
+       serviceSecurityUnderTest.SecurityInfo[0].ApiId = &apiId
+
+       invokerId := "invokerId"
+       securityUnderTest.trustedInvokers[invokerId] = serviceSecurityUnderTest
+
+       // Delete the security context
+       result := testutil.NewRequest().Delete("/trustedInvokers/"+invokerId).Go(t, requestHandler)
+
+       assert.Equal(t, http.StatusNoContent, result.Code())
+       _, ok := securityUnderTest.trustedInvokers[invokerId]
+       assert.False(t, ok)
+}
+
+func TestGetSecurityContextByInvokerId(t *testing.T) {
+
+       requestHandler, securityUnderTest := getEcho(nil, nil, nil, nil)
+
+       aefId := "aefId"
+       apiId := "apiId"
+       authenticationInfo := "authenticationInfo"
+       authorizationInfo := "authorizationInfo"
+       serviceSecurityUnderTest := getServiceSecurity(aefId, apiId)
+       serviceSecurityUnderTest.SecurityInfo[0].AuthenticationInfo = &authenticationInfo
+       serviceSecurityUnderTest.SecurityInfo[0].AuthorizationInfo = &authorizationInfo
+
+       invokerId := "invokerId"
+       securityUnderTest.trustedInvokers[invokerId] = serviceSecurityUnderTest
+
+       // Get security context
+       result := testutil.NewRequest().Get("/trustedInvokers/"+invokerId).Go(t, requestHandler)
+
+       assert.Equal(t, http.StatusOK, result.Code())
+       var resultService securityapi.ServiceSecurity
+       err := result.UnmarshalBodyToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       for _, secInfo := range resultService.SecurityInfo {
+               assert.Equal(t, apiId, *secInfo.ApiId)
+               assert.Equal(t, aefId, *secInfo.AefId)
+               assert.Equal(t, "", *secInfo.AuthenticationInfo)
+               assert.Equal(t, "", *secInfo.AuthorizationInfo)
+       }
+
+       result = testutil.NewRequest().Get("/trustedInvokers/"+invokerId+"?authenticationInfo=true&authorizationInfo=false").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+       err = result.UnmarshalBodyToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       for _, secInfo := range resultService.SecurityInfo {
+               assert.Equal(t, authenticationInfo, *secInfo.AuthenticationInfo)
+               assert.Equal(t, "", *secInfo.AuthorizationInfo)
+       }
+
+       result = testutil.NewRequest().Get("/trustedInvokers/"+invokerId+"?authenticationInfo=true&authorizationInfo=true").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+       err = result.UnmarshalBodyToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       for _, secInfo := range resultService.SecurityInfo {
+               assert.Equal(t, authenticationInfo, *secInfo.AuthenticationInfo)
+               assert.Equal(t, authorizationInfo, *secInfo.AuthorizationInfo)
+       }
+}
+
+func getEcho(serviceRegister providermanagement.ServiceRegister, publishRegister publishservice.PublishRegister, invokerRegister invokermanagement.InvokerRegister, keycloakMgm keycloak.AccessManagement) (*echo.Echo, *Security) {
        swagger, err := securityapi.GetSwagger()
        if err != nil {
                fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
@@ -433,7 +504,7 @@ func getEcho(serviceRegister providermanagement.ServiceRegister, publishRegister
        e.Use(middleware.OapiRequestValidator(swagger))
 
        securityapi.RegisterHandlers(e, s)
-       return e
+       return e, s
 }
 
 func getServiceSecurity(aefId string, apiId string) securityapi.ServiceSecurity {
index 7d77b92..571d475 100644 (file)
@@ -101,7 +101,7 @@ func Test_routing(t *testing.T) {
                        name: "Security path",
                        args: args{
                                url:          "/capif-security/v1/trustedInvokers/apiInvokerId",
-                               returnStatus: http.StatusNotImplemented,
+                               returnStatus: http.StatusNotFound,
                                method:       "GET",
                        },
                },