2 // ========================LICENSE_START=================================
5 // Copyright (C) 2022: Nordix Foundation
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 // ========================LICENSE_END===================================
31 "oransc.org/nonrtric/capifcore/internal/keycloak"
32 "oransc.org/nonrtric/capifcore/internal/securityapi"
34 "oransc.org/nonrtric/capifcore/internal/invokermanagement"
35 "oransc.org/nonrtric/capifcore/internal/providermanagement"
36 "oransc.org/nonrtric/capifcore/internal/publishservice"
38 "github.com/labstack/echo/v4"
40 invokermocks "oransc.org/nonrtric/capifcore/internal/invokermanagement/mocks"
41 keycloackmocks "oransc.org/nonrtric/capifcore/internal/keycloak/mocks"
42 servicemocks "oransc.org/nonrtric/capifcore/internal/providermanagement/mocks"
43 publishmocks "oransc.org/nonrtric/capifcore/internal/publishservice/mocks"
45 "github.com/deepmap/oapi-codegen/pkg/middleware"
46 "github.com/deepmap/oapi-codegen/pkg/testutil"
47 echomiddleware "github.com/labstack/echo/v4/middleware"
48 "github.com/stretchr/testify/assert"
49 "github.com/stretchr/testify/mock"
52 func TestPostSecurityIdTokenInvokerRegistered(t *testing.T) {
53 invokerRegisterMock := invokermocks.InvokerRegister{}
54 invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
55 invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true)
56 serviceRegisterMock := servicemocks.ServiceRegister{}
57 serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(true)
58 publishRegisterMock := publishmocks.PublishRegister{}
59 publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true)
61 jwt := keycloak.Jwttoken{
62 AccessToken: "eyJhbGNIn0.e3YTQ0xLjEifQ.FcqCwCy7iJiOmw",
64 Scope: "3gpp#aefIdpath",
66 accessMgmMock := keycloackmocks.AccessManagement{}
67 accessMgmMock.On("GetToken", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(jwt, nil)
69 requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
73 clientSecret := "secret"
76 data.Set("client_id", clientId)
77 data.Set("client_secret", clientSecret)
78 data.Set("grant_type", "client_credentials")
79 data.Set("scope", "3gpp#"+aefId+":"+path)
81 encodedData := data.Encode()
83 result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler)
85 assert.Equal(t, http.StatusCreated, result.Code())
86 var resultResponse securityapi.AccessTokenRsp
87 err := result.UnmarshalBodyToObject(&resultResponse)
88 assert.NoError(t, err, "error unmarshaling response")
89 assert.NotEmpty(t, resultResponse.AccessToken)
90 assert.Equal(t, securityapi.AccessTokenRspTokenTypeBearer, resultResponse.TokenType)
91 invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", clientId)
92 invokerRegisterMock.AssertCalled(t, "VerifyInvokerSecret", clientId, clientSecret)
93 serviceRegisterMock.AssertCalled(t, "IsFunctionRegistered", aefId)
94 publishRegisterMock.AssertCalled(t, "IsAPIPublished", aefId, path)
95 accessMgmMock.AssertCalled(t, "GetToken", clientId, clientSecret, "3gpp#"+aefId+":"+path, "invokerrealm")
98 func TestPostSecurityIdTokenInvokerNotRegistered(t *testing.T) {
99 invokerRegisterMock := invokermocks.InvokerRegister{}
100 invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(false)
102 requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil)
105 data.Set("client_id", "id")
106 data.Add("client_secret", "secret")
107 data.Add("grant_type", "client_credentials")
108 data.Add("scope", "3gpp#aefId:path")
109 encodedData := data.Encode()
111 result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler)
113 assert.Equal(t, http.StatusBadRequest, result.Code())
114 var errDetails securityapi.AccessTokenErr
115 err := result.UnmarshalBodyToObject(&errDetails)
116 assert.NoError(t, err, "error unmarshaling response")
117 assert.Equal(t, securityapi.AccessTokenErrErrorInvalidClient, errDetails.Error)
118 errMsg := "Invoker not registered"
119 assert.Equal(t, &errMsg, errDetails.ErrorDescription)
122 func TestPostSecurityIdTokenInvokerSecretNotValid(t *testing.T) {
123 invokerRegisterMock := invokermocks.InvokerRegister{}
124 invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
125 invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(false)
127 requestHandler := getEcho(nil, nil, &invokerRegisterMock, nil)
130 data.Set("client_id", "id")
131 data.Add("client_secret", "secret")
132 data.Add("grant_type", "client_credentials")
133 data.Add("scope", "3gpp#aefId:path")
134 encodedData := data.Encode()
136 result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler)
138 assert.Equal(t, http.StatusBadRequest, result.Code())
139 var errDetails securityapi.AccessTokenErr
140 err := result.UnmarshalBodyToObject(&errDetails)
141 assert.NoError(t, err, "error unmarshaling response")
142 assert.Equal(t, securityapi.AccessTokenErrErrorUnauthorizedClient, errDetails.Error)
143 errMsg := "Invoker secret not valid"
144 assert.Equal(t, &errMsg, errDetails.ErrorDescription)
147 func TestPostSecurityIdTokenFunctionNotRegistered(t *testing.T) {
148 invokerRegisterMock := invokermocks.InvokerRegister{}
149 invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
150 invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true)
151 serviceRegisterMock := servicemocks.ServiceRegister{}
152 serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(false)
154 requestHandler := getEcho(&serviceRegisterMock, nil, &invokerRegisterMock, nil)
157 data.Set("client_id", "id")
158 data.Add("client_secret", "secret")
159 data.Add("grant_type", "client_credentials")
160 data.Add("scope", "3gpp#aefId:path")
161 encodedData := data.Encode()
163 result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler)
165 assert.Equal(t, http.StatusBadRequest, result.Code())
166 var errDetails securityapi.AccessTokenErr
167 err := result.UnmarshalBodyToObject(&errDetails)
168 assert.NoError(t, err, "error unmarshaling response")
169 assert.Equal(t, securityapi.AccessTokenErrErrorInvalidScope, errDetails.Error)
170 errMsg := "AEF Function not registered"
171 assert.Equal(t, &errMsg, errDetails.ErrorDescription)
174 func TestPostSecurityIdTokenAPINotPublished(t *testing.T) {
175 invokerRegisterMock := invokermocks.InvokerRegister{}
176 invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
177 invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true)
178 serviceRegisterMock := servicemocks.ServiceRegister{}
179 serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(true)
180 publishRegisterMock := publishmocks.PublishRegister{}
181 publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(false)
183 requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, nil)
186 data.Set("client_id", "id")
187 data.Add("client_secret", "secret")
188 data.Add("grant_type", "client_credentials")
189 data.Add("scope", "3gpp#aefId:path")
190 encodedData := data.Encode()
192 result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler)
194 assert.Equal(t, http.StatusBadRequest, result.Code())
195 var errDetails securityapi.AccessTokenErr
196 err := result.UnmarshalBodyToObject(&errDetails)
197 assert.NoError(t, err, "error unmarshaling response")
198 assert.Equal(t, securityapi.AccessTokenErrErrorInvalidScope, errDetails.Error)
199 errMsg := "API not published"
200 assert.Equal(t, &errMsg, errDetails.ErrorDescription)
203 func TestPostSecurityIdTokenInvokerInvalidCredentials(t *testing.T) {
204 invokerRegisterMock := invokermocks.InvokerRegister{}
205 invokerRegisterMock.On("IsInvokerRegistered", mock.AnythingOfType("string")).Return(true)
206 invokerRegisterMock.On("VerifyInvokerSecret", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true)
207 serviceRegisterMock := servicemocks.ServiceRegister{}
208 serviceRegisterMock.On("IsFunctionRegistered", mock.AnythingOfType("string")).Return(true)
209 publishRegisterMock := publishmocks.PublishRegister{}
210 publishRegisterMock.On("IsAPIPublished", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true)
212 jwt := keycloak.Jwttoken{}
213 accessMgmMock := keycloackmocks.AccessManagement{}
214 accessMgmMock.On("GetToken", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(jwt, errors.New("invalid_credentials"))
216 requestHandler := getEcho(&serviceRegisterMock, &publishRegisterMock, &invokerRegisterMock, &accessMgmMock)
220 clientSecret := "secret"
223 data.Set("client_id", clientId)
224 data.Set("client_secret", clientSecret)
225 data.Set("grant_type", "client_credentials")
226 data.Set("scope", "3gpp#"+aefId+":"+path)
228 encodedData := data.Encode()
230 result := testutil.NewRequest().Post("/securities/invokerId/token").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(encodedData)).Go(t, requestHandler)
232 assert.Equal(t, http.StatusBadRequest, result.Code())
233 var resultResponse securityapi.AccessTokenErr
234 err := result.UnmarshalBodyToObject(&resultResponse)
235 assert.NoError(t, err, "error unmarshaling response")
236 invokerRegisterMock.AssertCalled(t, "IsInvokerRegistered", clientId)
237 invokerRegisterMock.AssertCalled(t, "VerifyInvokerSecret", clientId, clientSecret)
238 serviceRegisterMock.AssertCalled(t, "IsFunctionRegistered", aefId)
239 publishRegisterMock.AssertCalled(t, "IsAPIPublished", aefId, path)
240 accessMgmMock.AssertCalled(t, "GetToken", clientId, clientSecret, "3gpp#"+aefId+":"+path, "invokerrealm")
243 func getEcho(serviceRegister providermanagement.ServiceRegister, publishRegister publishservice.PublishRegister, invokerRegister invokermanagement.InvokerRegister, keycloakMgm keycloak.AccessManagement) *echo.Echo {
244 swagger, err := securityapi.GetSwagger()
246 fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
250 swagger.Servers = nil
252 s := NewSecurity(serviceRegister, publishRegister, invokerRegister, keycloakMgm)
255 e.Use(echomiddleware.Logger())
256 e.Use(middleware.OapiRequestValidator(swagger))
258 securityapi.RegisterHandlers(e, s)