X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=capifcore%2Finternal%2Fsecurityservice%2Fsecurity_test.go;h=13af737a093a24441e6f98f35e250712f96f1e23;hb=4308df0663b45eb9d95b3babdf519a06ee76c15a;hp=2abc33bcbc205086cd61e0b34a78b04cbba4615f;hpb=ca348a91e7bb7486e98f42fcbec7c6b94f667228;p=nonrtric%2Fplt%2Fsme.git diff --git a/capifcore/internal/securityservice/security_test.go b/capifcore/internal/securityservice/security_test.go index 2abc33b..13af737 100644 --- a/capifcore/internal/securityservice/security_test.go +++ b/capifcore/internal/securityservice/security_test.go @@ -21,12 +21,14 @@ package security import ( + "errors" "fmt" "net/http" "net/url" "os" "testing" + "oransc.org/nonrtric/capifcore/internal/keycloak" "oransc.org/nonrtric/capifcore/internal/securityapi" "oransc.org/nonrtric/capifcore/internal/invokermanagement" @@ -35,9 +37,8 @@ import ( "github.com/labstack/echo/v4" - "oransc.org/nonrtric/capifcore/internal/common29122" - invokermocks "oransc.org/nonrtric/capifcore/internal/invokermanagement/mocks" + keycloackmocks "oransc.org/nonrtric/capifcore/internal/keycloak/mocks" servicemocks "oransc.org/nonrtric/capifcore/internal/providermanagement/mocks" publishmocks "oransc.org/nonrtric/capifcore/internal/publishservice/mocks" @@ -54,16 +55,29 @@ func TestPostSecurityIdTokenInvokerRegistered(t *testing.T) { invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true) serviceRegisterMock := servicemocks.ServiceRegister{} serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(true) - apiRegisterMock := publishmocks.APIRegister{} - apiRegisterMock.On("IsAPIRegistered", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true) + publishRegisterMock := publishmocks.PublishRegister{} + publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true) + + jwt := keycloak.Jwttoken{ + AccessToken: "eyJhbGNIn0.e3YTQ0xLjEifQ.FcqCwCy7iJiOmw", + ExpiresIn: 300, + Scope: "3gpp#aefIdpath", + } + accessMgmMock := keycloackmocks.AccessManagement{} + accessMgmMock.On("GetToken", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(jwt, nil) - requestHandler := getEcho(&serviceRegisterMock, &apiRegisterMock, &invokerRegisterMock) + requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock) data := url.Values{} - data.Set("client_id", "id") - data.Add("client_secret", "secret") - data.Add("grant_type", "client_credentials") - data.Add("scope", "scope#aefId:path") + clientId := "id" + clientSecret := "secret" + aefId := "aefId" + path := "path" + data.Set("client_id", clientId) + data.Set("client_secret", clientSecret) + data.Set("grant_type", "client_credentials") + data.Set("scope", "3gpp#"+aefId+":"+path) + encodedData := data.Encode() result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler) @@ -73,38 +87,36 @@ func TestPostSecurityIdTokenInvokerRegistered(t *testing.T) { err := result.UnmarshalBodyToObject(&resultResponse) assert.NoError(t, err, "error unmarshaling response") assert.NotEmpty(t, resultResponse.AccessToken) - assert.Equal(t, "scope#aefId:path", *resultResponse.Scope) assert.Equal(t, securityapi.AccessTokenRspTokenTypeBearer, resultResponse.TokenType) - assert.Equal(t, common29122.DurationSec(0), resultResponse.ExpiresIn) - invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", "id") - invokerRegisterMock.AssertCalled(t, "VerifyInvokerSecret", "id", "secret") - serviceRegisterMock.AssertCalled(t, "IsFunctionRegistered", "aefId") - apiRegisterMock.AssertCalled(t, "IsAPIRegistered", "aefId", "path") + invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", clientId) + invokerRegisterMock.AssertCalled(t, "VerifyInvokerSecret", clientId, clientSecret) + serviceRegisterMock.AssertCalled(t, "IsFunctionRegistered", aefId) + publishRegisterMock.AssertCalled(t, "IsAPIPublished", aefId, path) + accessMgmMock.AssertCalled(t, "GetToken", clientId, clientSecret, "3gpp#"+aefId+":"+path, "invokerrealm") } func TestPostSecurityIdTokenInvokerNotRegistered(t *testing.T) { invokerRegisterMock := invokermocks.InvokerRegister{} invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(false) - requestHandler := getEcho(nil, nil, &invokerRegisterMock) + requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil) data := url.Values{} data.Set("client_id", "id") data.Add("client_secret", "secret") data.Add("grant_type", "client_credentials") - data.Add("scope", "scope#aefId:path") + data.Add("scope", "3gpp#aefId:path") encodedData := data.Encode() result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler) assert.Equal(t, http.StatusBadRequest, result.Code()) - var problemDetails common29122.ProblemDetails - err := result.UnmarshalBodyToObject(&problemDetails) + var errDetails securityapi.AccessTokenErr + err := result.UnmarshalBodyToObject(&errDetails) assert.NoError(t, err, "error unmarshaling response") - badRequest := http.StatusBadRequest - assert.Equal(t, &badRequest, problemDetails.Status) + assert.Equal(t, securityapi.AccessTokenErrErrorInvalidClient, errDetails.Error) errMsg := "Invoker not registered" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Equal(t, &errMsg, errDetails.ErrorDescription) } func TestPostSecurityIdTokenInvokerSecretNotValid(t *testing.T) { @@ -112,25 +124,24 @@ 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) + requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil) data := url.Values{} data.Set("client_id", "id") data.Add("client_secret", "secret") data.Add("grant_type", "client_credentials") - data.Add("scope", "scope#aefId:path") + data.Add("scope", "3gpp#aefId:path") encodedData := data.Encode() result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler) assert.Equal(t, http.StatusBadRequest, result.Code()) - var problemDetails common29122.ProblemDetails - err := result.UnmarshalBodyToObject(&problemDetails) + var errDetails securityapi.AccessTokenErr + err := result.UnmarshalBodyToObject(&errDetails) assert.NoError(t, err, "error unmarshaling response") - badRequest := http.StatusBadRequest - assert.Equal(t, &badRequest, problemDetails.Status) + assert.Equal(t, securityapi.AccessTokenErrErrorUnauthorizedClient, errDetails.Error) errMsg := "Invoker secret not valid" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Equal(t, &errMsg, errDetails.ErrorDescription) } func TestPostSecurityIdTokenFunctionNotRegistered(t *testing.T) { @@ -140,25 +151,24 @@ func TestPostSecurityIdTokenFunctionNotRegistered(t *testing.T) { serviceRegisterMock := servicemocks.ServiceRegister{} serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(false) - requestHandler := getEcho(&serviceRegisterMock, nil, &invokerRegisterMock) + requestHandler := getEcho(&serviceRegisterMock, nil, &invokerRegisterMock, nil) data := url.Values{} data.Set("client_id", "id") data.Add("client_secret", "secret") data.Add("grant_type", "client_credentials") - data.Add("scope", "scope#aefId:path") + data.Add("scope", "3gpp#aefId:path") encodedData := data.Encode() result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler) assert.Equal(t, http.StatusBadRequest, result.Code()) - var problemDetails common29122.ProblemDetails - err := result.UnmarshalBodyToObject(&problemDetails) + var errDetails securityapi.AccessTokenErr + err := result.UnmarshalBodyToObject(&errDetails) assert.NoError(t, err, "error unmarshaling response") - badRequest := http.StatusBadRequest - assert.Equal(t, &badRequest, problemDetails.Status) - errMsg := "Function not registered" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Equal(t, securityapi.AccessTokenErrErrorInvalidScope, errDetails.Error) + errMsg := "AEF Function not registered" + assert.Equal(t, &errMsg, errDetails.ErrorDescription) } func TestPostSecurityIdTokenAPINotPublished(t *testing.T) { @@ -167,31 +177,70 @@ func TestPostSecurityIdTokenAPINotPublished(t *testing.T) { invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true) serviceRegisterMock := servicemocks.ServiceRegister{} serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(true) - apiRegisterMock := publishmocks.APIRegister{} - apiRegisterMock.On("IsAPIRegistered", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(false) + publishRegisterMock := publishmocks.PublishRegister{} + publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(false) - requestHandler := getEcho(&serviceRegisterMock, &apiRegisterMock, &invokerRegisterMock) + requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, nil) data := url.Values{} data.Set("client_id", "id") data.Add("client_secret", "secret") data.Add("grant_type", "client_credentials") - data.Add("scope", "scope#aefId:path") + data.Add("scope", "3gpp#aefId:path") encodedData := data.Encode() result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler) assert.Equal(t, http.StatusBadRequest, result.Code()) - var problemDetails common29122.ProblemDetails - err := result.UnmarshalBodyToObject(&problemDetails) + var errDetails securityapi.AccessTokenErr + err := result.UnmarshalBodyToObject(&errDetails) assert.NoError(t, err, "error unmarshaling response") - badRequest := http.StatusBadRequest - assert.Equal(t, &badRequest, problemDetails.Status) + assert.Equal(t, securityapi.AccessTokenErrErrorInvalidScope, errDetails.Error) errMsg := "API not published" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Equal(t, &errMsg, errDetails.ErrorDescription) +} + +func TestPostSecurityIdTokenInvokerInvalidCredentials(t *testing.T) { + invokerRegisterMock := invokermocks.InvokerRegister{} + invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true) + invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true) + serviceRegisterMock := servicemocks.ServiceRegister{} + serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(true) + publishRegisterMock := publishmocks.PublishRegister{} + publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true) + + jwt := keycloak.Jwttoken{} + 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) + + data := url.Values{} + clientId := "id" + clientSecret := "secret" + aefId := "aefId" + path := "path" + data.Set("client_id", clientId) + data.Set("client_secret", clientSecret) + data.Set("grant_type", "client_credentials") + data.Set("scope", "3gpp#"+aefId+":"+path) + + encodedData := data.Encode() + + result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler) + + assert.Equal(t, http.StatusBadRequest, result.Code()) + var resultResponse securityapi.AccessTokenErr + err := result.UnmarshalBodyToObject(&resultResponse) + assert.NoError(t, err, "error unmarshaling response") + invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", clientId) + invokerRegisterMock.AssertCalled(t, "VerifyInvokerSecret", clientId, clientSecret) + serviceRegisterMock.AssertCalled(t, "IsFunctionRegistered", aefId) + publishRegisterMock.AssertCalled(t, "IsAPIPublished", aefId, path) + accessMgmMock.AssertCalled(t, "GetToken", clientId, clientSecret, "3gpp#"+aefId+":"+path, "invokerrealm") } -func getEcho(serviceRegister providermanagement.ServiceRegister, apiRegister publishservice.APIRegister, invokerRegister invokermanagement.InvokerRegister) *echo.Echo { +func getEcho(serviceRegister providermanagement.ServiceRegister, publishRegister publishservice.PublishRegister, invokerRegister invokermanagement.InvokerRegister, keycloakMgm keycloak.AccessManagement) *echo.Echo { swagger, err := securityapi.GetSwagger() if err != nil { fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err) @@ -200,7 +249,7 @@ func getEcho(serviceRegister providermanagement.ServiceRegister, apiRegister pub swagger.Servers = nil - s := NewSecurity(serviceRegister, apiRegister, invokerRegister) + s := NewSecurity(serviceRegister, publishRegister, invokerRegister, keycloakMgm) e := echo.New() e.Use(echomiddleware.Logger())