From ccea526a9ba642d726817b6bc1eeb1d4062b53cb Mon Sep 17 00:00:00 2001 From: Michael Dürre Date: Thu, 14 Mar 2024 11:54:26 +0100 Subject: fix oauth code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit split oauth to realm and web functionality Issue-ID: CCSDK-3394 Change-Id: I245a30a9df4e9a5c40af5dfe3e0d5318bceed9dc Signed-off-by: Michael Dürre --- sdnr/wt/featureaggregator/feature-oauth/pom.xml | 16 +- sdnr/wt/featureaggregator/installer/pom.xml | 4 +- sdnr/wt/featureaggregator/pom.xml | 2 +- sdnr/wt/oauth-provider/oauth-core/pom.xml | 191 ++++++ .../sdnr/wt/oauthprovider/OAuth2Realm.java | 143 +++++ .../sdnr/wt/oauthprovider/data/Config.java | 347 +++++++++++ .../wt/oauthprovider/data/CustomObjectMapper.java | 39 ++ .../data/InvalidConfigurationException.java | 32 + .../sdnr/wt/oauthprovider/data/KeycloakRole.java | 80 +++ .../data/KeycloakUserTokenPayload.java | 231 +++++++ .../data/NoDefinitionFoundException.java | 33 + .../wt/oauthprovider/data/OAuthProviderConfig.java | 202 ++++++ .../wt/oauthprovider/data/OAuthResponseData.java | 88 +++ .../sdnr/wt/oauthprovider/data/OAuthToken.java | 57 ++ .../sdnr/wt/oauthprovider/data/OdlPolicy.java | 130 ++++ .../oauthprovider/data/OdlShiroConfiguration.java | 67 ++ .../sdnr/wt/oauthprovider/data/OdlXmlMapper.java | 44 ++ .../data/OpenIdConfigResponseData.java | 65 ++ .../data/UnableToConfigureOAuthService.java | 12 + .../wt/oauthprovider/data/UserTokenPayload.java | 103 +++ .../filters/AnyRoleHttpAuthenticationFilter.java | 75 +++ .../BearerAndBasicHttpAuthenticationFilter.java | 161 +++++ .../CustomizedMDSALDynamicAuthorizationFilter.java | 188 ++++++ .../wt/oauthprovider/http/AuthHttpServlet.java | 527 ++++++++++++++++ .../http/HeadersOnlyHttpServletRequest.java | 469 ++++++++++++++ .../http/client/MappedBaseHttpResponse.java | 63 ++ .../http/client/MappingBaseHttpClient.java | 63 ++ .../wt/oauthprovider/providers/AuthService.java | 356 +++++++++++ .../providers/GitlabProviderService.java | 180 ++++++ .../providers/KeycloakProviderService.java | 115 ++++ .../providers/MdSalAuthorizationStore.java | 118 ++++ .../providers/NextcloudProviderService.java | 91 +++ .../providers/OAuthProviderFactory.java | 47 ++ .../sdnr/wt/oauthprovider/providers/PemUtils.java | 106 ++++ .../wt/oauthprovider/providers/RSAKeyReader.java | 47 ++ .../wt/oauthprovider/providers/TokenCreator.java | 202 ++++++ .../wt/oauthprovider/test/TestAuthHttpServlet.java | 404 ++++++++++++ .../sdnr/wt/oauthprovider/test/TestConfig.java | 80 +++ .../wt/oauthprovider/test/TestDeserializer.java | 101 +++ .../oauthprovider/test/TestGitlabAuthService.java | 198 ++++++ .../test/TestKeycloakAuthService.java | 196 ++++++ .../sdnr/wt/oauthprovider/test/TestPolicy.java | 56 ++ .../sdnr/wt/oauthprovider/test/TestProperty.java | 42 ++ .../wt/oauthprovider/test/TestRSAAlgorithms.java | 108 ++++ .../sdnr/wt/oauthprovider/test/TestRealm.java | 219 +++++++ .../oauthprovider/test/helper/OdlJsonMapper.java | 65 ++ .../wt/oauthprovider/test/helper/OdlXmlMapper.java | 46 ++ .../src/test/resources/aaa-app-config.test.xml | 77 +++ .../oauth-core/src/test/resources/jwtRS256.key | 27 + .../oauth-core/src/test/resources/jwtRS256.key.pub | 9 + .../oauth-core/src/test/resources/jwtRS512.key | 51 ++ .../oauth-core/src/test/resources/jwtRS512.key.pub | 14 + .../src/test/resources/mdsalDynAuthData.json | 694 +++++++++++++++++++++ .../resources/oauth/gitlab-groups-response.json | 112 ++++ .../resources/oauth/gitlab-token-response.json | 7 + .../test/resources/oauth/gitlab-user-response.json | 32 + .../resources/oauth/keycloak-token-response.json | 11 + .../src/test/resources/oom.test.config.json | 21 + .../oauth-core/src/test/resources/test.config.json | 20 + .../test/resources/test.configRS256-invalid.json | 24 + .../src/test/resources/test.configRS256.json | 22 + .../src/test/resources/test.configRS512.json | 22 + sdnr/wt/oauth-provider/oauth-realm/pom.xml | 154 +++++ sdnr/wt/oauth-provider/oauth-web/pom.xml | 155 +++++ .../org/opendaylight/blueprint/impl-blueprint.xml | 41 ++ sdnr/wt/oauth-provider/pom.xml | 5 +- sdnr/wt/oauth-provider/provider-jar/pom.xml | 188 ------ .../features/sdnr/wt/oauthprovider/Helper.java | 66 -- .../sdnr/wt/oauthprovider/OAuth2Realm.java | 143 ----- .../sdnr/wt/oauthprovider/data/Config.java | 347 ----------- .../wt/oauthprovider/data/CustomObjectMapper.java | 39 -- .../data/InvalidConfigurationException.java | 32 - .../sdnr/wt/oauthprovider/data/KeycloakRole.java | 80 --- .../data/KeycloakUserTokenPayload.java | 231 ------- .../data/NoDefinitionFoundException.java | 33 - .../wt/oauthprovider/data/OAuthProviderConfig.java | 202 ------ .../wt/oauthprovider/data/OAuthResponseData.java | 88 --- .../sdnr/wt/oauthprovider/data/OAuthToken.java | 57 -- .../sdnr/wt/oauthprovider/data/OdlPolicy.java | 130 ---- .../data/OpenIdConfigResponseData.java | 65 -- .../data/UnableToConfigureOAuthService.java | 12 - .../wt/oauthprovider/data/UserTokenPayload.java | 103 --- .../filters/AnyRoleHttpAuthenticationFilter.java | 75 --- .../BearerAndBasicHttpAuthenticationFilter.java | 134 ---- .../CustomizedMDSALDynamicAuthorizationFilter.java | 171 ----- .../wt/oauthprovider/http/AuthHttpServlet.java | 507 --------------- .../http/HeadersOnlyHttpServletRequest.java | 469 -------------- .../http/client/MappedBaseHttpResponse.java | 63 -- .../http/client/MappingBaseHttpClient.java | 63 -- .../wt/oauthprovider/providers/AuthService.java | 356 ----------- .../providers/GitlabProviderService.java | 180 ------ .../providers/KeycloakProviderService.java | 115 ---- .../providers/MdSalAuthorizationStore.java | 118 ---- .../providers/NextcloudProviderService.java | 91 --- .../providers/OAuthProviderFactory.java | 47 -- .../sdnr/wt/oauthprovider/providers/PemUtils.java | 106 ---- .../wt/oauthprovider/providers/RSAKeyReader.java | 47 -- .../wt/oauthprovider/providers/TokenCreator.java | 204 ------ .../wt/oauthprovider/test/TestAuthHttpServlet.java | 369 ----------- .../sdnr/wt/oauthprovider/test/TestConfig.java | 80 --- .../wt/oauthprovider/test/TestDeserializer.java | 101 --- .../oauthprovider/test/TestGitlabAuthService.java | 198 ------ .../test/TestKeycloakAuthService.java | 196 ------ .../sdnr/wt/oauthprovider/test/TestPolicy.java | 56 -- .../sdnr/wt/oauthprovider/test/TestProperty.java | 42 -- .../wt/oauthprovider/test/TestRSAAlgorithms.java | 108 ---- .../sdnr/wt/oauthprovider/test/TestRealm.java | 227 ------- .../oauthprovider/test/helper/OdlJsonMapper.java | 65 -- .../wt/oauthprovider/test/helper/OdlXmlMapper.java | 46 -- .../src/test/resources/aaa-app-config.test.xml | 353 ----------- .../provider-jar/src/test/resources/jwtRS256.key | 27 - .../src/test/resources/jwtRS256.key.pub | 9 - .../provider-jar/src/test/resources/jwtRS512.key | 51 -- .../src/test/resources/jwtRS512.key.pub | 14 - .../src/test/resources/mdsalDynAuthData.json | 694 --------------------- .../resources/oauth/gitlab-groups-response.json | 112 ---- .../resources/oauth/gitlab-token-response.json | 7 - .../test/resources/oauth/gitlab-user-response.json | 32 - .../resources/oauth/keycloak-token-response.json | 11 - .../src/test/resources/oom.test.config.json | 21 - .../src/test/resources/test.config.json | 20 - .../test/resources/test.configRS256-invalid.json | 24 - .../src/test/resources/test.configRS256.json | 22 - .../src/test/resources/test.configRS512.json | 22 - sdnr/wt/oauth-provider/provider-osgi/pom.xml | 156 ----- .../org/opendaylight/blueprint/impl-blueprint.xml | 57 -- sdnr/wt/pom.xml | 2 +- 127 files changed, 7695 insertions(+), 7696 deletions(-) create mode 100644 sdnr/wt/oauth-provider/oauth-core/pom.xml create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlShiroConfiguration.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlXmlMapper.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/aaa-app-config.test.xml create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key.pub create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key.pub create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/mdsalDynAuthData.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-groups-response.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-token-response.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-user-response.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/keycloak-token-response.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/oom.test.config.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.config.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256-invalid.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256.json create mode 100644 sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS512.json create mode 100644 sdnr/wt/oauth-provider/oauth-realm/pom.xml create mode 100644 sdnr/wt/oauth-provider/oauth-web/pom.xml create mode 100644 sdnr/wt/oauth-provider/oauth-web/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml delete mode 100644 sdnr/wt/oauth-provider/provider-jar/pom.xml delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/Helper.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/aaa-app-config.test.xml delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key.pub delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key.pub delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/mdsalDynAuthData.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-groups-response.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-token-response.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-user-response.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/keycloak-token-response.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/oom.test.config.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256-invalid.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256.json delete mode 100644 sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS512.json delete mode 100644 sdnr/wt/oauth-provider/provider-osgi/pom.xml delete mode 100644 sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml diff --git a/sdnr/wt/featureaggregator/feature-oauth/pom.xml b/sdnr/wt/featureaggregator/feature-oauth/pom.xml index b79b320e6..707dc7801 100644 --- a/sdnr/wt/featureaggregator/feature-oauth/pom.xml +++ b/sdnr/wt/featureaggregator/feature-oauth/pom.xml @@ -22,6 +22,7 @@ ~ ============LICENSE_END======================================================= ~ --> + 4.0.0 @@ -34,7 +35,7 @@ org.onap.ccsdk.features.sdnr.wt sdnr-wt-feature-aggregator-oauth - 1.6.0-SNAPSHOT + 1.7.0-SNAPSHOT feature ccsdk-features :: ${project.artifactId} @@ -47,14 +48,13 @@ ${project.groupId} - sdnr-wt-oauth-provider + sdnr-wt-oauth-web + ${project.version} + + + ${project.groupId} + sdnr-wt-oauth-realm ${project.version} - - - ${project.groupId} - sdnr-wt-oauth-provider-jar - - diff --git a/sdnr/wt/featureaggregator/installer/pom.xml b/sdnr/wt/featureaggregator/installer/pom.xml index ce1e3fe98..1c0e15597 100755 --- a/sdnr/wt/featureaggregator/installer/pom.xml +++ b/sdnr/wt/featureaggregator/installer/pom.xml @@ -65,13 +65,13 @@ xml features - + ${project.groupId} sdnr-wt-data-provider-setup diff --git a/sdnr/wt/featureaggregator/pom.xml b/sdnr/wt/featureaggregator/pom.xml index f0349e472..c0fb6e7bf 100755 --- a/sdnr/wt/featureaggregator/pom.xml +++ b/sdnr/wt/featureaggregator/pom.xml @@ -41,7 +41,7 @@ feature - + feature-oauth feature-devicemanager feature-devicemanager-base installer diff --git a/sdnr/wt/oauth-provider/oauth-core/pom.xml b/sdnr/wt/oauth-provider/oauth-core/pom.xml new file mode 100644 index 000000000..ef00bf8e9 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/pom.xml @@ -0,0 +1,191 @@ + + + + + 4.0.0 + + + org.onap.ccsdk.parent + binding-parent + 2.6.1 + + + + org.onap.ccsdk.features.sdnr.wt + sdnr-wt-oauth-core + 1.7.0-SNAPSHOT + jar + + ccsdk-features :: ${project.artifactId} + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + true + true + + + + ${project.groupId} + sdnr-wt-common + ${project.version} + + + com.fasterxml.jackson.core + jackson-databind + provided + + + com.auth0 + java-jwt + + + org.bouncycastle + bcprov-jdk15on + + + org.opendaylight.aaa + aaa-shiro + + + org.opendaylight.aaa + aaa-cert + + + org.opendaylight.aaa + aaa-filterchain + + + org.opendaylight.aaa + aaa-password-service-api + + + org.opendaylight.aaa.web + web-api + + + org.opendaylight.aaa.web + servlet-api + + + commons-collections + commons-collections + + + commons-text + commons-text + + + com.google.code.gson + gson + + + org.opendaylight.mdsal + mdsal-binding-api + + + com.h2database + h2 + + + com.google.guava + guava + + + ehcache-root + ehcache + + + + + org.opendaylight.mdsal + mdsal-binding-api + provided + + + org.opendaylight.mdsal + yang-binding + provided + + + org.osgi + org.osgi.core + provided + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + ${project.groupId} + sdnr-wt-yang-utils + ${project.version} + + + org.osgi + osgi.cmpn + compile + + + javax.servlet + javax.servlet-api + provided + + + org.mockito + mockito-core + test + + + org.eclipse.jetty + jetty-server + test + + + org.eclipse.jetty + jetty-servlet + test + + + org.opendaylight.mdsal.binding.model.ietf + rfc6991-ietf-yang-types + test + + + org.opendaylight.netconf + sal-netconf-connector + test + + + org.osgi + org.osgi.core + test + + + diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java new file mode 100644 index 000000000..b9f3d6119 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java @@ -0,0 +1,143 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider; + +import com.auth0.jwt.interfaces.DecodedJWT; +import java.io.IOException; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.subject.PrincipalCollection; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; +import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal; +import org.apache.shiro.authc.BearerToken; +import org.opendaylight.aaa.shiro.realm.TokenAuthRealm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OAuth2Realm extends TokenAuthRealm { + + public static final String REALM_NAME = "OAuth2Realm"; + private static final Logger LOG = LoggerFactory.getLogger(OAuth2Realm.class); + private final TokenCreator tokenCreator; + private final Config config; + + public OAuth2Realm() throws IllegalArgumentException, IOException, InvalidConfigurationException { + super(); + super.setName(REALM_NAME); + this.config = Config.getInstance(); + this.tokenCreator = TokenCreator.getInstance(this.config); + LOG.info("instantiated"); + } + + @Override + public boolean supports(AuthenticationToken token) { + boolean supports = (token instanceof BearerToken) + || (this.config.doSupportOdlUsers() && (token instanceof UsernamePasswordToken)); + LOG.debug("supports {} is {}", token == null ? null : token.getClass().getName(), supports); + return supports; + } + + @Override + public String getName() { + return REALM_NAME; + } + + @Override + protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai) + throws AuthenticationException { + LOG.debug("assertCredentialsMatch"); + if (atoken instanceof BearerToken) { + if (this.tokenCreator.verify(((BearerToken) atoken).getToken()) == null) { + throw new AuthenticationException("Credentials do not match"); + } + } else if (this.config.doSupportOdlUsers() && (atoken instanceof UsernamePasswordToken)) { + //nothing to do + } else { + throw new AuthenticationException("AuthenticationInfo is not an OAuth2AuthenticationInfo"); + } + } + + + // check what I can do + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) { + + LOG.debug("auth info in shiro"); + Object principal = arg.getPrimaryPrincipal(); + if (principal instanceof DecodedJWT) { + LOG.debug("detected jwt token"); + try { + DecodedJWT token = (DecodedJWT) arg.getPrimaryPrincipal(); + String[] roles = token.getClaim("roles").asArray(String.class); + SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); + for (String role : roles) { + LOG.trace("found role {} in token", role); + authorizationInfo.addRole(role); + } + return authorizationInfo; + } catch (ClassCastException e) { + LOG.error("Couldn't decode authorization request", e); + } + } else if (principal instanceof ODLPrincipal) { + LOG.debug("detected basic token"); + ODLPrincipal odlPrincipal = (ODLPrincipal) principal; + return new SimpleAuthorizationInfo(odlPrincipal.getRoles()); + } + return new SimpleAuthorizationInfo(); + } + + + + // check who I am + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + + LOG.debug("auth token in shiro:"); + if (token instanceof UsernamePasswordToken && this.config.doSupportOdlUsers()) { + LOG.debug("basic auth token found"); + return super.doGetAuthenticationInfo(token); + } else if (token instanceof BearerToken) { + LOG.debug("jwt token found"); + BearerToken oauthToken = (BearerToken) token; + + DecodedJWT jwt = this.tokenCreator.verify(oauthToken.getToken()); + if (jwt != null) { + SimpleAuthenticationInfo authenticationInfo = + new SimpleAuthenticationInfo(jwt, token.getCredentials(), getName()); + return authenticationInfo; + + } + } else { + LOG.debug("no valid token found"); + } + throw new AuthenticationException("unable to verify token " + token); + + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java new file mode 100644 index 000000000..6798026f3 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java @@ -0,0 +1,347 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSetter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Config { + + private static final Logger LOG = LoggerFactory.getLogger(Config.class); + private static final String DEFAULT_CONFIGFILENAME = "etc/oauth-provider.config.json"; + private static final String ENVVARIABLE = "${"; + private static final String REGEXENVVARIABLE = "(\\$\\{[A-Z0-9_-]+\\})"; + private static final Pattern pattern = Pattern.compile(REGEXENVVARIABLE); + private static final String DEFAULT_TOKENISSUER = "Opendaylight"; + private static final String DEFAULT_TOKENSECRET = generateSecret(); + private static final String DEFAULT_REDIRECTURI = "/odlux/index.html#/oauth?token="; + private static final String DEFAULT_SUPPORTODLUSERS = "true"; + public static final String TOKENALG_HS256 = "HS256"; + public static final String TOKENALG_RS256 = "RS256"; + public static final String TOKENALG_RS512 = "RS512"; + private static final String CLIENTALG_PRE = "Client"; + public static final String TOKENALG_CLIENT_RS256 = CLIENTALG_PRE + TOKENALG_RS256; + public static final String TOKENALG_CLIENT_RS512 = CLIENTALG_PRE + TOKENALG_RS512; + private static final String DEFAULT_TOKEN_ALGORITHM = TOKENALG_HS256; + + private static final long DEFAULT_TOKEN_LIFETIME = 30 * 60; + private static final List VALID_ALGORITHMS = + Arrays.asList(TOKENALG_HS256, TOKENALG_RS256, TOKENALG_RS512, TOKENALG_CLIENT_RS256, TOKENALG_CLIENT_RS512); + private static final List VALID_ALGORITHMS_FOR_INTERNAL_LOGIN = + Arrays.asList(TOKENALG_HS256, TOKENALG_RS256, TOKENALG_RS512); + private static SecureRandom random; + private static Config _instance; + + private List providers; + private String redirectUri; + private String supportOdlUsers; + private String tokenSecret; + private String tokenPubKey; + private String algorithm; + private String tokenIssuer; + private String publicUrl; + private long tokenLifetime; + + @Override + public String toString() { + return "Config [providers=" + providers + ", redirectUri=" + redirectUri + ", supportOdlUsers=" + + supportOdlUsers + ", tokenSecret=***, tokenPubKey=" + tokenPubKey + ", algorithm=" + algorithm + + ", tokenIssuer=" + tokenIssuer + ", publicUrl=" + publicUrl + ", tokenLifetime=" + tokenLifetime + + "]"; + } + + public List getProviders() { + return providers; + } + + public void setProviders(List providers) { + this.providers = providers; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public String getSupportOdlUsers() { + return supportOdlUsers; + } + + public void setSupportOdlUsers(String supportOdlUsers) { + this.supportOdlUsers = supportOdlUsers; + } + + public String getTokenSecret() { + return tokenSecret; + } + + public void setTokenSecret(String tokenSecret) { + this.tokenSecret = tokenSecret; + } + + public String getAlgorithm() { + return this.algorithm; + } + + public void setAlgorithm(String alg) { + this.algorithm = alg; + } + + @JsonGetter("tokenPubKey") + public String getPublicKey() { + return this.tokenPubKey; + } + + @JsonSetter("tokenPubKey") + public void setPublicKey(String pubKey) { + this.tokenPubKey = pubKey; + } + + public String getTokenIssuer() { + return tokenIssuer; + } + + public void setTokenIssuer(String tokenIssuer) { + this.tokenIssuer = tokenIssuer; + } + + public String getPublicUrl() { + return publicUrl; + } + + public void setPublicUrl(String publicUrl) { + this.publicUrl = publicUrl; + } + + public long getTokenLifetime() { + return this.tokenLifetime; + } + + public void setTokenLifetime(long lifetime) { + this.tokenLifetime = lifetime; + } + + @JsonIgnore + private void handleEnvironmentVars() { + if (isEnvExpression(this.tokenIssuer)) { + this.tokenIssuer = getProperty(this.tokenIssuer, null); + } + if (isEnvExpression(this.tokenSecret)) { + this.tokenSecret = getProperty(this.tokenSecret, null); + } + if (isEnvExpression(this.tokenPubKey)) { + this.tokenPubKey = getProperty(this.tokenPubKey, null); + } + if (isEnvExpression(this.algorithm)) { + this.algorithm = getProperty(this.algorithm, null); + } + if (isEnvExpression(this.publicUrl)) { + this.publicUrl = getProperty(this.publicUrl, null); + } + if (isEnvExpression(this.redirectUri)) { + this.redirectUri = getProperty(this.redirectUri, null); + } + if (isEnvExpression(this.supportOdlUsers)) { + this.supportOdlUsers = getProperty(this.supportOdlUsers, null); + } + if (this.providers != null && !this.providers.isEmpty()) { + for (OAuthProviderConfig cfg : this.providers) { + cfg.handleEnvironmentVars(); + } + } + } + + @JsonIgnore + private void handleDefaultValues() { + if (this.tokenIssuer == null || this.tokenIssuer.isEmpty()) { + this.tokenIssuer = DEFAULT_TOKENISSUER; + } + if (this.algorithm == null || this.algorithm.isEmpty()) { + this.algorithm = DEFAULT_TOKEN_ALGORITHM; + } + if (TOKENALG_HS256.equals(this.algorithm) && (this.tokenSecret == null || this.tokenSecret.isEmpty())) { + this.tokenSecret = DEFAULT_TOKENSECRET; + } + if (this.redirectUri == null || this.redirectUri.isEmpty() || "null".equals(this.redirectUri)) { + this.redirectUri = DEFAULT_REDIRECTURI; + } + if (this.publicUrl != null && (this.publicUrl.isEmpty() || "null".equals(this.publicUrl))) { + this.publicUrl = null; + } + if (this.supportOdlUsers == null || this.supportOdlUsers.isEmpty()) { + this.supportOdlUsers = DEFAULT_SUPPORTODLUSERS; + } + if (this.tokenLifetime <= 0) { + this.tokenLifetime = DEFAULT_TOKEN_LIFETIME; + } + } + + static boolean isEnvExpression(String key) { + return key != null && key.contains(ENVVARIABLE); + } + + public static String generateSecret() { + return generateSecret(30); + } + + public static String generateSecret(int targetStringLength) { + int leftLimit = 48; // numeral '0' + int rightLimit = 122; // letter 'z' + if (random == null) { + random = new SecureRandom(); + } + String generatedString = random.ints(leftLimit, rightLimit + 1) + .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)).limit(targetStringLength) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); + return generatedString; + } + + /** + * + * @param key environment var + * @param defValue default value if no env var found + * @return + */ + public static String getProperty(final String key, final String defValue) { + String value = defValue; + //try to read env var + boolean found = false; + if (isEnvExpression(key)) { + + LOG.info("try to find env var(s) for {}", key); + final Matcher matcher = pattern.matcher(key); + String tmp = new String(key); + while (matcher.find() && matcher.groupCount() > 0) { + final String mkey = matcher.group(1); + if (mkey != null) { + try { + LOG.info("match found for v={} and env key={}", key, mkey); + String envvar = mkey.substring(2, mkey.length() - 1); + String env = System.getenv(envvar); + tmp = tmp.replace(mkey, env == null ? "" : env); + if (env != null && !env.isEmpty()) { + found = true; + } + } catch (SecurityException e) { + LOG.warn("unable to read env {}: {}", key, e); + } + } + } + if (found) { + value = tmp; + } + } + return value; + } + + public static boolean getPropertyBoolean(String key, boolean defaultValue) { + final String value = getProperty(key, String.valueOf(defaultValue)); + return value.equals("true"); + } + + public static Config load(String filename) throws IOException, InvalidConfigurationException { + CustomObjectMapper mapper = new CustomObjectMapper(); + File file = new File(filename); + if (!file.exists()) { + throw new FileNotFoundException(); + } + String content = String.join("", Files.readAllLines(file.toPath())); + Config cfg = mapper.readValue(content, Config.class); + cfg.handleEnvironmentVars(); + cfg.handleDefaultValues(); + cfg.validate(); + return cfg; + } + + + @JsonIgnore + private void validate() throws InvalidConfigurationException { + //verify that algorithm is supported + if (!VALID_ALGORITHMS.contains(this.algorithm)) { + throw new InvalidConfigurationException(String.format("Algorithm '%s' is not supported ", this.algorithm)); + } + //verify that set values are matching the algorithm + //if hs256 check if secret is set + if (this.algorithm.startsWith("HS")) { + if (this.tokenSecret == null || this.tokenSecret.isBlank()) { + throw new InvalidConfigurationException( + String.format("There is no secret set for algorithm '%s'", this.algorithm)); + } + } + //if rs256 or rs512 check if secret(private key) and pubkey are set + if (this.algorithm.startsWith("RS")) { + if (this.tokenSecret == null || this.tokenSecret.isBlank()) { + throw new InvalidConfigurationException( + String.format("There is no secret set for algorithm '%s'", this.algorithm)); + } + if (this.tokenPubKey == null || this.tokenPubKey.isBlank()) { + throw new InvalidConfigurationException( + String.format("There is no public key for algorithm '%s'", this.algorithm)); + } + } + //if client rs256 or client rs512 check if pubkey are set + if (this.algorithm.startsWith("Client")) { + if (this.tokenPubKey == null || this.tokenPubKey.isBlank()) { + throw new InvalidConfigurationException( + String.format("There is no public key for algorithm '%s'", this.algorithm)); + } + } + } + + @JsonIgnore + public boolean doSupportOdlUsers() { + return "true".equals(this.supportOdlUsers); + } + + + public static Config getInstance() throws IOException, InvalidConfigurationException { + return getInstance(DEFAULT_CONFIGFILENAME); + } + + public static Config getInstance(String filename) throws IOException, InvalidConfigurationException { + if (_instance == null) { + _instance = load(filename); + } + return _instance; + } + + public boolean loginActive() { + return VALID_ALGORITHMS_FOR_INTERNAL_LOGIN.contains(this.algorithm); + } + + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java new file mode 100644 index 000000000..aa23d4dc1 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class CustomObjectMapper extends ObjectMapper{ + + private static final long serialVersionUID = 1L; + + + public CustomObjectMapper() { + this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.setSerializationInclusion(Include.NON_NULL); + this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java new file mode 100644 index 000000000..a0e97de74 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class InvalidConfigurationException extends Exception { + + public InvalidConfigurationException(String str) { + super(str); + } + + private static final long serialVersionUID = 1L; + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java new file mode 100644 index 000000000..67186baa7 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class KeycloakRole { + private String id; + private String name; + private String description; + private boolean composite; + private boolean clientRole; + private String containerId; // realmname + + public String getName() { + return name; + } + + public boolean isClientRole() { + return clientRole; + } + + public void setClientRole(boolean clientRole) { + this.clientRole = clientRole; + } + + public String getContainerId() { + return containerId; + } + + public void setContainerId(String containerId) { + this.containerId = containerId; + } + + public boolean isComposite() { + return composite; + } + + public void setComposite(boolean composite) { + this.composite = composite; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java new file mode 100644 index 000000000..c99ec0d71 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java @@ -0,0 +1,231 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** + * { + "exp": 1610362593, + "iat": 1610361393, + "jti": "09bd6f2c-5dba-44a0-bd76-cd0d440137d0", + "iss": "http://10.20.11.160:8080/auth/realms/onap", + "aud": "account", + "sub": "446a24bc-d8a0-43dd-afa5-e56eed75deb8", + "typ": "Bearer", + "azp": "admin-cli", + "session_state": "db2c96f4-cc9b-47e8-a83f-a01c50d656f2", + "acr": "1", + "realm_access": { + "roles": [ + "provision", + "offline_access", + "uma_authorization" + ] + }, + "resource_access": { + "account": { + "roles": [ + "manage-account", + "manage-account-links", + "view-profile" + ] + } + }, + "scope": "profile email", + "email_verified": false, + "name": "Luke Skywalker", + "preferred_username": "luke.skywalker", + "given_name": "Luke", + "family_name": "Skywalker", + "email": "luke.skywalker@sdnr.onap.org" +} + * @author jack + * + */ +public class KeycloakUserTokenPayload { + + private long exp; + private long iat; + private String jti; + private String iss; + private String aud; + private String sub; + private String typ; + private String azp; + @JsonProperty("session_state") + private String sessionState; + private String acr; + @JsonProperty("realm_access") + private RealmAccessData realmAccess; + @JsonProperty("resource_access") + private ResourceAccessData resourceAccess; + private String scope; + @JsonProperty("email_verified") + private String emailVerified; + private String name; + @JsonProperty("preferred_username") + private String preferredUsername; + @JsonProperty("given_name") + private String givenName; + @JsonProperty("family_name") + private String familyName; + private String email; + + public long getExp() { + return exp; + } + public void setExp(long exp) { + this.exp = exp; + } + public long getIat() { + return iat; + } + public void setIat(long iat) { + this.iat = iat; + } + public String getJti() { + return jti; + } + public void setJti(String jti) { + this.jti = jti; + } + public String getIss() { + return iss; + } + public void setIss(String iss) { + this.iss = iss; + } + public String getAud() { + return aud; + } + public void setAud(String aud) { + this.aud = aud; + } + public String getSub() { + return sub; + } + public void setSub(String sub) { + this.sub = sub; + } + public String getTyp() { + return typ; + } + public void setTyp(String typ) { + this.typ = typ; + } + public String getAzp() { + return azp; + } + public void setAzp(String azp) { + this.azp = azp; + } + public String getSessionState() { + return sessionState; + } + public void setSessionState(String sessionState) { + this.sessionState = sessionState; + } + public String getAcr() { + return acr; + } + public void setAcr(String acr) { + this.acr = acr; + } + public RealmAccessData getRealmAccess() { + return realmAccess; + } + public void setRealmAccess(RealmAccessData realmAccess) { + this.realmAccess = realmAccess; + } + public ResourceAccessData getResourceAccess() { + return resourceAccess; + } + public void setResourceAccess(ResourceAccessData resourceAccess) { + this.resourceAccess = resourceAccess; + } + public String getScope() { + return scope; + } + public void setScope(String scope) { + this.scope = scope; + } + public String getEmailVerified() { + return emailVerified; + } + public void setEmailVerified(String emailVerified) { + this.emailVerified = emailVerified; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public String getPreferredUsername() { + return preferredUsername; + } + public void setPreferredUsername(String preferredUsername) { + this.preferredUsername = preferredUsername; + } + public String getGivenName() { + return givenName; + } + public void setGivenName(String givenName) { + this.givenName = givenName; + } + public String getFamilyName() { + return familyName; + } + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + + public static class RealmAccessData { + private List roles; + + public List getRoles(){ + return this.roles; + } + public void setRoles(List roles) { + this.roles = roles; + } + } + public static class ResourceAccessData { + private RealmAccessData account; + + public RealmAccessData getAccount() { + return this.account; + } + public void setAccount(RealmAccessData account) { + this.account = account; + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java new file mode 100644 index 000000000..d13be9602 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class NoDefinitionFoundException extends Exception { + + private static final long serialVersionUID = 1L; + + public NoDefinitionFoundException(String message) { + super(message); + } + + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java new file mode 100644 index 000000000..4fb0d0069 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java @@ -0,0 +1,202 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.HashMap; +import java.util.Map; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.OAuthProviderFactory.OAuthProvider; + +public class OAuthProviderConfig { + + private String url; + private String internalUrl; + private String clientId; + private String secret; + private String id; + private String title; + private String scope; + private String realmName; + private String openIdConfigUrl; + + private boolean trustAll; + private OAuthProvider type; + private Map roleMapping; + + public OAuthProvider getType() { + return type; + } + + public OAuthProviderConfig(String id, String url, String internalUrl, String clientId, String secret, String scope, + String title, String realmName, String openIdConfigUrl, boolean trustAll) { + this.id = id; + this.url = url; + this.internalUrl = internalUrl; + this.clientId = clientId; + this.secret = secret; + this.scope = scope; + this.title = title; + this.realmName = realmName; + this.trustAll = trustAll; + this.openIdConfigUrl = openIdConfigUrl; + this.roleMapping = new HashMap<>(); + } + + @Override + public String toString() { + return "OAuthProviderConfig [url=" + url + ", clientId=" + clientId + ", secret=" + secret + ", id=" + id + + ", title=" + title + ", scope=" + scope + ", realmName=" + realmName + ", trustAll=" + trustAll + + ", type=" + type + ", roleMapping=" + roleMapping + "]"; + } + + public void setType(OAuthProvider type) { + this.type = type; + } + + public OAuthProviderConfig() { + this(null, null, null, null, null, null, null, null, null, false); + } + + public void setUrl(String url) { + this.url = url; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public void setId(String id) { + this.id = id; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getId() { + return this.id; + } + + public String getUrl() { + return this.url; + } + + public String getClientId() { + return this.clientId; + } + + public String getSecret() { + return this.secret; + } + + public String getTitle() { + return this.title; + } + + public String getScope() { + return this.scope; + } + + public String getRealmName() { + return realmName; + } + + public void setRealmName(String realmName) { + this.realmName = realmName; + } + + public boolean trustAll() { + return trustAll; + } + + public void setTrustAll(boolean trustAll) { + this.trustAll = trustAll; + } + + public Map getRoleMapping() { + return roleMapping; + } + + public void setRoleMapping(Map roleMapping) { + this.roleMapping = roleMapping; + } + + public String getInternalUrl() { + return internalUrl; + } + + public void setInternalUrl(String internalUrl) { + this.internalUrl = internalUrl; + } + + public void setOpenIdConfigUrl(String openIdConfigUrl){ this.openIdConfigUrl = openIdConfigUrl;} + + public String getOpenIdConfigUrl() { return this.openIdConfigUrl;} + @JsonIgnore + public void handleEnvironmentVars() { + if (Config.isEnvExpression(this.id)) { + this.id = Config.getProperty(this.id, null); + } + if (Config.isEnvExpression(this.url)) { + this.url = Config.getProperty(this.url, null); + } + if (Config.isEnvExpression(this.internalUrl)) { + this.internalUrl = Config.getProperty(this.internalUrl, null); + } + if (Config.isEnvExpression(this.clientId)) { + this.clientId = Config.getProperty(this.clientId, null); + } + if (Config.isEnvExpression(this.secret)) { + this.secret = Config.getProperty(this.secret, null); + } + if (Config.isEnvExpression(this.scope)) { + this.scope = Config.getProperty(this.scope, null); + } + if (Config.isEnvExpression(this.title)) { + this.title = Config.getProperty(this.title, null); + } + if (Config.isEnvExpression(this.realmName)) { + this.realmName = Config.getProperty(this.realmName, null); + } + if (Config.isEnvExpression(this.openIdConfigUrl)) { + this.openIdConfigUrl = Config.getProperty(this.openIdConfigUrl, null); + } + } + + @JsonIgnore + public String getUrlOrInternal() { + return this.internalUrl != null && this.internalUrl.length() > 0 ? this.internalUrl : this.url; + } + + @JsonIgnore + public boolean hasToBeConfigured(){ + return this.openIdConfigUrl!=null && this.openIdConfigUrl.length()>0; + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java new file mode 100644 index 000000000..0e25b5b0f --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java @@ -0,0 +1,88 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class OAuthResponseData { + + private String access_token; + private double expires_in; + private double refresh_expires_in; + private String refresh_token; + private String token_type; + private String id_token; + + public OAuthResponseData() { + } + + public OAuthResponseData(String token) { + this.access_token = token; + } + + public String getAccess_token() { + return access_token; + } + + public String getToken_type() { + return token_type; + } + + public void setToken_type(String token_type) { + this.token_type = token_type; + } + + public String getRefresh_token() { + return refresh_token; + } + + public void setRefresh_token(String refresh_token) { + this.refresh_token = refresh_token; + } + + public double getRefresh_expires_in() { + return refresh_expires_in; + } + + public void setRefresh_expires_in(double refresh_expires_in) { + this.refresh_expires_in = refresh_expires_in; + } + + public double getExpires_in() { + return expires_in; + } + + public void setExpires_in(double expires_in) { + this.expires_in = expires_in; + } + + public void setAccess_token(String access_token) { + this.access_token = access_token; + } + + public void setId_token(String id_token){ this.id_token = id_token;} + public String getId_token(){ return this.id_token;} + @Override + public String toString() { + return "OAuthResponseData [access_token=" + access_token + ", expires_in=" + expires_in + + ", refresh_expires_in=" + refresh_expires_in + ", refresh_token=" + refresh_token + ", token_type=" + + token_type + "]"; + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java new file mode 100644 index 000000000..0371f377d --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.apache.shiro.authc.BearerToken; + +public class OAuthToken { + private final String access_token; + private final String token_type; + private final long expires_at; + private final long issued_at; + + public OAuthToken(BearerToken btoken) { + this.access_token = btoken.getToken(); + this.token_type = "Bearer"; + DecodedJWT token = JWT.decode(this.access_token); + this.expires_at = token.getExpiresAt().getTime() / 1000L; + this.issued_at = token.getIssuedAt().getTime() / 1000L; + } + + public String getAccess_token() { + return access_token; + } + + public String getToken_type() { + return token_type; + } + + public long getExpires_at() { + return expires_at; + } + public long getIssued_at() { + return issued_at; + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java new file mode 100644 index 000000000..19eb4b68e --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java @@ -0,0 +1,130 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class OdlPolicy { + + private String path; + private PolicyMethods methods; + + + public OdlPolicy() { + + } + + public OdlPolicy(String path, PolicyMethods methods) { + this.path = path; + this.methods = methods; + } + + public PolicyMethods getMethods() { + return methods; + } + + public void setMethods(PolicyMethods methods) { + this.methods = methods; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public static OdlPolicy allowAll(String path) { + return new OdlPolicy(path, PolicyMethods.allowAll()); + } + + public static OdlPolicy denyAll(String path) { + return new OdlPolicy(path, PolicyMethods.denyAll()); + } + + public static class PolicyMethods { + private boolean get; + private boolean post; + private boolean put; + private boolean delete; + private boolean patch; + + public PolicyMethods() { + this(false, false, false, false, false); + } + + public PolicyMethods(boolean get, boolean post, boolean put, boolean del, boolean patch) { + this.get = get; + this.post = post; + this.put = put; + this.delete = del; + this.patch = patch; + } + + public boolean isGet() { + return get; + } + + public void setGet(boolean get) { + this.get = get; + } + + public boolean isPost() { + return post; + } + + public void setPost(boolean post) { + this.post = post; + } + + public boolean isPut() { + return put; + } + + public void setPut(boolean put) { + this.put = put; + } + + public boolean isDelete() { + return delete; + } + + public void setDelete(boolean delete) { + this.delete = delete; + } + + public boolean isPatch() { + return patch; + } + + public void setPatch(boolean patch) { + this.patch = patch; + } + + public static PolicyMethods allowAll() { + return new PolicyMethods(true, true, true, true, true); + } + + public static PolicyMethods denyAll() { + return new PolicyMethods(false, false, false, false, false); + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlShiroConfiguration.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlShiroConfiguration.java new file mode 100644 index 000000000..f5e067450 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlShiroConfiguration.java @@ -0,0 +1,67 @@ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import java.util.List; + +public class OdlShiroConfiguration { + + private List main; + private List urls; + + + + public List getMain() { + return main; + } + + public void setMain(List main) { + this.main = main; + } + public List getUrls() { + return urls; + } + public void setUrls(List urls) { + this.urls = urls; + } + public OdlShiroConfiguration(){ + + } + + public static class BaseItem{ + private String pairKey; + private String pairValue; + + public String getPairKey() { + return pairKey; + } + + public void setPairKey(String pairKey) { + this.pairKey = pairKey; + } + + public String getPairValue() { + return pairValue; + } + + public void setPairValue(String pairValue) { + this.pairValue = pairValue; + } + + public BaseItem(){ + + } + + } + + public static class MainItem extends BaseItem{ + public MainItem(){ + super(); + } + + } + public static class UrlItem extends BaseItem{ + public UrlItem(){ + super(); + } + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlXmlMapper.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlXmlMapper.java new file mode 100644 index 000000000..cbdc1d0d9 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlXmlMapper.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; + +public class OdlXmlMapper extends XmlMapper { + + private static final long serialVersionUID = 1L; + + + public OdlXmlMapper() { + this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.setSerializationInclusion(Include.NON_NULL); + this.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); + this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); + YangToolsBuilderAnnotationIntrospector introspector = new YangToolsBuilderAnnotationIntrospector(); + this.setAnnotationIntrospector(introspector); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java new file mode 100644 index 000000000..d94631fe3 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java @@ -0,0 +1,65 @@ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class OpenIdConfigResponseData { + + private String issuer; + private String authorization_endpoint; + private String token_endpoint; + private String userinfo_endpoint; + + private String end_session_endpoint; + private String jwks_uri; + + public OpenIdConfigResponseData(){ + + } + + public String getIssuer() { + return issuer; + } + + public void setIssuer(String issuer) { + this.issuer = issuer; + } + + public String getAuthorization_endpoint() { + return authorization_endpoint; + } + + public void setAuthorization_endpoint(String authorization_endpoint) { + this.authorization_endpoint = authorization_endpoint; + } + + public String getToken_endpoint() { + return token_endpoint; + } + + public void setToken_endpoint(String token_endpoint) { + this.token_endpoint = token_endpoint; + } + + public String getUserinfo_endpoint() { + return userinfo_endpoint; + } + + public void setUserinfo_endpoint(String userinfo_endpoint) { + this.userinfo_endpoint = userinfo_endpoint; + } + + public String getJwks_uri() { + return jwks_uri; + } + + public void setJwks_uri(String jwks_uri) { + this.jwks_uri = jwks_uri; + } + + public String getEnd_session_endpoint() { + return end_session_endpoint; + } + + public void setEnd_session_endpoint(String end_session_endpoint) { + this.end_session_endpoint = end_session_endpoint; + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java new file mode 100644 index 000000000..b791a4040 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java @@ -0,0 +1,12 @@ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +public class UnableToConfigureOAuthService extends Exception { + + public UnableToConfigureOAuthService(String configUrl){ + super(String.format("Unable to configure OAuth service from url %s", configUrl)); + } + public UnableToConfigureOAuthService(String configUrl, int responseCode){ + super(String.format("Unable to configure OAuth service from url %s. bad response with code %d", configUrl, responseCode)); + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java new file mode 100644 index 000000000..f7731f0b8 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java @@ -0,0 +1,103 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; + +import java.util.List; + +public class UserTokenPayload { + + public static final String PROVIDERID_INTERNAL="Internal"; + + private List roles; + private String preferredUsername; + private String givenName; + private String familyName; + private long exp; + private long iat; + + private String providerId; + + public long getExp() { + return exp; + } + + public long getIat() { + return this.iat; + } + + public void setPreferredUsername(String preferredUsername) { + this.preferredUsername = preferredUsername; + } + + public void setGivenName(String givenName) { + this.givenName = givenName; + } + + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + + public void setExp(long exp) { + this.exp = exp; + } + + public void setIat(long iat) { + this.iat = iat; + } + + public String getPreferredUsername() { + return preferredUsername; + } + + public String getGivenName() { + return givenName; + } + + public String getFamilyName() { + return familyName; + } + + public List getRoles() { + return this.roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public void setProviderId(String providerId){ this.providerId = providerId;} + + public String getProviderId(){ return this.providerId;} + + public static UserTokenPayload createInternal(String username, List roles) { + UserTokenPayload data = new UserTokenPayload(); + data.setPreferredUsername(username); + data.setRoles(roles); + data.setProviderId(PROVIDERID_INTERNAL); + return data; + } + + + public boolean isInternal() { + return PROVIDERID_INTERNAL.equals(this.providerId); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java new file mode 100644 index 000000000..0dc58efff --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters; + +import java.util.Arrays; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Requires the requesting user to be {@link org.apache.shiro.subject.Subject#isAuthenticated() authenticated} for the + * request to continue, and if they're not, requires the user to login via the HTTP Bearer protocol-specific challenge. + * Upon successful login, they're allowed to continue on to the requested resource/url. + *

+ * The {@link #onAccessDenied(ServletRequest, ServletResponse)} method will only be called if the subject making the + * request is not {@link org.apache.shiro.subject.Subject#isAuthenticated() authenticated} + * + * @see RFC 2617 + * @see OAuth2 Authorization Request Header Field + * @since 1.5 + */ + +public class AnyRoleHttpAuthenticationFilter extends RolesAuthorizationFilter { + + /** + * This class's private logger. + */ + private static final Logger LOG = LoggerFactory.getLogger(AnyRoleHttpAuthenticationFilter.class); + + @Override + public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { + final Subject subject = getSubject(request, response); + final String[] rolesArray = (String[]) mappedValue; + LOG.debug("isAccessAllowed {}", Arrays.asList(rolesArray)); + + if (rolesArray == null || rolesArray.length == 0) { + //no roles specified, so nothing to check - allow access. + LOG.debug("no role specified: access allowed"); + return true; + } + + for (String roleName : rolesArray) { + LOG.debug("checking role {}", roleName); + if (subject.hasRole(roleName)) { + LOG.debug("role matched to {}: access allowed", roleName); + return true; + } + } + LOG.debug("no role matched: access denied"); + return false; + } +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java new file mode 100644 index 000000000..51c064819 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java @@ -0,0 +1,161 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters; + +import java.util.Locale; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.codec.Base64; +import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; +import org.apache.shiro.web.filter.authc.BearerHttpAuthenticationFilter; +import org.apache.shiro.web.util.WebUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BearerAndBasicHttpAuthenticationFilter extends BearerHttpAuthenticationFilter { + + // defined in lower-case for more efficient string comparison + private static final Logger LOG = LoggerFactory.getLogger(BearerAndBasicHttpAuthenticationFilter.class); + private ODLHttpAuthenticationHelperFilter basicAuthFilter; + + public BearerAndBasicHttpAuthenticationFilter() { + this.basicAuthFilter = new ODLHttpAuthenticationHelperFilter(); + } + + protected static final String OPTIONS_HEADER = "OPTIONS"; + + @Override + protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { + final String authHeader = this.getAuthzHeader(request); + if (authHeader != null && authHeader.startsWith("Basic")) { + return this.createBasicAuthToken(request, response); + } + return super.createToken(request, response); + } + + @Override + protected String[] getPrincipalsAndCredentials(String scheme, String token) { + LOG.debug("getPrincipalsAndCredentials with scheme {} and token {}", scheme, token); + if (scheme.toLowerCase().equals("basic")) { + return this.basicAuthFilter.getPrincipalsAndCredentials(scheme, token); + } + return super.getPrincipalsAndCredentials(scheme, token); + } + + @Override + protected boolean isLoginAttempt(String authzHeader) { + LOG.debug("isLoginAttempt with header {}", authzHeader); + if (this.basicAuthFilter.isLoginAttempt(authzHeader)) { + return true; + } + return super.isLoginAttempt(authzHeader); + } + + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { + final HttpServletRequest httpRequest = WebUtils.toHttp(request); + final String httpMethod = httpRequest.getMethod(); + //always allow options requests + if (OPTIONS_HEADER.equalsIgnoreCase(httpMethod)) { + return true; + } + + if (this.basicAuthFilter.isAccessAllowed(httpRequest, response, mappedValue)) { + LOG.debug("isAccessAllowed succeeded on basicAuth"); + return true; + } + + return super.isAccessAllowed(request, response, mappedValue); + } + + protected AuthenticationToken createBasicAuthToken(ServletRequest request, ServletResponse response) { + String authorizationHeader = getAuthzHeader(request); + if (authorizationHeader == null || authorizationHeader.length() == 0) { + // Create an empty authentication token since there is no + // Authorization header. + return createToken("", "", request, response); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Attempting to execute login with headers [" + authorizationHeader + "]"); + } + + String[] prinCred = getPrincipalsAndCredentials(authorizationHeader, request); + if (prinCred == null || prinCred.length < 2) { + // Create an authentication token with an empty password, + // since one hasn't been provided in the request. + String username = prinCred == null || prinCred.length == 0 ? "" : prinCred[0]; + return createToken(username, "", request, response); + } + + String username = prinCred[0]; + String password = prinCred[1]; + + return createToken(username, password, request, response); + } + + private static class ODLHttpAuthenticationHelperFilter extends BasicHttpAuthenticationFilter { + + private static final Logger LOG = LoggerFactory.getLogger(ODLHttpAuthenticationHelperFilter.class); + + // defined in lower-case for more efficient string comparison + protected static final String BEARER_SCHEME = "bearer"; + + protected static final String OPTIONS_HEADER = "OPTIONS"; + + public ODLHttpAuthenticationHelperFilter() { + LOG.info("Creating the ODLHttpAuthenticationFilter"); + } + + @Override + protected String[] getPrincipalsAndCredentials(String scheme, String encoded) { + final String decoded = Base64.decodeToString(encoded); + // attempt to decode username/password; otherwise decode as token + if (decoded.contains(":")) { + return decoded.split(":"); + } + return new String[]{encoded}; + } + + @Override + protected boolean isLoginAttempt(String authzHeader) { + final String authzScheme = getAuthzScheme().toLowerCase(Locale.ROOT); + final String authzHeaderLowerCase = authzHeader.toLowerCase(Locale.ROOT); + return authzHeaderLowerCase.startsWith(authzScheme) + || authzHeaderLowerCase.startsWith(BEARER_SCHEME); + } + + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, + Object mappedValue) { + final HttpServletRequest httpRequest = WebUtils.toHttp(request); + final String httpMethod = httpRequest.getMethod(); + if (OPTIONS_HEADER.equalsIgnoreCase(httpMethod)) { + return true; + } else { + return super.isAccessAllowed(httpRequest, response, mappedValue); + } + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java new file mode 100644 index 000000000..27ca3b3f9 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java @@ -0,0 +1,188 @@ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import javax.servlet.Filter; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.authz.AuthorizationFilter; +import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.DataTreeModification; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.HttpAuthorization; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.policies.Policies; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("checkstyle:AbbreviationAsWordInName") +public class CustomizedMDSALDynamicAuthorizationFilter extends AuthorizationFilter + implements ClusteredDataTreeChangeListener { + + private static final Logger LOG = LoggerFactory.getLogger(CustomizedMDSALDynamicAuthorizationFilter.class); + + private static final DataTreeIdentifier AUTHZ_CONTAINER = DataTreeIdentifier.create( + LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(HttpAuthorization.class)); + + private static DataBroker dataBroker; + + public static void setDataBroker(DataBroker dataBroker2){ + dataBroker = dataBroker2; + } + private ListenerRegistration reg; + private volatile ListenableFuture> authContainer; + + public CustomizedMDSALDynamicAuthorizationFilter() { + + } + + @Override + public Filter processPathConfig(final String path, final String config) { + /*if (dataBroker == null){ + throw new RuntimeException("dataBroker is not initialized"); + }*/ + + return super.processPathConfig(path, config); + } + + @Override + public void destroy() { + if (reg != null) { + reg.close(); + reg = null; + } + super.destroy(); + } + + @Override + public void onDataTreeChanged(final Collection> changes) { + final HttpAuthorization newVal = Iterables.getLast(changes).getRootNode().getDataAfter(); + LOG.debug("Updating authorization information to {}", newVal); + authContainer = Futures.immediateFuture(Optional.ofNullable(newVal)); + } + + @Override + public boolean isAccessAllowed(final ServletRequest request, final ServletResponse response, + final Object mappedValue) { + if (dataBroker == null){ + throw new RuntimeException("dataBroker is not initialized"); + } + if(reg == null){ + try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) { + authContainer = tx.read(AUTHZ_CONTAINER.getDatastoreType(), AUTHZ_CONTAINER.getRootIdentifier()); + } + reg = dataBroker.registerDataTreeChangeListener(AUTHZ_CONTAINER, this); + } + checkArgument(request instanceof HttpServletRequest, "Expected HttpServletRequest, received {}", request); + + + final boolean defaultReturnValue=false; + final Subject subject = getSubject(request, response); + final HttpServletRequest httpServletRequest = (HttpServletRequest)request; + final String requestURI = httpServletRequest.getRequestURI(); + LOG.debug("isAccessAllowed for user={} to requestURI={}", subject, requestURI); + + final Optional authorizationOptional; + try { + authorizationOptional = authContainer.get(); + } catch (ExecutionException | InterruptedException e) { + // Something went completely wrong trying to read the authz container. Deny access. + LOG.warn("MDSAL attempt to read Http Authz Container failed, disallowing access", e); + return false; + } + + if (!authorizationOptional.isPresent()) { + // The authorization container does not exist-- hence no authz rules are present + // Allow access. + LOG.debug("Authorization Container does not exist"); + return defaultReturnValue; + } + + final HttpAuthorization httpAuthorization = authorizationOptional.get(); + final var policies = httpAuthorization.getPolicies(); + List policiesList = policies != null ? policies.getPolicies() : null; + if (policiesList == null || policiesList.isEmpty()) { + // The authorization container exists, but no rules are present. Allow access. + LOG.debug("Exiting early since no authorization rules exist"); + sendError(response, 403, ""); + return defaultReturnValue; + } + + // Sort the Policies list based on index + policiesList = new ArrayList<>(policiesList); + policiesList.sort(Comparator.comparing(Policies::getIndex)); + + for (Policies policy : policiesList) { + final String resource = policy.getResource(); + final boolean pathsMatch = pathsMatch(resource, requestURI); + if (pathsMatch) { + LOG.debug("paths match for policy {} pattern={} and requestURI={}", policy.getIndex(), resource, requestURI); + final String method = httpServletRequest.getMethod(); + LOG.trace("method={}", method); + List permissions = policy.getPermissions(); + LOG.trace("perm={}", permissions); + if(permissions !=null) { + for (Permissions permission : permissions) { + final String role = permission.getRole(); + LOG.trace("role={}", role); + Set actions = permission.getActions(); + if (actions != null) { + for (Permissions.Actions action : actions) { + LOG.trace("action={}", action.getName()); + if (action.getName().equalsIgnoreCase(method)) { + final boolean hasRole = subject.hasRole(role); + LOG.trace("hasRole({})={}", role, hasRole); + if (hasRole) { + return true; + } + } + } + } + else{ + LOG.trace("no actions found"); + } + } + } + else { + LOG.trace("no permissions found"); + } + LOG.debug("couldn't authorize the user for access"); + sendError(response, 403, ""); + return false; + } + } + LOG.debug("no path found that matches {}", requestURI); + sendError(response, 403, ""); + return defaultReturnValue; + } + + private void sendError(ServletResponse response, int code, String message) { + if(response instanceof HttpServletResponse){ + try { + ((HttpServletResponse)response).sendError(code, message); + } catch (IOException e) { + LOG.warn("unable to send {} {} response: ", code, message, e); + } + } + else{ + LOG.warn("unable to send {} {} response", code, message); + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java new file mode 100644 index 000000000..562fe5472 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java @@ -0,0 +1,527 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.ShiroException; +import org.apache.shiro.authc.BearerToken; +import org.apache.shiro.codec.Base64; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.*; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlShiroConfiguration.MainItem; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlShiroConfiguration.UrlItem; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters.CustomizedMDSALDynamicAuthorizationFilter; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService.PublicOAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.MdSalAuthorizationStore; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.OAuthProviderFactory; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; +import org.opendaylight.aaa.api.AuthenticationException; +import org.opendaylight.aaa.api.Claim; +import org.opendaylight.aaa.api.PasswordCredentialAuth; +import org.opendaylight.aaa.api.PasswordCredentials; +import org.opendaylight.aaa.tokenauthrealm.auth.PasswordCredentialBuilder; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AuthHttpServlet extends HttpServlet { + + private static final Logger LOG = LoggerFactory.getLogger(AuthHttpServlet.class.getName()); + private static final long serialVersionUID = 1L; + private static final String BASEURI = "/oauth"; + private static final String LOGINURI = BASEURI + "/login"; + private static final String LOGOUTURI = BASEURI + "/logout"; + private static final String PROVIDERSURI = BASEURI + "/providers"; + public static final String REDIRECTURI = BASEURI + "/redirect"; + private static final String REDIRECTURI_FORMAT = REDIRECTURI + "/%s"; + private static final String POLICIESURI = BASEURI + "/policies"; + private static final String REDIRECTID_REGEX = "^\\" + BASEURI + "\\/redirect\\/([^\\/]+)$"; + private static final String LOGIN_REDIRECT_REGEX = "^\\" + LOGINURI + "\\/([^\\/]+)$"; + private static final Pattern REDIRECTID_PATTERN = Pattern.compile(REDIRECTID_REGEX); + private static final Pattern LOGIN_REDIRECT_PATTERN = Pattern.compile(LOGIN_REDIRECT_REGEX); + + private static final String DEFAULT_DOMAIN = "sdn"; + private static final String HEAEDER_AUTHORIZATION = "Authorization"; + + private static final String LOGOUT_REDIRECT_URL_PARAMETER = "redirect_uri"; + private static final String CLASSNAME_ODLBASICAUTH = + "org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter"; + private static final String CLASSNAME_ODLBEARERANDBASICAUTH = + "org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter2"; + private static final String CLASSNAME_ODLMDSALAUTH = + "org.opendaylight.aaa.shiro.realm.MDSALDynamicAuthorizationFilter"; + public static final String LOGIN_REDIRECT_FORMAT = LOGINURI + "/%s"; + private static final String URI_PRE = BASEURI; + + private static final String CONFIGFILE ="/opt/opendaylight/etc/opendaylight/datastore/initial/config/aaa-app-config.xml"; + private final ObjectMapper mapper; + /* state <=> AuthProviderService> */ + private final Map providerStore; + private final TokenCreator tokenCreator; + private final Config config; + private static MdSalAuthorizationStore mdsalAuthStore; + private PasswordCredentialAuth passwordCredentialAuth; + private OdlShiroConfiguration shiroConfiguration; + + public AuthHttpServlet() throws IllegalArgumentException, IOException, InvalidConfigurationException, + UnableToConfigureOAuthService { + this(CONFIGFILE); + } + public AuthHttpServlet(String shiroconfigfile) throws IllegalArgumentException, IOException, InvalidConfigurationException, + UnableToConfigureOAuthService { + this.config = Config.getInstance(); + this.shiroConfiguration = loadShiroConfig(shiroconfigfile); + this.tokenCreator = TokenCreator.getInstance(this.config); + this.mapper = new ObjectMapper(); + this.providerStore = new HashMap<>(); + for (OAuthProviderConfig pc : config.getProviders()) { + this.providerStore.put(pc.getId(), OAuthProviderFactory.create(pc.getType(), pc, + this.config.getRedirectUri(), TokenCreator.getInstance(this.config))); + } + } + + public void setDataBroker(DataBroker dataBroker) { + CustomizedMDSALDynamicAuthorizationFilter.setDataBroker(dataBroker); + mdsalAuthStore = new MdSalAuthorizationStore(dataBroker); + } + + public void setPasswordCredentialAuth(PasswordCredentialAuth passwordCredentialAuth) { + this.passwordCredentialAuth = passwordCredentialAuth; + } + + + public void onUnbindService(HttpService httpService) { + httpService.unregister(AuthHttpServlet.URI_PRE); + + } + + public void onBindService(HttpService httpService) + throws ServletException, NamespaceException { + if (httpService == null) { + LOG.warn("Unable to inject HttpService into loader."); + } else { + httpService.registerServlet(AuthHttpServlet.URI_PRE, this, null, null); + LOG.info("oauth servlet registered."); + } + } + private static OdlShiroConfiguration loadShiroConfig(String filename) throws IOException { + OdlXmlMapper mapper = new OdlXmlMapper(); + return mapper.readValue(new File(filename), OdlShiroConfiguration.class); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + LOG.debug("GET request for {}", req.getRequestURI()); + getHost(req); + if (PROVIDERSURI.equals(req.getRequestURI())) { + this.sendResponse(resp, HttpServletResponse.SC_OK, getConfigs(this.providerStore.values())); + } else if (req.getRequestURI().startsWith(LOGINURI)) { + this.handleLoginRedirect(req, resp); + } else if (req.getRequestURI().equals(LOGOUTURI)) { + this.handleLogout(req, resp); + } else if (POLICIESURI.equals(req.getRequestURI())) { + this.sendResponse(resp, HttpServletResponse.SC_OK, this.getPoliciesForUser(req)); + } else if (req.getRequestURI().startsWith(REDIRECTURI)) { + this.handleRedirect(req, resp); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + } + + } + + private void handleLogout(HttpServletRequest req, HttpServletResponse resp) throws IOException { + final String bearerToken = this.tokenCreator.getBearerToken(req, true); + String redirectUrl = req.getParameter(LOGOUT_REDIRECT_URL_PARAMETER); + if (redirectUrl == null) { + redirectUrl = this.config.getPublicUrl(); + } + UserTokenPayload userInfo = this.tokenCreator.decode(bearerToken); + if (bearerToken != null && userInfo != null && !userInfo.isInternal()) { + AuthService provider = this.providerStore.getOrDefault(userInfo.getProviderId(), null); + + if (provider != null) { + provider.sendLogoutRedirectResponse(bearerToken, resp, redirectUrl); + this.logout(); + return; + } + } + this.logout(); + resp.sendRedirect(redirectUrl); + + } + + private void handleLoginRedirect(HttpServletRequest req, HttpServletResponse resp) throws IOException { + final String uri = req.getRequestURI(); + final Matcher matcher = LOGIN_REDIRECT_PATTERN.matcher(uri); + if (matcher.find()) { + final String id = matcher.group(1); + AuthService provider = this.providerStore.getOrDefault(id, null); + if (provider != null) { + String redirectUrl = getHost(req) + String.format(REDIRECTURI_FORMAT, id); + provider.sendLoginRedirectResponse(resp, redirectUrl); + return; + } + } + this.sendResponse(resp, HttpServletResponse.SC_NOT_FOUND, ""); + } + + /** + * find out what urls can be accessed by user and which are forbidden + *

+ * urlEntries: "anon" -> any access allowed "authcXXX" -> no grouping rule -> any access for user allowed "authcXXX, + * roles[abc] -> user needs to have role abc "authcXXX, roles["abc,def"] -> user needs to have roles abc AND def + * "authcXXX, anyroles[abc] -> user needs to have role abc "authcXXX, anyroles["abc,def"] -> user needs to have + * roles abc OR def + * + * @param req + * @return + */ + private List getPoliciesForUser(HttpServletRequest req) { + List policies = new ArrayList<>(); + List urlRules = this.shiroConfiguration.getUrls(); + UserTokenPayload data = this.getUserInfo(req); + if (urlRules != null) { + LOG.debug("try to find rules for user {} with roles {}", + data == null ? "null" : data.getPreferredUsername(), data == null ? "null" : data.getRoles()); + final String regex = "^([^,]+)[,]?[\\ ]?([anyroles]+)?(\\[\"?([a-zA-Z,]+)\"?\\])?"; + final Pattern pattern = Pattern.compile(regex); + Matcher matcher; + for (UrlItem urlRule : urlRules) { + matcher = pattern.matcher(urlRule.getPairValue()); + if (matcher.find()) { + try { + final String authClass = getAuthClass(matcher.group(1)); + Optional policy = Optional.empty(); + //anon access allowed + if (authClass == null) { + policy = Optional.of(OdlPolicy.allowAll(urlRule.getPairKey())); + } else if (authClass.equals(CLASSNAME_ODLBASICAUTH) || "authcBasic".equals(urlRule.getPairKey())) { + policy = isBasic(req) ? this.getTokenBasedPolicy(urlRule, matcher, data) + : Optional.of(OdlPolicy.denyAll(urlRule.getPairKey())); + } else if (authClass.equals(CLASSNAME_ODLBEARERANDBASICAUTH)) { + policy = this.getTokenBasedPolicy(urlRule, matcher, data); + } else if (authClass.equals(CLASSNAME_ODLMDSALAUTH)) { + policy = this.getMdSalBasedPolicy(urlRule, data); + } + if (policy.isPresent()) { + policies.add(policy.get()); + } else { + LOG.warn("unable to get policy for authClass {} for entry {}", authClass, + urlRule.getPairValue()); + policies.add(OdlPolicy.denyAll(urlRule.getPairKey())); + } + } catch (NoDefinitionFoundException e) { + LOG.warn("unknown authClass: ", e); + } + + } else { + LOG.warn("unable to detect url role value: {}", urlRule.getPairValue()); + } + } + } else { + LOG.debug("no url rules found"); + } + return policies; + } + + /** + * extract policy rule for user from MD-SAL not yet supported + * + * @param urlRule + * @param data + * @return + */ + private Optional getMdSalBasedPolicy(UrlItem urlRule, UserTokenPayload data) { + if (mdsalAuthStore != null) { + return data != null ? mdsalAuthStore.getPolicy(urlRule.getPairKey(), data.getRoles()) + : Optional.of(OdlPolicy.denyAll(urlRule.getPairKey())); + } + return Optional.empty(); + } + + /** + * extract policy rule for user from url rules of config + * + * @param urlRule + * @param matcher + * @param data + * @return + */ + private Optional getTokenBasedPolicy(UrlItem urlRule, Matcher matcher, + UserTokenPayload data) { + final String url = urlRule.getPairKey(); + final String rule = urlRule.getPairValue(); + if (!rule.contains(",")) { + LOG.debug("found rule without roles for '{}'", matcher.group(1)); + //not important if anon or authcXXX + if (data != null || "anon".equals(matcher.group(1))) { + return Optional.of(OdlPolicy.allowAll(url)); + } + } + if (data != null) { + LOG.debug("found rule with roles '{}'", matcher.group(4)); + if ("roles".equals(matcher.group(2))) { + if (this.rolesMatch(data.getRoles(), Arrays.asList(matcher.group(4).split(",")), false)) { + return Optional.of(OdlPolicy.allowAll(url)); + } else { + return Optional.of(OdlPolicy.denyAll(url)); + } + } else if ("anyroles".equals(matcher.group(2))) { + if (this.rolesMatch(data.getRoles(), Arrays.asList(matcher.group(4).split(",")), true)) { + return Optional.of(OdlPolicy.allowAll(url)); + } else { + return Optional.of(OdlPolicy.denyAll(url)); + } + } else { + LOG.warn("unable to detect url role value: {}", urlRule.getPairValue()); + } + } else { + return Optional.of(OdlPolicy.denyAll(url)); + } + return Optional.empty(); + } + + private String getAuthClass(String key) throws NoDefinitionFoundException { + if ("anon".equals(key)) { + return null; + } + if("authcBasic".equals(key)){ + return CLASSNAME_ODLBASICAUTH; + } + List list = shiroConfiguration.getMain(); + Optional main = + list == null ? Optional.empty() : list.stream().filter(e -> e.getPairKey().equals(key)).findFirst(); + if (main.isPresent()) { + return main.get().getPairValue(); + } + throw new NoDefinitionFoundException("unable to find def for " + key); + } + + private UserTokenPayload getUserInfo(HttpServletRequest req) { + if (isBearer(req)) { + UserTokenPayload data = this.tokenCreator.decode(req); + if (data != null) { + return data; + } + } else if (isBasic(req)) { + String username = getBasicAuthUsername(req); + if (username != null) { + final String domain = getBasicAuthDomain(username); + if (!username.contains("@")) { + username = String.format("%s@%s", username, domain); + } + List roles = List.of();// odlIdentityService.listRoles(username, domain); + return UserTokenPayload.createInternal(username, roles); + } + } + return null; + } + + private static String getBasicAuthDomain(String username) { + if (username.contains("@")) { + return username.split("@")[1]; + } + return DEFAULT_DOMAIN; + } + + private static String getBasicAuthUsername(HttpServletRequest req) { + final String header = req.getHeader(HEAEDER_AUTHORIZATION); + final String decoded = Base64.decodeToString(header.substring(6)); + // attempt to decode username/password; otherwise decode as token + if (decoded.contains(":")) { + return decoded.split(":")[0]; + } + LOG.warn("unable to detect username from basicauth header {}", header); + return null; + } + + private static boolean isBasic(HttpServletRequest req) { + final String header = req.getHeader(HEAEDER_AUTHORIZATION); + return header != null && header.startsWith("Basic"); + } + + private static boolean isBearer(HttpServletRequest req) { + final String header = req.getHeader(HEAEDER_AUTHORIZATION); + return header != null && header.startsWith("Bearer"); + } + + private boolean rolesMatch(List userRoles, List policyRoles, boolean any) { + if (any) { + for (String policyRole : policyRoles) { + if (userRoles.contains(policyRole)) { + return true; + } + } + return false; + } else { + for (String policyRole : policyRoles) { + if (!userRoles.contains(policyRole)) { + return false; + } + } + return true; + } + + } + + public String getHost(HttpServletRequest req) { + String hostUrl = this.config.getPublicUrl(); + if (hostUrl == null) { + final String tmp = req.getRequestURL().toString(); + final String regex = "^(http[s]{0,1}:\\/\\/[^\\/]+)"; + final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); + final Matcher matcher = pattern.matcher(tmp); + if (matcher.find()) { + hostUrl = matcher.group(1); + } + } + LOG.info("host={}", hostUrl); + return hostUrl; + + } + + private List getConfigs(Collection values) { + List configs = new ArrayList<>(); + for (AuthService svc : values) { + configs.add(svc.getConfig()); + } + return configs; + } + + /** + * GET /oauth/redirect/{providerID} + * + * @param req + * @param resp + * @throws IOException + */ + private void handleRedirect(HttpServletRequest req, HttpServletResponse resp) throws IOException { + final String uri = req.getRequestURI(); + final Matcher matcher = REDIRECTID_PATTERN.matcher(uri); + if (matcher.find()) { + AuthService provider = this.providerStore.getOrDefault(matcher.group(1), null); + if (provider != null) { + //provider.setLocalHostUrl(getHost(req)); + provider.handleRedirect(req, resp, getHost(req)); + return; + } + } + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + LOG.debug("POST request for {}", req.getRequestURI()); + if (this.config.loginActive() && this.config.doSupportOdlUsers() && LOGINURI.equals(req.getRequestURI())) { + final String username = req.getParameter("username"); + final String domain = req.getParameter("domain"); + BearerToken token = + this.doLogin(username, req.getParameter("password"), domain != null ? domain : DEFAULT_DOMAIN); + if (token != null) { + sendResponse(resp, HttpServletResponse.SC_OK, new OAuthToken(token)); + LOG.debug("login for odluser {} succeeded", username); + return; + } else { + LOG.debug("login failed"); + } + + } + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + + private BearerToken doLogin(String username, String password, String domain) { + + PasswordCredentials pc = + (new PasswordCredentialBuilder()).setUserName(username).setPassword(password).setDomain(domain).build(); + Claim claim = null; + try { + claim = this.passwordCredentialAuth.authenticate(pc); + } catch (AuthenticationException e) { + LOG.warn("unable to authentication user {} for domain {}: ", username, domain, e); + } + if (claim != null) { + List roles = claim.roles().stream().toList();//odlIdentityService.listRoles(username, domain); + UserTokenPayload data = new UserTokenPayload(); + data.setPreferredUsername(username); + data.setFamilyName(""); + data.setGivenName(username); + data.setIat(this.tokenCreator.getDefaultIat()); + data.setExp(this.tokenCreator.getDefaultExp()); + data.setRoles(roles); + return this.tokenCreator.createNewJWT(data); + } else { + LOG.info("unable to read auth from authservice"); + } + return null; + } + + +/* private void sendResponse(HttpServletResponse resp, int code) throws IOException { + this.sendResponse(resp, code, null); + }*/ + + private void sendResponse(HttpServletResponse resp, int code, Object data) throws IOException { + byte[] output = data != null ? mapper.writeValueAsString(data).getBytes() : new byte[0]; + // output + resp.setStatus(code); + resp.setContentLength(output.length); + resp.setContentType("application/json"); + ServletOutputStream os = resp.getOutputStream(); + os.write(output); + + } + + private void logout() { + /* final Subject subject = SecurityUtils.getSubject(); + try { + subject.logout(); + Session session = subject.getSession(false); + if (session != null) { + session.stop(); + } + } catch (ShiroException e) { + LOG.debug("Couldn't log out {}", subject, e); + }*/ + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java new file mode 100644 index 000000000..31b6d696f --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java @@ -0,0 +1,469 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +public class HeadersOnlyHttpServletRequest implements HttpServletRequest{ + + private final Map headers; + + public HeadersOnlyHttpServletRequest(Map headers) { + this.headers = headers; + } + @Override + public Object getAttribute(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setCharacterEncoding(String env) throws UnsupportedEncodingException { + // TODO Auto-generated method stub + + } + + @Override + public int getContentLength() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getContentLengthLong() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getContentType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getParameter(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getParameterNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getParameterValues(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map getParameterMap() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getProtocol() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getScheme() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServerName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getServerPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public BufferedReader getReader() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteAddr() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteHost() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setAttribute(String name, Object o) { + // TODO Auto-generated method stub + + } + + @Override + public void removeAttribute(String name) { + // TODO Auto-generated method stub + + } + + @Override + public Locale getLocale() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getLocales() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isSecure() { + // TODO Auto-generated method stub + return false; + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRealPath(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRemotePort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getLocalName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getLocalAddr() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getLocalPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public ServletContext getServletContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) + throws IllegalStateException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isAsyncStarted() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isAsyncSupported() { + // TODO Auto-generated method stub + return false; + } + + @Override + public AsyncContext getAsyncContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DispatcherType getDispatcherType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAuthType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Cookie[] getCookies() { + // TODO Auto-generated method stub + return null; + } + + @Override + public long getDateHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getHeader(String name) { + return this.headers.getOrDefault(name,null); + } + + @Override + public Enumeration getHeaders(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getHeaderNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getIntHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getMethod() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPathInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPathTranslated() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContextPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getQueryString() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteUser() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isUserInRole(String role) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Principal getUserPrincipal() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestedSessionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestURI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public StringBuffer getRequestURL() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServletPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public HttpSession getSession(boolean create) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HttpSession getSession() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String changeSessionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isRequestedSessionIdValid() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromURL() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + // TODO Auto-generated method stub + return false; + } + + @Override + public void login(String username, String password) throws ServletException { + // TODO Auto-generated method stub + + } + + @Override + public void logout() throws ServletException { + // TODO Auto-generated method stub + + } + + @Override + public Collection getParts() throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Part getPart(String name) throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java new file mode 100644 index 000000000..6b1a8eddd --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPResponse; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.CustomObjectMapper; + +public class MappedBaseHttpResponse { + + + public static final int CODE404 = 404; + public static final int CODE200 = 200; + public static final MappedBaseHttpResponse UNKNOWN = new MappedBaseHttpResponse<>(-1, null); + private static final ObjectMapper mapper = new CustomObjectMapper(); + public final int code; + public final T body; + + public MappedBaseHttpResponse(int code, String body, Class clazz) + throws JsonMappingException, JsonProcessingException { + this(code, body != null ? mapper.readValue(body, clazz) : null); + } + + private MappedBaseHttpResponse(int code, T body) { + this.code = code; + this.body = body; + } + + public MappedBaseHttpResponse(BaseHTTPResponse response, Class clazz) + throws JsonMappingException, JsonProcessingException { + this(response.code, response.body, clazz); + } + + @Override + public String toString() { + return "BaseHTTPResponse [code=" + code + ", body=" + body + "]"; + } + + public boolean isSuccess() { + return this.code == CODE200; + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java new file mode 100644 index 000000000..ca455dc72 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client; + +import java.io.IOException; +import java.util.Map; +import java.util.Optional; +import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MappingBaseHttpClient extends BaseHTTPClient { + + private static Logger LOG = LoggerFactory.getLogger(MappingBaseHttpClient.class); + + public MappingBaseHttpClient(String base, boolean trustAllCerts) { + super(base, trustAllCerts); + } + + public MappingBaseHttpClient(String host) { + super(host); + } + + public Optional> sendMappedRequest(String uri, String method, String body, + Map headers) { + return this.sendMappedRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers, String.class); + } + + public Optional> sendMappedRequest(String uri, String method, String body, + Map headers, Class clazz) { + return this.sendMappedRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers, clazz); + } + + protected Optional> sendMappedRequest(String uri, String method, byte[] body, + Map headers, Class clazz) { + try { + return Optional.of(new MappedBaseHttpResponse(this.sendRequest(uri, method, body, headers), clazz)); + } catch (IOException e) { + LOG.warn("problem during request for {}: ", uri, e); + } + return Optional.empty(); + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java new file mode 100644 index 000000000..2dc0b5746 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java @@ -0,0 +1,356 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.*; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappingBaseHttpClient; +import org.apache.shiro.authc.BearerToken; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AuthService { + + + private static final Logger LOG = LoggerFactory.getLogger(AuthService.class); + private final MappingBaseHttpClient httpClient; + protected final ObjectMapper mapper; + protected final OAuthProviderConfig config; + protected final TokenCreator tokenCreator; + private final String redirectUri; + private final String tokenEndpointRelative; + private final String authEndpointAbsolute; + private final String logoutEndpointAbsolute; + + private final Map logoutTokenMap; + protected abstract String getTokenVerifierUri(); + + protected abstract Map getAdditionalTokenVerifierParams(); + + protected abstract ResponseType getResponseType(); + + protected abstract boolean doSeperateRolesRequest(); + + protected abstract UserTokenPayload mapAccessToken(String spayload) + throws JsonMappingException, JsonProcessingException; + + protected abstract String getLoginUrl(String callbackUrl); + protected abstract String getLogoutUrl(); + + protected abstract UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at); + + protected abstract boolean verifyState(String state); + + public AuthService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + this.config = config; + this.tokenCreator = tokenCreator; + this.redirectUri = redirectUri; + this.mapper = new ObjectMapper(); + this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.httpClient = new MappingBaseHttpClient(this.config.getUrlOrInternal(), this.config.trustAll()); + this.logoutTokenMap = new HashMap<>(); + if (this.config.hasToBeConfigured()){ + Optional> oresponse = this.httpClient.sendMappedRequest( + this.config.getOpenIdConfigUrl(), "GET", null, null, OpenIdConfigResponseData.class); + if(oresponse.isEmpty()){ + throw new UnableToConfigureOAuthService(this.config.getOpenIdConfigUrl()); + } + MappedBaseHttpResponse response = oresponse.get(); + if(!response.isSuccess()){ + throw new UnableToConfigureOAuthService(this.config.getOpenIdConfigUrl(), response.code); + } + this.tokenEndpointRelative = trimUrl(this.config.getUrlOrInternal(),response.body.getToken_endpoint()); + this.authEndpointAbsolute = extendUrl(this.config.getUrlOrInternal(),response.body.getAuthorization_endpoint()); + this.logoutEndpointAbsolute = extendUrl(this.config.getUrlOrInternal(),response.body.getEnd_session_endpoint()); + } + else{ + this.tokenEndpointRelative = null; + this.authEndpointAbsolute = null; + this.logoutEndpointAbsolute = null; + } + } + + public static String trimUrl(String baseUrl, String endpoint) { + if(endpoint.startsWith(baseUrl)){ + return endpoint.substring(baseUrl.length()); + } + if(endpoint.startsWith("http")){ + return endpoint.substring(endpoint.indexOf("/",8)); + } + return endpoint; + } + public static String extendUrl(String baseUrl, String endpoint) { + if(endpoint.startsWith("http")){ + endpoint= endpoint.substring(endpoint.indexOf("/",8)); + } + if(baseUrl.endsWith("/")){ + baseUrl=baseUrl.substring(0,baseUrl.length()-2); + } + return baseUrl+endpoint; + } + + public PublicOAuthProviderConfig getConfig() { + return new PublicOAuthProviderConfig(this); + } + + protected MappingBaseHttpClient getHttpClient() { + return this.httpClient; + } + + public void handleRedirect(HttpServletRequest req, HttpServletResponse resp, String host) throws IOException { + switch (this.getResponseType()) { + case CODE: + this.handleRedirectCode(req, resp, host); + break; + case TOKEN: + sendErrorResponse(resp, "not yet implemented"); + break; + case SESSION_STATE: + break; + } + } + + public void sendLoginRedirectResponse(HttpServletResponse resp, String callbackUrl) { + resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + String url = this.authEndpointAbsolute !=null?String.format( + "%s?client_id=%s&response_type=code&scope=%s&redirect_uri=%s", + this.authEndpointAbsolute, urlEncode(this.config.getClientId()), this.config.getScope(), + urlEncode(callbackUrl)):this.getLoginUrl(callbackUrl); + resp.setHeader("Location", url); + } + public void sendLogoutRedirectResponse(String token, HttpServletResponse resp, String redirectUrl) + throws IOException { + String idToken = this.logoutTokenMap.getOrDefault(token, null); + String logoutEndpoint = this.logoutEndpointAbsolute!=null?this.logoutEndpointAbsolute:this.getLogoutUrl(); + if(idToken==null) { + LOG.debug("unable to find token in map. Do unsafe logout."); + resp.sendRedirect(this.logoutEndpointAbsolute); + return; + } + LOG.debug("id token found. redirect to specific logout"); + resp.sendRedirect(String.format("%s?id_token_hint=%s&post_logout_redirect_uri=%s",logoutEndpoint, idToken, + urlEncode(redirectUrl))); + } + + + + private static void sendErrorResponse(HttpServletResponse resp, String message) throws IOException { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, message); + } + + private void handleRedirectCode(HttpServletRequest req, HttpServletResponse resp, String host) throws IOException { + final String code = req.getParameter("code"); + final String state = req.getParameter("state"); + OAuthResponseData response = null; + if(this.verifyState(state)) { + response = this.getTokenForUser(code, host); + } + if (response != null) { + if (this.doSeperateRolesRequest()) { + LOG.debug("do a seperate role request"); + long expiresAt = this.tokenCreator.getDefaultExp(); + long issuedAt = this.tokenCreator.getDefaultIat(); + UserTokenPayload data = this.requestUserRoles(response.getAccess_token(), issuedAt, expiresAt); + if (data != null) { + BearerToken createdToken = this.handleUserInfoToken(data, resp, host); + this.logoutTokenMap.put(createdToken.getToken(),response.getId_token()); + } else { + sendErrorResponse(resp, "unable to verify user"); + } + } else { + BearerToken createdToken = this.handleUserInfoToken(response.getAccess_token(), resp, host); + this.logoutTokenMap.put(createdToken.getToken(),response.getId_token()); + } + } else { + sendErrorResponse(resp, "unable to verify code"); + } + } + + private BearerToken handleUserInfoToken(UserTokenPayload data, HttpServletResponse resp, String localHostUrl) + throws IOException { + BearerToken onapToken = this.tokenCreator.createNewJWT(data); + sendTokenResponse(resp, onapToken, localHostUrl); + return onapToken; + } + + private BearerToken handleUserInfoToken(String accessToken, HttpServletResponse resp, String localHostUrl) + throws IOException { + try { + DecodedJWT jwt = JWT.decode(accessToken); + String spayload = base64Decode(jwt.getPayload()); + LOG.debug("payload in jwt='{}'", spayload); + UserTokenPayload data = this.mapAccessToken(spayload); + return this.handleUserInfoToken(data, resp, localHostUrl); + } catch (JWTDecodeException | JsonProcessingException e) { + LOG.warn("unable to decode jwt token {}: ", accessToken, e); + sendErrorResponse(resp, e.getMessage()); + } + return null; + } + + + protected List mapRoles(List roles) { + final Map map = this.config.getRoleMapping(); + return roles.stream().map(r -> map.getOrDefault(r, r)).collect(Collectors.toList()); + } + + private void sendTokenResponse(HttpServletResponse resp, BearerToken data, String localHostUrl) throws IOException { + if (this.redirectUri == null) { + byte[] output = data != null ? mapper.writeValueAsString(data).getBytes() : new byte[0]; + resp.setStatus(200); + resp.setContentLength(output.length); + resp.setContentType("application/json"); + resp.addCookie(this.tokenCreator.createAuthCookie(data)); + ServletOutputStream os = null; + os = resp.getOutputStream(); + os.write(output); + } else { + resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + resp.setHeader("Location", assembleUrl(localHostUrl, this.redirectUri, data.getToken())); + resp.addCookie(this.tokenCreator.createAuthCookie(data)); + } + } + + + + private static String base64Decode(String data) { + return new String(Base64.getDecoder().decode(data), StandardCharsets.UTF_8); + } + + private OAuthResponseData getTokenForUser(String code, String localHostUrl) { + + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/x-www-form-urlencoded"); + headers.put("Accept", "application/json"); + Map params = this.getAdditionalTokenVerifierParams(); + params.put("code", code); + params.put("client_id", this.config.getClientId()); + params.put("client_secret", this.config.getSecret()); + params.put("redirect_uri", assembleRedirectUrl(localHostUrl, AuthHttpServlet.REDIRECTURI, this.config.getId())); + StringBuilder body = new StringBuilder(); + for (Entry p : params.entrySet()) { + body.append(String.format("%s=%s&", p.getKey(), urlEncode(p.getValue()))); + } + + String url = this.tokenEndpointRelative !=null?this.tokenEndpointRelative :this.getTokenVerifierUri(); + Optional> response = + this.httpClient.sendMappedRequest(url, "POST", + body.substring(0, body.length() - 1), headers, OAuthResponseData.class); + if (response.isPresent() && response.get().isSuccess()) { + return response.get().body; + } + LOG.warn("problem get token for code {}", code); + + return null; + } + + /** + * Assemble callback url for service provider {host}{baseUri}/{serviceId} e.g. + * http://10.20.0.11:8181/oauth/redirect/keycloak + * + * @param host + * @param baseUri + * @param serviceId + * @return + */ + public static String assembleRedirectUrl(String host, String baseUri, String serviceId) { + return String.format("%s%s/%s", host, baseUri, serviceId); + } + + private static String assembleUrl(String host, String uri, String token) { + return String.format("%s%s%s", host, uri, token); + } + + public static String urlEncode(String s) { + return URLEncoder.encode(s, StandardCharsets.UTF_8); + } + + + + public enum ResponseType { + CODE, TOKEN, SESSION_STATE + } + + + public static class PublicOAuthProviderConfig { + + private String id; + private String title; + private String loginUrl; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getLoginUrl() { + return loginUrl; + } + + public void setLoginUrl(String loginUrl) { + this.loginUrl = loginUrl; + } + + public PublicOAuthProviderConfig(AuthService authService) { + this.id = authService.config.getId(); + this.title = authService.config.getTitle(); + this.loginUrl = String.format(AuthHttpServlet.LOGIN_REDIRECT_FORMAT, authService.config.getId()); + } + + } + + + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java new file mode 100644 index 000000000..d271948c2 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java @@ -0,0 +1,180 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GitlabProviderService extends AuthService { + + private static final Logger LOG = LoggerFactory.getLogger(GitlabProviderService.class); + private Map additionalTokenVerifierParams; + protected final List randomIds; + private static final String API_USER_URI = "/api/v4/user"; + private static final String API_GROUP_URI = "/api/v4/groups?min_access_level=10"; + + public GitlabProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + super(config, redirectUri, tokenCreator); + this.additionalTokenVerifierParams = new HashMap<>(); + this.additionalTokenVerifierParams.put("grant_type", "authorization_code"); + this.randomIds = new ArrayList<>(); + } + + @Override + protected String getTokenVerifierUri() { + return "/oauth/token"; + } + + @Override + protected String getLoginUrl(String callbackUrl) { + return String.format("%s/oauth/authorize?client_id=%s&response_type=code&state=%s&redirect_uri=%s", + this.config.getUrl(), urlEncode(this.config.getClientId()), this.createRandomId(), callbackUrl); + } + + @Override + protected String getLogoutUrl() { + return String.format("%s/oauth/logout", this.config.getUrl()); + } + + private String createRandomId() { + String rnd = null; + while(true) { + rnd=Config.generateSecret(20); + if(!this.randomIds.contains(rnd)) { + break; + } + } + this.randomIds.add(rnd); + return rnd; + } + + @Override + protected ResponseType getResponseType() { + return ResponseType.CODE; + } + + @Override + protected Map getAdditionalTokenVerifierParams() { + return this.additionalTokenVerifierParams; + + } + + @Override + protected boolean doSeperateRolesRequest() { + return true; + } + + @Override + protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException { + return null; + } + + @Override + protected UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at) { + LOG.info("reqesting user roles with token={}", access_token); + Map authHeaders = new HashMap<>(); + authHeaders.put("Authorization", String.format("Bearer %s", access_token)); + Optional> userInfo = + this.getHttpClient().sendMappedRequest(API_USER_URI, "GET", null, authHeaders, GitlabUserInfo.class); + if (userInfo.isEmpty()) { + LOG.warn("unable to read user data"); + return null; + } + Optional> groupInfos = this.getHttpClient() + .sendMappedRequest(API_GROUP_URI, "GET", null, authHeaders, GitlabGroupInfo[].class); + if (groupInfos.isEmpty()) { + LOG.warn("unable to read group information for user"); + return null; + } + UserTokenPayload data = new UserTokenPayload(); + GitlabUserInfo uInfo = userInfo.get().body; + data.setPreferredUsername(uInfo.getUsername()); + data.setGivenName(uInfo.getName()); + data.setFamilyName(uInfo.getName()); + data.setIat(issued_at); + data.setExp(expires_at); + List roles = new ArrayList<>(); + GitlabGroupInfo[] uRoles = groupInfos.get().body; + for (GitlabGroupInfo uRole : uRoles) { + roles.add(uRole.getName()); + } + data.setRoles(this.mapRoles(roles)); + return data; + } + + + + @SuppressWarnings("unused") + private static class GitlabUserInfo { + + private String username; + private String name; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + @SuppressWarnings("unused") + private static class GitlabGroupInfo { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + @Override + protected boolean verifyState(String state) { + if(this.randomIds.contains(state)) { + this.randomIds.remove(state); + return true; + } + return false; + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java new file mode 100644 index 000000000..bdbf9286a --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java @@ -0,0 +1,115 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.KeycloakUserTokenPayload; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; + +public class KeycloakProviderService extends AuthService { + + public static final String ID = "keycloak"; + private Map additionalTokenVerifierParams; + + public KeycloakProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + super(config, redirectUri, tokenCreator); + this.additionalTokenVerifierParams = new HashMap<>(); + this.additionalTokenVerifierParams.put("grant_type", "authorization_code"); + } + + @Override + protected String getTokenVerifierUri() { + return String.format("/auth/realms/%s/protocol/openid-connect/token", urlEncode(this.config.getRealmName())); + } + + @Override + protected String getLoginUrl(String callbackUrl) { + return String.format( + "%s/auth/realms/%s/protocol/openid-connect/auth?client_id=%s&response_type=code&scope=%s&redirect_uri=%s", + this.config.getUrl(), urlEncode(this.config.getRealmName()), urlEncode(this.config.getClientId()), + this.config.getScope(), urlEncode(callbackUrl)); + } + + @Override + protected String getLogoutUrl() { + return String.format("%s/auth/realms/%s/protocol/openid-connect/logout", this.config.getUrl(), + urlEncode(this.config.getRealmName())); + } + + @Override + protected List mapRoles(List data) { + final Map map = this.config.getRoleMapping(); + List filteredRoles = + data.stream().filter(role -> !role.equals("uma_authorization") && !role.equals("offline_access")) + .map(r -> map.getOrDefault(r, r)).collect(Collectors.toList()); + return filteredRoles; + } + + @Override + protected ResponseType getResponseType() { + return ResponseType.CODE; + } + + @Override + protected Map getAdditionalTokenVerifierParams() { + return this.additionalTokenVerifierParams; + + } + + @Override + protected boolean doSeperateRolesRequest() { + return false; + } + + @Override + protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException { + KeycloakUserTokenPayload payload = mapper.readValue(spayload, KeycloakUserTokenPayload.class); + UserTokenPayload data = new UserTokenPayload(); + data.setIat(payload.getIat() * 1000L); + data.setExp(payload.getExp() * 1000L); + data.setFamilyName(payload.getFamilyName()); + data.setGivenName(payload.getGivenName()); + data.setProviderId(this.config.getId()); + data.setPreferredUsername(payload.getPreferredUsername()); + data.setRoles(this.mapRoles(payload.getRealmAccess().getRoles())); + return data; + } + + @Override + protected UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at) { + return null; + } + + @Override + protected boolean verifyState(String state) { + return true; + } + + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java new file mode 100644 index 000000000..4bf35e72d --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java @@ -0,0 +1,118 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy.PolicyMethods; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.HttpAuthorization; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.Policies; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions.Actions; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MdSalAuthorizationStore { + + private static final Logger LOG = LoggerFactory.getLogger(MdSalAuthorizationStore.class.getName()); + + private final DataBroker dataBroker; + + public MdSalAuthorizationStore(DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + public Optional getPolicy(String path, List userRoles) { + InstanceIdentifier iif = InstanceIdentifier.create(HttpAuthorization.class).child(Policies.class); + Optional odata = Optional.empty(); + // The implicite close is not handled correctly by underlaying opendaylight netconf service + ReadTransaction transaction = this.dataBroker.newReadOnlyTransaction(); + try { + odata = transaction.read(LogicalDatastoreType.CONFIGURATION, iif).get(); + } catch (ExecutionException e) { + LOG.warn("unable to read policies from mdsal: ", e); + } catch (InterruptedException e) { + LOG.warn("Interrupted!", e); + // Restore interrupted state... + Thread.currentThread().interrupt(); + } + if (odata.isEmpty()) { + return Optional.empty(); + } + List data = + odata.get().getPolicies(); + if (data == null) { + return Optional.empty(); + } + Optional entry = + data.stream().filter(e -> path.equals(e.getResource())).findFirst(); + if (entry.isEmpty()) { + return Optional.empty(); + } + List permissions = entry.get().getPermissions(); + if (permissions == null) { + return Optional.empty(); + } + Optional rolePm = permissions.stream().filter((e) -> userRoles.contains(e.getRole())).findFirst(); + if (rolePm.isEmpty()) { + return Optional.empty(); + } + return Optional.of(mapPolicy(path, rolePm.get().getActions())); + } + + private OdlPolicy mapPolicy(String path, Set actions) { + PolicyMethods methods = new PolicyMethods(); + String action; + for (Actions a : actions) { + action = a.getName().toLowerCase(); + switch (action) { + case "get": + methods.setGet(true); + break; + case "post": + methods.setPost(true); + break; + case "put": + methods.setPut(true); + break; + case "delete": + methods.setDelete(true); + break; + case "patch": + methods.setPatch(true); + break; + default: + LOG.warn("unknown http method {}", action); + break; + } + } + return new OdlPolicy(path, methods); + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java new file mode 100644 index 000000000..73bae5d4c --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java @@ -0,0 +1,91 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import java.util.Map; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; + +public class NextcloudProviderService extends AuthService { + + public NextcloudProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + super(config, redirectUri, tokenCreator); + // TODO Auto-generated constructor stub + } + + @Override + protected String getTokenVerifierUri() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Map getAdditionalTokenVerifierParams() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected ResponseType getResponseType() { + // TODO Auto-generated method stub + return ResponseType.TOKEN; + } + + @Override + protected boolean doSeperateRolesRequest() { + // TODO Auto-generated method stub + return false; + } + + @Override + protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException { + // TODO Auto-generated method stub + return null; + } + + @Override + protected String getLoginUrl(String callbackUrl) { + // TODO Auto-generated method stub + return null; + } + + @Override + protected String getLogoutUrl() { + return null; + } + + @Override + protected UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at) { + // TODO Auto-generated method stub + return null; + } + + @Override + protected boolean verifyState(String state) { + // TODO Auto-generated method stub + return false; + } + +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java new file mode 100644 index 000000000..152569930 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; + +public class OAuthProviderFactory { + + + public static AuthService create(OAuthProvider key, OAuthProviderConfig config, String redirectUri, + TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + switch (key) { + case KEYCLOAK: + return new KeycloakProviderService(config, redirectUri, tokenCreator); + case NEXTCLOUD: + return new NextcloudProviderService(config, redirectUri, tokenCreator); + case GITLAB: + return new GitlabProviderService(config, redirectUri, tokenCreator); + } + return null; + } + + public static enum OAuthProvider { + KEYCLOAK, NEXTCLOUD, GITLAB + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java new file mode 100644 index 000000000..fac46f6b1 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java @@ -0,0 +1,106 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; + +public class PemUtils { + + private static byte[] parsePEMFile(File pemFile) throws IOException { + if (!pemFile.isFile() || !pemFile.exists()) { + throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath())); + } + return parsePEMFile(new FileReader(pemFile)); + } + private static byte[] parsePEMFile(Reader inputReader) throws IOException { + PemReader reader = new PemReader(inputReader); + PemObject pemObject = reader.readPemObject(); + byte[] content = pemObject.getContent(); + reader.close(); + return content; + } + private static PublicKey getPublicKey(byte[] keyBytes, String algorithm) { + PublicKey publicKey = null; + try { + KeyFactory kf = KeyFactory.getInstance(algorithm); + EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + publicKey = kf.generatePublic(keySpec); + } catch (NoSuchAlgorithmException e) { + System.out.println("Could not reconstruct the public key, the given algorithm could not be found."); + } catch (InvalidKeySpecException e) { + System.out.println("Could not reconstruct the public key"); + } + + return publicKey; + } + + private static PrivateKey getPrivateKey(byte[] keyBytes, String algorithm) { + PrivateKey privateKey = null; + try { + KeyFactory kf = KeyFactory.getInstance(algorithm); + EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + privateKey = kf.generatePrivate(keySpec); + } catch (NoSuchAlgorithmException e) { + System.out.println("Could not reconstruct the private key, the given algorithm could not be found."); + } catch (InvalidKeySpecException e) { + System.out.println("Could not reconstruct the private key"); + } + + return privateKey; + } + + public static PublicKey readPublicKeyFromFile(String filepath, String algorithm) throws IOException { + byte[] bytes = PemUtils.parsePEMFile(new File(filepath)); + return PemUtils.getPublicKey(bytes, algorithm); + } + + public static PublicKey readPublicKey(String filecontent, String algorithm) throws IOException { + byte[] bytes = PemUtils.parsePEMFile(new StringReader(filecontent)); + return PemUtils.getPublicKey(bytes, algorithm); + } + + public static PrivateKey readPrivateKeyFromFile(String filepath, String algorithm) throws IOException { + byte[] bytes = PemUtils.parsePEMFile(new File(filepath)); + return PemUtils.getPrivateKey(bytes, algorithm); + } + + public static PrivateKey readPrivateKey(String filecontent, String algorithm) throws IOException { + byte[] bytes = PemUtils.parsePEMFile(new StringReader(filecontent)); + return PemUtils.getPrivateKey(bytes, algorithm); + } + +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java new file mode 100644 index 000000000..028dff9dd --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import java.io.IOException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; + +public class RSAKeyReader { + + private static final String PREFIX_FILEURL = "file://"; + + public static RSAPrivateKey getPrivateKey(String filenameOrContent) throws IOException { + if (filenameOrContent.startsWith(PREFIX_FILEURL)) { + return (RSAPrivateKey) PemUtils.readPrivateKeyFromFile(filenameOrContent.substring(PREFIX_FILEURL.length()), + "RSA"); + } + return (RSAPrivateKey) PemUtils.readPrivateKey(filenameOrContent, "RSA"); + } + + public static RSAPublicKey getPublicKey(String filenameOrContent) throws IOException { + if (filenameOrContent.startsWith(PREFIX_FILEURL)) { + return (RSAPublicKey) PemUtils.readPublicKeyFromFile(filenameOrContent.substring(PREFIX_FILEURL.length()), + "RSA"); + } + return (RSAPublicKey) PemUtils.readPublicKey(filenameOrContent, "RSA"); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java new file mode 100644 index 000000000..d8720e823 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java @@ -0,0 +1,202 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.JWTVerifier; +import java.io.IOException; +import java.security.Security; +import java.util.Arrays; +import java.util.Date; +import java.util.Optional; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; +import org.apache.shiro.authc.BearerToken; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TokenCreator { + + private static final Logger LOG = LoggerFactory.getLogger(AuthHttpServlet.class.getName()); + private final String issuer; + private static TokenCreator _instance; + private final long tokenLifetimeSeconds; + private final Algorithm algorithm; + + private static final String ROLES_CLAIM = "roles"; + private static final String FAMILYNAME_CLAIM = "family_name"; + private static final String NAME_CLAIM = "name"; + private static final String PROVIDERID_CLAIM = "provider_id"; + private static final String COOKIE_NAME_AUTH = "token"; + + static { + Security.addProvider( + new BouncyCastleProvider() + ); + } + public static TokenCreator getInstance(Config config) throws IllegalArgumentException, IOException { + if (_instance == null) { + _instance = new TokenCreator(config); + } + return _instance; + } + + public static TokenCreator getInstance(String alg, String secret, String issuer, long tokenLifetime) + throws IllegalArgumentException, IOException { + return getInstance(alg, secret, null, issuer, tokenLifetime); + } + + public static TokenCreator getInstance(String alg, String secret, String pubkey, String issuer, long tokenLifetime) + throws IllegalArgumentException, IOException { + if (_instance == null) { + _instance = new TokenCreator(alg, secret, pubkey, issuer, tokenLifetime); + } + return _instance; + } + + private TokenCreator(Config config) throws IllegalArgumentException, IOException { + this(config.getAlgorithm(), config.getTokenSecret(), config.getPublicKey(), config.getTokenIssuer(), + config.getTokenLifetime()); + } + + private TokenCreator(String alg, String secret, String pubkey, String issuer, long tokenLifetime) + throws IllegalArgumentException, IOException { + this.issuer = issuer; + this.tokenLifetimeSeconds = tokenLifetime; + this.algorithm = this.createAlgorithm(alg, secret, pubkey); + } + + private Algorithm createAlgorithm(String alg, String secret, String pubkey) + throws IllegalArgumentException, IOException { + if (alg == null) { + alg = Config.TOKENALG_HS256; + } + switch (alg) { + case Config.TOKENALG_HS256: + return Algorithm.HMAC256(secret); + case Config.TOKENALG_RS256: + return Algorithm.RSA256(RSAKeyReader.getPublicKey(pubkey), RSAKeyReader.getPrivateKey(secret)); + case Config.TOKENALG_RS512: + return Algorithm.RSA512(RSAKeyReader.getPublicKey(pubkey), RSAKeyReader.getPrivateKey(secret)); + case Config.TOKENALG_CLIENT_RS256: + return Algorithm.RSA256(RSAKeyReader.getPublicKey(pubkey), null); + case Config.TOKENALG_CLIENT_RS512: + return Algorithm.RSA512(RSAKeyReader.getPublicKey(pubkey), null); + } + throw new IllegalArgumentException(String.format("unable to find algorithm for %s", alg)); + + } + + public BearerToken createNewJWT(UserTokenPayload data) { + final String token = JWT.create().withIssuer(issuer).withExpiresAt(new Date(data.getExp())) + .withIssuedAt(new Date(data.getIat())).withSubject(data.getPreferredUsername()) + .withClaim(NAME_CLAIM, data.getGivenName()).withClaim(FAMILYNAME_CLAIM, data.getFamilyName()) + .withClaim(PROVIDERID_CLAIM, data.getProviderId()) + .withArrayClaim(ROLES_CLAIM, data.getRoles().toArray(new String[data.getRoles().size()])) + .sign(this.algorithm); + LOG.trace("token created: {}", token); + return new BearerToken(token); + } + + public DecodedJWT verify(String token) { + DecodedJWT jwt = null; + LOG.debug("try to verify token {}", token); + try { + JWTVerifier verifier = JWT.require(this.algorithm).withIssuer(issuer).build(); + jwt = verifier.verify(token); + + } catch (JWTVerificationException e) { + LOG.warn("unable to verify token {}:", token, e); + } + return jwt; + } + + public long getDefaultExp() { + return new Date().getTime() + (this.tokenLifetimeSeconds * 1000); + } + + public long getDefaultExp(long expIn) { + return new Date().getTime() + expIn; + } + + public long getDefaultIat() { + return new Date().getTime(); + } + + public String getBearerToken(HttpServletRequest req) { + return this.getBearerToken(req, false); + } + + public String getBearerToken(HttpServletRequest req, boolean checkCookie) { + final String authHeader = req.getHeader("Authorization"); + if ((authHeader == null || !authHeader.startsWith("Bearer")) && checkCookie) { + Cookie[] cookies = req.getCookies(); + Optional ocookie = Optional.empty(); + if (cookies != null) { + ocookie = Arrays.stream(cookies).filter(c -> c != null && COOKIE_NAME_AUTH.equals(c.getName())) + .findFirst(); + } + if (ocookie.isEmpty()) { + return null; + } + return ocookie.get().getValue(); + } + return authHeader.substring(7); + } + + public UserTokenPayload decode(HttpServletRequest req) throws JWTDecodeException { + final String token = this.getBearerToken(req); + return token != null ? this.decode(token) : null; + } + + public UserTokenPayload decode(String token) { + if (token == null) { + return null; + } + DecodedJWT jwt = JWT.decode(token); + UserTokenPayload data = new UserTokenPayload(); + data.setRoles(Arrays.asList(jwt.getClaim(ROLES_CLAIM).asArray(String.class))); + data.setExp(jwt.getExpiresAt().getTime()); + data.setFamilyName(jwt.getClaim(FAMILYNAME_CLAIM).asString()); + data.setGivenName(jwt.getClaim(NAME_CLAIM).asString()); + data.setPreferredUsername(jwt.getClaim(NAME_CLAIM).asString()); + data.setProviderId(jwt.getClaim(PROVIDERID_CLAIM).asString()); + return data; + } + + public Cookie createAuthCookie(BearerToken data) { + Cookie cookie = new Cookie(COOKIE_NAME_AUTH, data.getToken()); + cookie.setMaxAge((int) this.tokenLifetimeSeconds); + cookie.setPath("/"); + cookie.setHttpOnly(true); + cookie.setSecure(true); + return cookie; + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java new file mode 100644 index 000000000..3e9205733 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java @@ -0,0 +1,404 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import java.util.Set; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import org.junit.Ignore; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.common.util.concurrent.FluentFuture; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jolokia.osgi.security.Authenticator; +import org.json.JSONArray; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.internal.matchers.Any; +import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient; +import org.onap.ccsdk.features.sdnr.wt.common.test.ServletOutputStreamToByteArrayOutputStream; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.CustomObjectMapper; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.HeadersOnlyHttpServletRequest; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper.OdlJsonMapper; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper.OdlXmlMapper; +import org.opendaylight.aaa.api.Claim; +import org.opendaylight.aaa.api.IdMService; +import org.apache.shiro.authc.BearerToken; +import org.opendaylight.aaa.api.PasswordCredentialAuth; +import org.opendaylight.aaa.api.PasswordCredentials; +import org.opendaylight.aaa.shiro.web.env.AAAShiroWebEnvironment; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration; +import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfigurationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.HttpAuthorization; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.Policies; +import org.opendaylight.yangtools.util.concurrent.FluentFutures; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + + +public class TestAuthHttpServlet { + + private static final String TESTCONFIGFILE = TestConfig.TEST_CONFIG_FILENAME; + private static final String TESTSHIROCONFIGFILE = "src/test/resources/aaa-app-config.test.xml"; + private static final String MDSALDYNAUTHFILENAME = "src/test/resources/mdsalDynAuthData.json"; + private static TestServlet servlet; + private static DataBroker dataBroker = loadDynamicMdsalAuthDataBroker(); + private static Authenticator odlAuthenticator = mock(Authenticator.class); + private static IdMService odlIdentityService = mock(IdMService.class); + private static PasswordCredentialAuth passwordCredentialAuth; + private static TokenCreator tokenCreator; +// private static final HttpServletRequest authreq = new HeadersOnlyHttpServletRequest( +// Map.of("Authorization", BaseHTTPClient.getAuthorizationHeaderValue("admin@sdn", "admin"))); + + @BeforeClass + public static void init() throws IllegalArgumentException, Exception { + + try { + Config config = createConfigFile(); + tokenCreator = TokenCreator.getInstance(config); + servlet = new TestServlet(); + } catch (IOException | InvalidConfigurationException e) { + fail(e.getMessage()); + } + servlet.setDataBroker(dataBroker); + passwordCredentialAuth = mock(PasswordCredentialAuth.class); + + servlet.setPasswordCredentialAuth(passwordCredentialAuth); + } + + private static DataBroker loadDynamicMdsalAuthDataBroker() { + DataBroker dataBroker = mock(DataBroker.class); + ReadTransaction rotx = mock(ReadTransaction.class); + InstanceIdentifier iif = InstanceIdentifier.create(HttpAuthorization.class).child(Policies.class); + try { + when(rotx.read(LogicalDatastoreType.CONFIGURATION, iif)) + .thenReturn(loadDataBrokerFile(MDSALDYNAUTHFILENAME, Policies.class)); + } catch (IOException e) { + fail("problem init databroker read" + e.getMessage()); + } + when(dataBroker.newReadOnlyTransaction()).thenReturn(rotx); + return dataBroker; + } + + private static FluentFuture> loadDataBrokerFile(String fn, Class clazz) throws IOException { + return FluentFutures.immediateFluentFuture(Optional.ofNullable(readJson(new File(fn), clazz))); + } + + private static ShiroConfiguration loadShiroConfig(String filename) + throws JsonParseException, JsonMappingException, IOException { + OdlXmlMapper mapper = new OdlXmlMapper(); + return mapper.readValue(new File(filename), ShiroConfigurationBuilder.class).build(); + } + + private static Config createConfigFile() throws IOException, InvalidConfigurationException { + return Config.getInstance(TESTCONFIGFILE); + + } + + @Test + public void testValidLoginRedirect() { + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/login/keycloak"); + HttpServletResponse resp = mock(HttpServletResponse.class); + try { + servlet.doGet(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(302); + verify(resp).setHeader("Location", + "http://10.20.11.160:8080/auth/realms/onap/protocol/openid-connect/auth?client_id=odlux.app&response" + + "_type=code&scope=openid&redirect_uri=http%3A%2F%2Fnasp.diasf.de%2Foauth%2Fredirect%2Fkeycloak"); + } + + @Test + public void testInValidLoginRedirect() { + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/login/unknownproviderid"); + HttpServletResponse resp = mock(HttpServletResponse.class); + ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); + try { + when(resp.getOutputStream()).thenReturn(printOut); + servlet.doGet(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(404); + } + + @Test + public void testValidLogin() { + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/login"); + when(req.getParameter("username")).thenReturn("admin"); + when(req.getParameter("password")).thenReturn("admin"); + Claim claim = new Claim() { + @Override + public String clientId() { + return "admin"; + } + + @Override + public String userId() { + return "admin"; + } + + @Override + public String user() { + return null; + } + + @Override + public String domain() { + return "sdn"; + } + + @Override + public Set roles() { + return Set.of("admin"); + } + }; + when(passwordCredentialAuth.authenticate(any(PasswordCredentials.class))).thenReturn(claim); + HttpServletResponse resp = mock(HttpServletResponse.class); + ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); + try { + when(resp.getOutputStream()).thenReturn(printOut); + servlet.doPost(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(200); + } + + @Test + public void testGetProviders() { + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/providers"); + HttpServletResponse resp = mock(HttpServletResponse.class); + ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); + try { + when(resp.getOutputStream()).thenReturn(printOut); + servlet.doGet(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(200); + String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); + System.out.println(responseBody); + JSONArray a = new JSONArray(responseBody); + assertEquals(1, a.length()); + assertEquals("keycloak", a.getJSONObject(0).getString("id")); + assertEquals("OSNL Keycloak Provider", a.getJSONObject(0).getString("title")); + assertEquals("/oauth/login/keycloak", a.getJSONObject(0).getString("loginUrl")); + + } + + @Test +/* + @Ignore +*/ + public void testPoliciesAnon() { + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/policies"); + HttpServletResponse resp = mock(HttpServletResponse.class); + ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); + try { + when(resp.getOutputStream()).thenReturn(printOut); + servlet.doGet(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(200); + String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); + System.out.println(responseBody); + OdlPolicy[] anonPolicies = null; + try { + anonPolicies = readJson(responseBody, OdlPolicy[].class); + } catch (JsonProcessingException e) { + fail("unable to read anon policies response"); + } + assertEquals(9, anonPolicies.length); + OdlPolicy pApidoc = find(anonPolicies, "/apidoc/**"); + assertNotNull(pApidoc); + assertAllEquals(false, pApidoc); + OdlPolicy pOauth = find(anonPolicies, "/oauth/**"); + assertNotNull(pOauth); + assertAllEquals(true, pOauth); + OdlPolicy pRestconf = find(anonPolicies, "/rests/**"); + assertNotNull(pRestconf); + assertAllEquals(false, pRestconf); + } + + @Test + public void testPoliciesBasicAuth() { + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/policies"); + when(req.getHeader("Authorization")).thenReturn(BaseHTTPClient.getAuthorizationHeaderValue("admin", "admin")); + when(odlIdentityService.listRoles("admin@sdn", "sdn")).thenReturn(Arrays.asList("admin")); + HttpServletResponse resp = mock(HttpServletResponse.class); + ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); + try { + when(resp.getOutputStream()).thenReturn(printOut); + servlet.doGet(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(200); + String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); + System.out.println(responseBody); + OdlPolicy[] anonPolicies = null; + try { + anonPolicies = readJson(responseBody, OdlPolicy[].class); + } catch (JsonProcessingException e) { + fail("unable to read anon policies response"); + } + assertEquals(9, anonPolicies.length); + OdlPolicy pApidoc = find(anonPolicies, "/apidoc/**"); + assertNotNull(pApidoc); + assertAllEquals(false, pApidoc); + OdlPolicy pOauth = find(anonPolicies, "/oauth/**"); + assertNotNull(pOauth); + assertAllEquals(true, pOauth); + OdlPolicy pRestconf = find(anonPolicies, "/rests/**"); + assertNotNull(pRestconf); + assertAllEquals(false, pRestconf); + } + + @Test + public void testPoliciesBearer() { + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/oauth/policies"); + String token = createToken("admin", Arrays.asList("admin", "provision")).getToken(); + when(req.getHeader("Authorization")).thenReturn(String.format("Bearer %s", token)); + HttpServletResponse resp = mock(HttpServletResponse.class); + ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); + try { + when(resp.getOutputStream()).thenReturn(printOut); + servlet.doGet(req, resp); + } catch (ServletException | IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(200); + String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); + System.out.println(responseBody); + OdlPolicy[] anonPolicies = null; + try { + anonPolicies = readJson(responseBody, OdlPolicy[].class); + } catch (JsonProcessingException e) { + fail("unable to read anon policies response"); + } + assertEquals(9, anonPolicies.length); + OdlPolicy pApidoc = find(anonPolicies, "/apidoc/**"); + assertNotNull(pApidoc); + assertAllEquals(false, pApidoc); + OdlPolicy pOauth = find(anonPolicies, "/oauth/**"); + assertNotNull(pOauth); + assertAllEquals(true, pOauth); + OdlPolicy pRestconf = find(anonPolicies, "/rests/**"); + assertNotNull(pRestconf); + assertAllEquals(true, pRestconf); + } + + private static BearerToken createToken(String username, List roles) { + UserTokenPayload data = new UserTokenPayload(); + data.setPreferredUsername(username); + data.setFamilyName(""); + data.setGivenName(username); + data.setExp(tokenCreator.getDefaultExp()); + data.setRoles(roles); + return tokenCreator.createNewJWT(data); + } + + private static void assertAllEquals(boolean b, OdlPolicy p) { + assertEquals(b, p.getMethods().isGet()); + assertEquals(b, p.getMethods().isPost()); + assertEquals(b, p.getMethods().isPut()); + assertEquals(b, p.getMethods().isDelete()); + assertEquals(b, p.getMethods().isPatch()); + } + + private static OdlPolicy find(OdlPolicy[] policies, String path) { + for (OdlPolicy p : policies) { + if (path.equals(p.getPath())) { + return p; + } + } + return null; + } + + private static T readJson(String data, Class clazz) throws JsonMappingException, JsonProcessingException { + CustomObjectMapper mapper = new CustomObjectMapper(); + return mapper.readValue(data, clazz); + } + + private static T readJson(File file, Class clazz) throws IOException { + OdlJsonMapper mapper = new OdlJsonMapper(); + return mapper.readValue(file, clazz); + } + + private static class TestServlet extends AuthHttpServlet { + + private static final long serialVersionUID = 1L; + + public TestServlet() throws IllegalArgumentException, Exception { + super(TESTSHIROCONFIGFILE); + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + super.doGet(req, resp); + } + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + super.doPost(req, resp); + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java new file mode 100644 index 000000000..80ae8cf95 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import java.io.IOException; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; + +public class TestConfig { + + public static String TEST_CONFIG_FILENAME = "src/test/resources/test.config.json"; + public static String TEST_OOMCONFIG_FILENAME = "src/test/resources/oom.test.config.json"; + public static String TEST_RS256_FILENAME = "src/test/resources/test.configRS256.json"; + public static String TEST_RS256INVALID_FILENAME = "src/test/resources/test.configRS256-invalid.json"; + public static String TEST_RS512_FILENAME = "src/test/resources/test.configRS512.json"; + + + @Test + public void test() throws IOException, InvalidConfigurationException { + + Config config = Config.load(TEST_CONFIG_FILENAME); + System.out.println("config="+config); + assertEquals(60*60,config.getTokenLifetime()); + assertNotNull(config.getAlgorithm()); + assertNotNull(config.getTokenSecret()); + //assertNotNull(config.getPublicKey()); + assertEquals(Config.TOKENALG_HS256, config.getAlgorithm()); + } + @Test + public void testOom() throws IOException, InvalidConfigurationException { + + Config config = Config.load(TEST_OOMCONFIG_FILENAME); + System.out.println("config="+config); + assertEquals(30*60,config.getTokenLifetime()); + + } + @Test + public void testRS256() throws IOException, InvalidConfigurationException { + + Config config = Config.load(TEST_RS256_FILENAME); + System.out.println("config="+config); + assertEquals(60*60,config.getTokenLifetime()); + + } + @Test + public void testRS512() throws IOException, InvalidConfigurationException { + + Config config = Config.load(TEST_RS512_FILENAME); + System.out.println("config="+config); + assertEquals(60*60,config.getTokenLifetime()); + + } + @Test(expected = InvalidConfigurationException.class) + public void testRS256Invalid() throws IOException, InvalidConfigurationException { + + Config.load(TEST_RS256INVALID_FILENAME); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java new file mode 100644 index 000000000..421b61919 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java @@ -0,0 +1,101 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPResponse; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.KeycloakUserTokenPayload; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthResponseData; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse; + +public class TestDeserializer { + + @Test + public void test1() throws IOException { + final String token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTME" + + "RNIn0.eyJleHAiOjE2MTAzNjE2OTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiOWRhOThmMTYtOTEyOS00N2NmLTgzOGQtNWQzYmVkYzYyZTJjIiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJjYzcxZmMxZi1hZGQ0LTRhODYtYWU1ZS1jMzRkZjQwM2M3NzIiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.PUT4NzCM1ej3sNMMCkQa1NuQQwDgn19G-OnWL4NgLvZ3ocJUZ1Yfr9KAPkrJHaiK_HXQqwTA-Ma6Qn7BBMoXNdFjwu0k_HpqyUbBDilGN4wpkGiUeS1p5SW4T_hnWJtwCJ5BYkEvF6WaEbi7MFCbEVO9LVcUvsa-7St1WZ8V8RVfbWgjAu7ejlxe6RYUDMYzIKDj5F5y1-qCyoKzGIjt5ajcA9FWrexHifLJECKO8ZG08Wp7xQld1sYPOdde6XHMwiyNelTwd_EzCBgUw_8664rETGDVtyfuYchowo5Z6fmn4U87L6EGjEuxiAE8f3USy_jh6UF0LnvyTyq_9I" + + "M1VA"; + final String response = + "{\"access_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTME" + + "RNIn0.eyJleHAiOjE2MTAzNjE2OTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiOWRhOThmMTYtOTEyOS00N2NmLTgzOGQtNWQzYmVkYzYyZTJjIiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6I" + + "mFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJjYzcxZmMxZi1hZGQ0LTRhODYtYWU1ZS1jMzRkZjQwM2M3NzIiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.PUT4NzCM1ej3sNMMCkQa1NuQQwDgn19G-OnWL4NgLvZ3ocJUZ1Yfr9KAPkrJHaiK_HX" + + "QqwTA-Ma6Qn7BBMoXNdFjwu0k_HpqyUbBDilGN4wpkGiUeS1p5SW4T_hnWJtwCJ5BYkEvF6WaEbi7MFCbEVO9LVcUvsa-7St1WZ8V8RVfbWgjAu7ejlxe6RYUDMYzIKDj5F5y1-qCyoKzGIjt5ajcA9FWrexHifLJECKO8ZG08Wp7xQld1sYPOdde6XHMwiyNelTwd_EzCBgUw_8664rETGDVtyfuYchowo5Z6fmn4U87L6EGjEuxiAE8f3USy_jh6UF0LnvyTyq_9I" + + "M1VA\",\"expires_in\":300,\"refresh_expires_in\":1800,\"refresh_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1NzdiN2Q3MC00NzMwLTQ0MDMtODk4My04ZjJmYTg4M2U2M2EifQ.eyJleHAiOjE2MTAzNjMxOTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiMmNjMGY4YWYtNWY2OC00YmFhLWEyOTctNjMxMjk2YzhmY2" + + "U5IiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6Imh0dHA6Ly8xMC4yMC4xMS4xNjA6ODA4MC9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiIxODM4YzRmMi01ZmUzLTRmMGMtYjJkMi1kMzY0YjI3YTQ5OTciLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYWRtaW4tY2xpIiwic2Vzc2lvbl9zdGF0ZSI6I" + + "mNjNzFmYzFmLWFkZDQtNGE4Ni1hZTVlLWMzNGRmNDAzYzc3MiIsInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.qutqcFuQW-GzaCVNMfiYrbmHYD34GYwBqIbaQbJSY-g\",\"token_type\":\"bearer\",\"not-before-policy\":0,\"session_state\":\"cc71fc1f-add4-4a86-ae5e-c34df403c772\",\"scope\":\"email profile\"} "; + + BaseHTTPResponse res = new BaseHTTPResponse(200, response); + OAuthResponseData data = new MappedBaseHttpResponse<>(res,OAuthResponseData.class).body; + assertEquals(token,data.getAccess_token()); + + } + + @Test + public void testUserPayloadDeser() throws JsonMappingException, JsonProcessingException { + final String payload = "{\n" + + " \"exp\": 1610362593,\n" + + " \"iat\": 1610361393,\n" + + " \"jti\": \"09bd6f2c-5dba-44a0-bd76-cd0d440137d0\",\n" + + " \"iss\": \"http://10.20.11.160:8080/auth/realms/onap\",\n" + + " \"aud\": \"account\",\n" + + " \"sub\": \"446a24bc-d8a0-43dd-afa5-e56eed75deb8\",\n" + + " \"typ\": \"Bearer\",\n" + + " \"azp\": \"admin-cli\",\n" + + " \"session_state\": \"db2c96f4-cc9b-47e8-a83f-a01c50d656f2\",\n" + + " \"acr\": \"1\",\n" + + " \"realm_access\": {\n" + + " \"roles\": [\n" + + " \"provision\",\n" + + " \"offline_access\",\n" + + " \"uma_authorization\"\n" + + " ]\n" + + " },\n" + + " \"resource_access\": {\n" + + " \"account\": {\n" + + " \"roles\": [\n" + + " \"manage-account\",\n" + + " \"manage-account-links\",\n" + + " \"view-profile\"\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"scope\": \"profile email\",\n" + + " \"email_verified\": false,\n" + + " \"name\": \"Luke Skywalker\",\n" + + " \"preferred_username\": \"luke.skywalker\",\n" + + " \"given_name\": \"Luke\",\n" + + " \"family_name\": \"Skywalker\",\n" + + " \"email\": \"luke.skywalker@sdnr.onap.org\"\n" + + "}"; + + ObjectMapper mapper = new ObjectMapper(); + KeycloakUserTokenPayload data = mapper.readValue(payload,KeycloakUserTokenPayload.class); + assertNotNull(data.getRealmAccess()); + assertEquals(3, data.getRealmAccess().getRoles().size()); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java new file mode 100644 index 000000000..6c2390ea0 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java @@ -0,0 +1,198 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.GitlabProviderService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; + +public class TestGitlabAuthService { + + private static HttpServer server; + private static ExecutorService httpThreadPool; + private static GitlabProviderServiceToTest oauthService; + private static final int PORT = randomPort(50000, 55000); + private static final String GITURL = String.format("http://127.0.0.1:%d", PORT); + private static final String OAUTH_SECRET = "oauthsecret"; + private static final String TOKENCREATOR_SECRET = "secret"; + private static final String REDIRECT_URI = "/odlux/token?"; + + @BeforeClass + public static void init() throws IllegalArgumentException, Exception { + + TokenCreator tokenCreator = TokenCreator.getInstance(Config.TOKENALG_HS256, TOKENCREATOR_SECRET, "issuer", 30*60); + OAuthProviderConfig config = new OAuthProviderConfig("git", GITURL, null, "odlux.app", OAUTH_SECRET, "openid", + "gitlab test", "", null, false); + oauthService = new GitlabProviderServiceToTest(config, REDIRECT_URI, tokenCreator); + try { + initGitlabTestWebserver(PORT, "/"); + } catch (IOException e) { + fail(e.getMessage()); + } + } + + @AfterClass + public static void close() { + stopTestWebserver(); + } + + @Test + public void test() { + HttpServletRequest req; + HttpServletResponse resp = null; + String host = "http://localhost:8412"; + final String state = "stateabc"; + try { + req = mock(HttpServletRequest.class); + resp = mock(HttpServletResponse.class); + when(req.getParameter("code")).thenReturn("abcdefg"); + when(req.getParameter("state")).thenReturn(state); + oauthService.addState(state); + oauthService.handleRedirect(req, resp, host); + } catch (IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(302); + //verify(resp).setHeader("Location",any(String.class)); + } + + public void test2() { + oauthService.sendLoginRedirectResponse(null, null); + } + + public static class GitlabProviderServiceToTest extends GitlabProviderService { + + public GitlabProviderServiceToTest(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + super(config, redirectUri, tokenCreator); + } + + public void addState(String state) { + this.randomIds.add(state); + } + } + + private static int randomPort(int min, int max) { + Random random = new Random(); + return random.nextInt(max + 1 - min) + min; + } + + public static void initGitlabTestWebserver(int port, String baseUri) throws IOException { + server = HttpServer.create(new InetSocketAddress("127.0.0.1", port), 0); + httpThreadPool = Executors.newFixedThreadPool(5); + server.setExecutor(httpThreadPool); + server.createContext(baseUri, new MyHandler()); + //server.createContext("/", new MyRootHandler()); + server.setExecutor(null); // creates a default executor + server.start(); + System.out.println("http server started"); + } + + public static void stopTestWebserver() { + if (server != null) { + server.stop(0); + httpThreadPool.shutdownNow(); + System.out.println("http server stopped"); + } + } + + private static String loadResourceFileContent(String filename) { + try { + return Files.readString(new File(filename).toPath()); + } catch (IOException e) { + fail(e.getMessage()); + } + return null; + } + + public static class MyHandler implements HttpHandler { + private static final String GITLAB_TOKEN_ENDPOINT = "/oauth/token"; + private static final String GITLAB_USER_ENDPOINT = "/api/v4/user"; + private static final String GITLAB_GROUP_ENDPOINT = "/api/v4/groups?min_access_level=10"; + private static final String GITLAB_TOKEN_RESPONSE = + loadResourceFileContent("src/test/resources/oauth/gitlab-token-response.json"); + private static final String GITLAB_USER_RESPONSE = + loadResourceFileContent("src/test/resources/oauth/gitlab-user-response.json"); + private static final String GITLAB_GROUP_RESPONSE = + loadResourceFileContent("src/test/resources/oauth/gitlab-groups-response.json"); + + @Override + public void handle(HttpExchange t) throws IOException { + final String method = t.getRequestMethod(); + final String uri = t.getRequestURI().toString(); + System.out.println(String.format("req received: %s %s", method, t.getRequestURI())); + OutputStream os = null; + try { + if (method.equals("GET")) { + if (uri.equals(GITLAB_USER_ENDPOINT)) { + t.sendResponseHeaders(200, GITLAB_USER_RESPONSE.length()); + os = t.getResponseBody(); + os.write(GITLAB_USER_RESPONSE.getBytes()); + } else if (uri.equals(GITLAB_GROUP_ENDPOINT)) { + t.sendResponseHeaders(200, GITLAB_GROUP_RESPONSE.length()); + os = t.getResponseBody(); + os.write(GITLAB_GROUP_RESPONSE.getBytes()); + } + } else if (method.equals("POST")) { + if (uri.equals(GITLAB_TOKEN_ENDPOINT)) { + t.sendResponseHeaders(200, GITLAB_TOKEN_RESPONSE.length()); + os = t.getResponseBody(); + os.write(GITLAB_TOKEN_RESPONSE.getBytes()); + } else { + t.sendResponseHeaders(404, 0); + } + } else { + t.sendResponseHeaders(404, 0); + } + System.out.println("req handled successful"); + + } catch (Exception e) { + System.out.println(e.getMessage()); + } finally { + if (os != null) { + os.close(); + } + } + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java new file mode 100644 index 000000000..acc7c6b36 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java @@ -0,0 +1,196 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.KeycloakProviderService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; + +public class TestKeycloakAuthService { + + private static HttpServer server; + private static ExecutorService httpThreadPool; + private static KeycloakProviderServiceToTest oauthService; + private static final int PORT = randomPort(50000, 55000); + private static final String KEYCLOAKURL = String.format("http://127.0.0.1:%d", PORT); + private static final String OAUTH_SECRET = "oauthsecret"; + private static final String TOKENCREATOR_SECRET = "secret"; + private static final String REDIRECT_URI = "/odlux/token?"; + + @BeforeClass + public static void init() throws IllegalArgumentException, Exception { + + TokenCreator tokenCreator = TokenCreator.getInstance(Config.TOKENALG_HS256, TOKENCREATOR_SECRET, "issuer", 30*60); + OAuthProviderConfig config = new OAuthProviderConfig("kc", KEYCLOAKURL, null, "odlux.app", OAUTH_SECRET, + "openid", "keycloak test", "onap",null, false); + oauthService = new KeycloakProviderServiceToTest(config, REDIRECT_URI, tokenCreator); + try { + initKeycloakTestWebserver(PORT, "/"); + } catch (IOException e) { + fail(e.getMessage()); + } + } + + @AfterClass + public static void close() { + stopTestWebserver(); + } + + @Test + public void test() { + HttpServletRequest req; + HttpServletResponse resp = null; + String host = "http://localhost:8412"; + final String state = "stateabc"; + try { + req = mock(HttpServletRequest.class); + resp = mock(HttpServletResponse.class); + when(req.getParameter("code")).thenReturn("abcdefg"); + when(req.getParameter("state")).thenReturn(state); + oauthService.handleRedirect(req, resp, host); + } catch (IOException e) { + fail(e.getMessage()); + } + verify(resp).setStatus(302); + //verify(resp).setHeader("Location",any(String.class)); + } + + public void test2() { + oauthService.sendLoginRedirectResponse(null, null); + } + @Ignore + @Test + public void test3() { + HttpServletResponse resp = mock(HttpServletResponse.class); + String token = ""; + try { + oauthService.sendLogoutRedirectResponse(token, resp,"http://sdnr.onap/odlux/index.html"); + verify(resp).setStatus(302); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + public static class KeycloakProviderServiceToTest extends KeycloakProviderService { + + public KeycloakProviderServiceToTest(OAuthProviderConfig config, String redirectUri, + TokenCreator tokenCreator) throws UnableToConfigureOAuthService { + super(config, redirectUri, tokenCreator); + } + } + + private static int randomPort(int min, int max) { + Random random = new Random(); + return random.nextInt(max + 1 - min) + min; + } + + public static void initKeycloakTestWebserver(int port, String baseUri) throws IOException { + server = HttpServer.create(new InetSocketAddress("127.0.0.1", port), 0); + httpThreadPool = Executors.newFixedThreadPool(5); + server.setExecutor(httpThreadPool); + server.createContext(baseUri, new MyHandler()); + //server.createContext("/", new MyRootHandler()); + server.setExecutor(null); // creates a default executor + server.start(); + System.out.println("http server started"); + } + + public static void stopTestWebserver() { + if (server != null) { + server.stop(0); + httpThreadPool.shutdownNow(); + System.out.println("http server stopped"); + } + } + + private static String loadResourceFileContent(String filename) { + try { + return Files.readString(new File(filename).toPath()); + } catch (IOException e) { + fail(e.getMessage()); + } + return null; + } + + public static class MyHandler implements HttpHandler { + private static final String KEYCLOAK_TOKEN_ENDPOINT = "/auth/realms/onap/protocol/openid-connect/token"; + private static final String KEYCLOAK_LOGOUT_ENDPOINT = "/auth/realms/onap/protocol/openid-connect/logout"; + private static final String KEYCLOAK_TOKEN_RESPONSE = + loadResourceFileContent("src/test/resources/oauth/keycloak-token-response.json"); + + @Override + public void handle(HttpExchange t) throws IOException { + final String method = t.getRequestMethod(); + final String uri = t.getRequestURI().toString(); + System.out.println(String.format("req received: %s %s", method, t.getRequestURI())); + OutputStream os = null; + try { + if("GET".equals(method)){ + if(KEYCLOAK_LOGOUT_ENDPOINT.equals(uri)){ + t.sendResponseHeaders(200, 0); + } + } + else if ("POST".equals(method)) { + if (uri.equals(KEYCLOAK_TOKEN_ENDPOINT)) { + t.sendResponseHeaders(200, KEYCLOAK_TOKEN_RESPONSE.length()); + os = t.getResponseBody(); + os.write(KEYCLOAK_TOKEN_RESPONSE.getBytes()); + } else { + t.sendResponseHeaders(404, 0); + } + } else { + t.sendResponseHeaders(404, 0); + } + System.out.println("req handled successful"); + + } catch (Exception e) { + System.out.println(e.getMessage()); + } finally { + if (os != null) { + os.close(); + } + } + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java new file mode 100644 index 000000000..31d72944c --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; + +public class TestPolicy { + + private static final String PATH_1 = "/p1/**"; + + @Test + public void testPolicyAllowAll() { + OdlPolicy p = OdlPolicy.allowAll(PATH_1); + assertTrue(p.getMethods().isGet()); + assertTrue(p.getMethods().isPost()); + assertTrue(p.getMethods().isPut()); + assertTrue(p.getMethods().isDelete()); + assertTrue(p.getMethods().isPatch()); + assertEquals(PATH_1,p.getPath()); + } + + @Test + public void testPolicyDenyAll() { + OdlPolicy p = OdlPolicy.denyAll(PATH_1); + assertFalse(p.getMethods().isGet()); + assertFalse(p.getMethods().isPost()); + assertFalse(p.getMethods().isPut()); + assertFalse(p.getMethods().isDelete()); + assertFalse(p.getMethods().isPatch()); + assertEquals(PATH_1,p.getPath()); + } + +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java new file mode 100644 index 000000000..2d03bab1d --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; + +public class TestProperty { + + @Ignore + @Test + public void test() { + String hostname = Config.getProperty("${HOSTNAME}", null); + System.out.println(hostname); + assertNotNull(hostname); + hostname = Config.getProperty("${HOSTNAME2}", null); + System.out.println(hostname); + assertNull(hostname); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java new file mode 100644 index 000000000..84d8e0a96 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java @@ -0,0 +1,108 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.fail; +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.JWTVerifier; +import java.io.IOException; +import java.security.Security; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Date; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.RSAKeyReader; + +/** + * + * @author jack + * + */ +public class TestRSAAlgorithms { + + private static final String ISSUER = "jwttest"; + private static final String SUBJECT = "meandmymonkey"; + + @BeforeClass + public static void init() { + Security.addProvider( + new BouncyCastleProvider() + ); + } + + /** + * private and public key were generated in ubuntu 20.04 with + * $ ssh-keygen -t rsa -b 4096 -m PEM -P "" -f jwtRS512.key + * $ openssl rsa -in jwtRS512.key -pubout -outform PEM -out jwtRS512.key.pub + */ + @Test + public void testRSA512() { + RSAPrivateKey privKey = null; + RSAPublicKey pubKey = null; + try { + privKey = RSAKeyReader.getPrivateKey("file://src/test/resources/jwtRS512.key"); + pubKey = RSAKeyReader.getPublicKey("file://src/test/resources/jwtRS512.key.pub"); + } catch (IOException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + verifyAlg(Algorithm.RSA512(pubKey, privKey)); + } + + /** + * private and public key were generated in ubuntu 20.04 with + * $ openssl genrsa 2048 -out rsa-2048bit-jwtRS256.key + * $ openssl rsa -in jwtRS256.key -pubout > jwtRS256.key.pub + */ + @Test + public void testRSA256() { + RSAPrivateKey privKey = null; + RSAPublicKey pubKey = null; + try { + privKey = RSAKeyReader.getPrivateKey("file://src/test/resources/jwtRS256.key"); + pubKey = RSAKeyReader.getPublicKey("file://src/test/resources/jwtRS256.key.pub"); + } catch (IOException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + verifyAlg(Algorithm.RSA512(pubKey, privKey)); + } + + private static void verifyAlg(Algorithm a) { + long now = new Date().getTime(); + final String token = JWT.create().withIssuer(ISSUER).withExpiresAt(new Date(now+10000)) + .withIssuedAt(new Date(now)) + .withSubject(SUBJECT) + .sign(a); + try { + JWTVerifier verifier = JWT.require(a).withIssuer(ISSUER).build(); + verifier.verify(token); + + } catch (JWTVerificationException e) { + fail(e.getMessage()); + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java new file mode 100644 index 000000000..ebf01a1ba --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java @@ -0,0 +1,219 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import com.auth0.jwt.interfaces.DecodedJWT; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.BearerToken; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.subject.PrincipalCollection; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.OAuth2Realm; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService; +import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; +import org.opendaylight.aaa.api.Authentication; +import org.opendaylight.aaa.api.TokenStore; +import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal; +import org.opendaylight.aaa.shiro.realm.TokenAuthRealm; +import org.opendaylight.aaa.tokenauthrealm.auth.AuthenticationManager; +import org.opendaylight.aaa.tokenauthrealm.auth.TokenAuthenticators; + +public class TestRealm { + + private static OAuth2RealmToTest realm; + private static TokenCreator tokenCreator; + + @BeforeClass + public static void init() throws IllegalArgumentException, Exception { + + try { + Config config = Config.getInstance(TestConfig.TEST_CONFIG_FILENAME); + tokenCreator = TokenCreator.getInstance(config); + TokenAuthRealm.prepareForLoad(new AuthenticationManager(), new TokenAuthenticators(), new TokenStore() { + @Override + public void put(String token, Authentication auth) { + + } + + @Override + public Authentication get(String token) { + return null; + } + + @Override + public boolean delete(String token) { + return false; + } + + @Override + public long tokenExpiration() { + return 0; + } + }); + realm = new OAuth2RealmToTest(); + } catch (IOException e) { + fail(e.getMessage()); + } + } + + + @Test + public void testTokenSupport() { + assertTrue(realm.supports(new UsernamePasswordToken())); + assertTrue(realm.supports(new BearerToken(""))); + } + + + @Test + public void testAuthorizationInfo() { + //bearer token use case + PrincipalCollection c = mock(PrincipalCollection.class); + final List roles = Arrays.asList("admin", "provision"); + UserTokenPayload userData = createUserData("", roles); + + DecodedJWT decodedJwt = tokenCreator.verify(tokenCreator.createNewJWT(userData).getToken()); + when(c.getPrimaryPrincipal()).thenReturn(decodedJwt); + + AuthorizationInfo ai = realm.doGetAuthorizationInfo(c); + for (String role : roles) { + assertTrue(ai.getRoles().contains(role)); + } + assertEquals(roles.size(), ai.getRoles().size()); + //odl token use case + ODLPrincipal principal = mock(ODLPrincipal.class); + when(principal.getRoles()).thenReturn(new HashSet(roles)); + PrincipalCollection c2 = mock(PrincipalCollection.class); + when(c2.getPrimaryPrincipal()).thenReturn(principal); + ai = realm.doGetAuthorizationInfo(c2); + for (String role : roles) { + assertTrue(ai.getRoles().contains(role)); + } + assertEquals(roles.size(), ai.getRoles().size()); + + } + + @Test + public void testUrlTrimming(){ + final String internalUrl="https://test.identity.onap:49333"; + final String externalUrl="https://test.identity.onap:49333"; + final String testUrl1 = "/my/token/endpoint"; + final String testUrl2 = internalUrl+testUrl1; + final String testUrl3 = externalUrl+testUrl1; + + assertEquals(testUrl1, AuthService.trimUrl(internalUrl, testUrl1)); + assertEquals(testUrl1, AuthService.trimUrl(internalUrl, testUrl2)); + assertEquals(testUrl1, AuthService.trimUrl(externalUrl, testUrl3)); + + assertEquals(testUrl2, AuthService.extendUrl(internalUrl, testUrl3)); + + + + } + @Test + public void testAssertCredentialsMatch() { + //bearer token use case + UserTokenPayload userData = createUserData("", Arrays.asList("admin", "provision")); + AuthenticationToken atoken = new BearerToken(tokenCreator.createNewJWT(userData).getToken()); + AuthenticationInfo ai = null; + try { + realm.assertCredentialsMatch(atoken, ai); + } catch (AuthenticationException e) { + fail(e.getMessage()); + } + //odl token use case + atoken = new UsernamePasswordToken("admin", "admin"); + try { + realm.assertCredentialsMatch(atoken, ai); + } catch (AuthenticationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testAuthenticationInfo() { + //bearer token use case + UserTokenPayload userData = createUserData("", Arrays.asList("admin", "provision")); + AuthenticationToken atoken = new BearerToken(tokenCreator.createNewJWT(userData).getToken()); + AuthenticationInfo ai = null; + try { + ai = realm.doGetAuthenticationInfo(atoken); + } catch (AuthenticationException e) { + fail(e.getMessage()); + } + //odl token use case + ai=null; + atoken = new UsernamePasswordToken("admin", "admin"); + try { + ai = realm.doGetAuthenticationInfo(atoken); + } catch (AuthenticationException e) { + fail(e.getMessage()); + } + } + + private static UserTokenPayload createUserData(String username, List roles) { + UserTokenPayload userData = new UserTokenPayload(); + userData.setExp(tokenCreator.getDefaultExp()); + userData.setFamilyName(""); + userData.setGivenName(""); + userData.setPreferredUsername(username); + userData.setRoles(roles); + return userData; + } + + public static class OAuth2RealmToTest extends OAuth2Realm { + + public OAuth2RealmToTest() throws IllegalArgumentException, Exception { + super(); + } + + @Override + public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) { + return super.doGetAuthorizationInfo(arg); + } + + @Override + public void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai) + throws AuthenticationException { + super.assertCredentialsMatch(atoken, ai); + } + + @Override + public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + return super.doGetAuthenticationInfo(token); + } + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java new file mode 100644 index 000000000..7d51b2fe8 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsModule; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions; + +public class OdlJsonMapper extends ObjectMapper { + + private static final long serialVersionUID = 1L; + + + public OdlJsonMapper() { + this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.setSerializationInclusion(Include.NON_NULL); + this.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); + this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); + YangToolsBuilderAnnotationIntrospector introspector = new YangToolsBuilderAnnotationIntrospector(); + //introspector.addDeserializer(Main.class, ShiroMainBuilder.class.getName()); + //introspector.addDeserializer(Permissions.class,PermissionsBuilder.class.getName()); + this.setAnnotationIntrospector(introspector); + this.registerModule(new YangToolsModule()); + } + + /* public static class PermissionsBuilder implements Builder { + private Permissions _value; + + public PermissionsBuilder() { + + } + public PermissionsBuilder(Permissions value) { + this._value = value; + } + + @Override + public Permissions build() { + return this._value; + } + }*/ +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java new file mode 100644 index 000000000..b965878e8 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; + +public class OdlXmlMapper extends XmlMapper{ + + private static final long serialVersionUID = 1L; + + + public OdlXmlMapper() { + this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.setSerializationInclusion(Include.NON_NULL); + this.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); + this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); + YangToolsBuilderAnnotationIntrospector introspector = new YangToolsBuilderAnnotationIntrospector(); + //introspector.addDeserializer(Main.class, ShiroMainBuilder.class.getName()); + + this.setAnnotationIntrospector(introspector); + } +} diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/aaa-app-config.test.xml b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/aaa-app-config.test.xml new file mode 100644 index 000000000..e46508d68 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/aaa-app-config.test.xml @@ -0,0 +1,77 @@ + + + + + + +

+ tokenAuthRealm + org.onap.ccsdk.features.sdnr.wt.oauthprovider.OAuth2Realm +
+ +
+ securityManager.realms + $tokenAuthRealm +
+ +
+ anyroles + org.opendaylight.aaa.shiro.filters.AnyRoleHttpAuthenticationFilter +
+
+ authcBearer + org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter2 +
+ +
+ accountingListener + org.opendaylight.aaa.shiro.filters.AuthenticationListener +
+
+ securityManager.authenticator.authenticationListeners + $accountingListener +
+ +
+ dynamicAuthorization + org.opendaylight.aaa.shiro.realm.MDSALDynamicAuthorizationFilter +
+ + + /**/operations/cluster-admin** + dynamicAuthorization + + + /**/v1/** + authcBearer, roles[admin] + + + /**/config/aaa*/** + authcBearer, roles[admin] + + + /oauth/** + anon + + + /odlux/** + anon + + + /apidoc/** + authcBasic, roles[admin] + + + /test123/** + authcBasic + + + /rests/** + authcBearer, anyroles["admin,provision"] + + + /** + authcBearer, anyroles["admin,provision"] + + + diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key new file mode 100644 index 000000000..c0c15e014 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAyzd6BwZLS1UKchZENYyVycHZWp9iRTtLx31dZHfG8h0PLawG +y+dXPEW8W/zVB13/Rdci9HXCnskBhzkFu9Ep+nI7X5C+lO3vxxNnGQ1CrRyHxHbb +BYlm6J55l6tQox5qVcWe4iMbLm7F2eNKFPqEUu8OInjmLFZvS9C0qtfpqdeoyt4G +XucUHcGZ/0E6yeq882+zYyb4pWN5PogAsP2KYeT1T6P0VCw4tda9GtokD3zOSaOg +IvhIqe9jLAVcqWkxpuhV+IQdULBOxcJziW3AdQcB5IFQ7/SfZ9SnO5OpDTe02R5q +bjH9k0iihrpI9HnlVrHqIEtFwDjuoPSeAOBjjwIDAQABAoIBAQCOfNeTFVa1+2rX +k8U/xtNAJCvC3v6IjIsV1VEmoNVd7gI2g+hAEHWaTUtFNIIqKD5VOgPIZMmRjF8F +8XWTu5UzheUbnOIEitEVRQWFC0c1GkwX9T6dIzqE4JlhPz3LIghtG6PL69GjPQh9 +PmEzVHRzsiq3AQ5jCDgBcNU89SdhbhPsfNpDq9+GaWUaVJ4MmJw52qLeSW0nh4NZ +fMSINAfGZ/3Q2Nfe55zIk4KICyatKYLUMdcwynMwWYdZzg1e/4gxemdWdgFVUdPl +rE6y404m+FrHl/nntL153u0C24jtEU0CJvLasu7hLjzAoANBzohcXxLY46jeNqk9 +yS4juMgBAoGBAPxn9hRH5vMxFCfT23/s1RnUB9Sal6OL8/hZ8OpwrnLaLmWDvvr5 +FBcDThhrHnJTLj0pOAxFX8kLjKgQdWB0ZqrEsG1R9AAVHxM4hXc92kDsAk4QJgCG +tKDtzk9PKy8Jt1LnOF9n6NDLZuZim9Sv7qim6tt0L7K/mGrlCN4Gq6E3AoGBAM4c +N2r0vObiSboryfY4xNSUZ1qLWAEJz4gyUQljSrlu2Gj5DK4rrTEd8Qyk9ehUdjuR +giejpdjIvmjQ7NNPUogJbIoSbtKmx+k8qF7ieRulJjVBiJZLwNtGhiB4e6oZdhNl +fJETn8MhkbOt8Sa1eEiR9u2O7IAYVwZLU/khkNxpAoGARxqKSgBPYSbsRKP767et ++I6wfgXmvd3JJqc/pOuFWTl5ZIOOo2jTbgAyWdKjSxV/qx8XeO16JEqqnxWz2y4v +Vd/+y20QzY0lqeZ8QrEb8LoLlC4cZn2MGOGlAtaMlb2o9SPJz6aYAWmrXS9eMrY1 +BzGua4/5d+Ndbo+CxfkfFFUCgYEAjFimW8w+/TDFZ2H96g2J6f8LyZns2PgnOuSY +Tb4w2cfi0MgVnFvdWP68bxG86PDqeXGBoSBMBCvdjF4HhXQUDNHt+K7Ii+RJaEaH +l+S69tokBEuViFIZBrclCeNAwfkIb/jBM8CbHzIylpkxBly3hSLvc5/I5wir6XtN +uOzkSVECgYEAy2oGf68OkNL74/WKDmQvnRxWkn78rCTzVAe0iJmJ3rAdak/Jb2Lj +iihXn0XPsedZOZStbZYCG6GtcZCRypPi9HjO6DRRYFv3+aicjS7tVuJ3u39e5nIR +K6eMAgFn1TAToc3gt/hUCnmreZ4ZUfQfuFK21Lqmn1FYJtck9ZHx0sw= +-----END RSA PRIVATE KEY----- diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key.pub b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key.pub new file mode 100644 index 000000000..add863aef --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS256.key.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyzd6BwZLS1UKchZENYyV +ycHZWp9iRTtLx31dZHfG8h0PLawGy+dXPEW8W/zVB13/Rdci9HXCnskBhzkFu9Ep ++nI7X5C+lO3vxxNnGQ1CrRyHxHbbBYlm6J55l6tQox5qVcWe4iMbLm7F2eNKFPqE +Uu8OInjmLFZvS9C0qtfpqdeoyt4GXucUHcGZ/0E6yeq882+zYyb4pWN5PogAsP2K +YeT1T6P0VCw4tda9GtokD3zOSaOgIvhIqe9jLAVcqWkxpuhV+IQdULBOxcJziW3A +dQcB5IFQ7/SfZ9SnO5OpDTe02R5qbjH9k0iihrpI9HnlVrHqIEtFwDjuoPSeAOBj +jwIDAQAB +-----END PUBLIC KEY----- diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key new file mode 100644 index 000000000..6b4e8c7bc --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEA5vZBjfLjlUPK0b/F8FbGAyT1jXNVv2vjl+ZGUlThDX1jn0Wh +XER5CL9CfkHKjJE47r8pQsO6nX9s5y+XzmAU9+QggtaDA+g0Px+cvCJQzJbtDbh0 +94m3uC50S+SSnYvr7vY1zy+jdswf/pXg1z059FokRxGso36SkSv81NYbN/WQrTKo +gY6jkZXfPP8/sn8KV8uf7jYy2ZyHtakM9c9oCopWH78mhf9ioUNbgJsAxZmiohQU +N5a3GbLS/nsTBOcVxUezvjvfb732iChKoARj3NiNN7HFHpXEXfiZ10OjrtAb9Y1K +9RZsu/MKcFxBhDZusXjee6/x+NluQwT3RybgkCyV/i97Sroc37wOqimxtoSJ+MZY +ZXNAUGNbNySkjvIGL8jWMj6w/zvyiHVbQg+DqY2Qds7Tdk29swYsMQQlz9v0FS/p +GFVWo+5HTm+3MMlaMjSofw6j5/sE4OvJ4RCcnX8Cj1Zq9PrsMLLSF5MBOCSiclpI +C1EYQ9Oi6XrcL3bbyyKGwB/u1X1HHnUmhRdKdVwKpSHR54XlfBDDoYtVnb1HTTxX +MuiGU0XQRLvdnytJX1Lk6NJg/UUUKhrVXiH05CZsxlPFjDlhEhp4Jh+f/mdf6llX +vsXn8k9ujBZBBD6PI4X7GkKB45H9zicbwt65f/MjhEohkbL5oZAKySzaUuMCAwEA +AQKCAgBF7uLCnH0UwUY0ZKEGuP+UDCjd/8JDB+QOJoe8fj722rTDkU3epk0PvPnh +SQKPtZlLkU5pDOMAtYjAJ8ULlERFGypM868QC8tmIahPvwRALqLwuJ2SJn0eo9JK ++Jb8ZVW3MY3xgjc4zW4SpEdEZSGbP4AklNF1X+n5UxxnRb1QIGcCSoiDUjFs77h8 +u70JyzXSh7GRa4/SHHdrJhjqhTa3mlOhoTuE72Np+P9H3adKLc70zKeifVxLx73j +mFiV73LEHYXrYC2zpA12BN0zvqCOSnPYHVfWfvrKiW/romt5j0IoA/Riabva3SiY +BRdBdUnnKvYS9Z+K/itI18QYI0lzSuLiaCTCo/3N/2MkuRMwS3Mvae7kK43/6c3w +sXobp8KBRMnpnT+AHENIHVJ35XKkWfTY9xMg/JkKbAXY06TitKW53ds03vb9Y9n2 +3SKBUcpbTkJJbJ50E/BiglLVxlllzVJiUIMNDGUmZO7eYQx9fs16cz4JkhzKcN+F +zYg4BVXL8blWU6AjXzexjTNuic/IxkqJruG05tCFwVxHjhajb9xQ1ANDMcXnwPmt +VKpU4KxrGqFgsVdZ5SE9gdu1g+zf96DdhXjHhZCfq6fsf2TYXD2SsUhx4kk9zOE/ +I4tXwf7Q7Ol24qlV9W8enc3gr1nk+buutl+I55LSM4bG4M3uQQKCAQEA/rkulfhl +wxStbVIICRl6iuC1nhqlxOBZAbc45pRgEDyTO5IfxnVA6kVCa5DkQ5cWZOoshKg9 +MNfHbo9JIYZzElnM/XxpmqIsHpQ+ZXe5XVaaYz9DogNnH2iLtQGVVLPphtxJxTqW +A6944GuhmZ9DmRwn0nN2nU0nUqBtLFio9+b7nChDaJj5aIkLHjx3p9ytjzzJP5nM +0lKSo9BD97+AhCaIT7NxjKSRWRs7ftf7Bv5vxPXrpgUN8ltkg4YVIzGX7UMXT+ga +H2kf+QkAJX1+9kbNMjkqhOH7zkv1DVqCVup9XewA2GltxoJZIVH04+QmgNWcS+XP +cbxe0r95tuMTqQKCAQEA6B6WYpC9UxXLPfOJdWDzSO3oh13RgQo1uEHdU9rc9vfi +vYZZsSL06uR7v6fuiuyAAayZgCTS1xr69MCAJR2056E3RthktAzOkfCJrcIyEHmy +b9yekRyL+R8P4HxV76AYqY52PhdgDntGoXb7hcGKt6hvkmcR41cnRHRjrb7zkEVy +55JY1woEVtt6otxHKZSnx5nlQct73Lv65QDfosfkESOmbE2W4G87XBk36I2YBywU +kNEr49tnI09qyEPJLjTTGxFdMeqXbnCgzSwqlBlrQE8NYJBsy2GBL0EWOYeRXkuz +RFug3o89uAOircy2virMhl6EOA0EKakWR4ZQCKlJqwKCAQEA40aBnYhL6/sIHtGh +n9Te9Qk4o4AtRnPSluhPWdUrvXD/AZkIxv+Z0y3G7MkUEoa9kX8sB5VBO9Jb/HbW +jpYzGD2N3OLkKvfmG8azwb9IYlLCYClzhBw7J9gVR4TJJBF/HThyjgsPDOzFEqCW +SMbE/tkTYwBo5kOQAXZo0res07yB5bw7IRnU94PHqsvTC7CoH3TiL+Bf042fj5Bl +BKoW1lK3Lz3x48Z2daYJuMynC398ZKX0A2bhIcyP65Z4R7WZVDaXl1GF9V7MC10P +h2PpI37a2aQOHxCvp0s4tBh80WZaQ7Iusumm7Acj1coVkjzgafWuhj3fkSC9DpeP +1zHXOQKCAQBCiVIOWvMKN/sUfRTwAqR6SUgYVXpShPy1Hpw1B03DtXbXYQWg0yZl +lq0qWRb116kx0aoGo4eUhXVeZzfUa9mJdBsGQc1MF0e3ab3tgvca5eeSTSle61Hs +TU0dykZP9BJduCqIzeaJAClU62haBQqgbrXcv5LPGhJ1eu9/xHbI6j9vxfGVYpev +1iYnPQFhF+2oN6MR4yRUN8ZJkqCIZsgnaZKxBOS03O2lDs2J6dykYaxbfroYDLJZ +2s//K/8lMZs57RZL0rUpwTs21Ow3m7m0q3RoM74b5o1DYGLghs3Su9xdQe6xHVpR +vykIrN/NTzNlaP55mrGQx5lNU2Dpuq0VAoIBAQDVCfAJlu+wkZmeXm1zUOFjOMvq +el3t55RCQ/SuhIpaNf2CWD6SOZfHfTxJ8nuYE+FJmjL6r9Z4a8ND0VPttuyBG6gY +siuZUE31+2OBvdKBhi4stqGZWMKJqYsDFH7QIfu7wSS1kuJ/vA7MB9f7IsrHJb2z +QBJoVMZoXhh4tqyFVatEp6yYSE4uKLvlKQSJ6W8DEuPggoiNPbhxQq2ctFUyup/S +9MsfJ9tj99mjlPSelMUXsHcsprIZBuhskfeidTe+gy43TBm0G8l7xeAGWkBlWQMR +L843JjebD6QCnPIS4nrW7kCRM8lv1ZId6D5Jq1Coc8b1ZrezfII7/eNgZZCv +-----END RSA PRIVATE KEY----- diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key.pub b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key.pub new file mode 100644 index 000000000..7191c95f8 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/jwtRS512.key.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5vZBjfLjlUPK0b/F8FbG +AyT1jXNVv2vjl+ZGUlThDX1jn0WhXER5CL9CfkHKjJE47r8pQsO6nX9s5y+XzmAU +9+QggtaDA+g0Px+cvCJQzJbtDbh094m3uC50S+SSnYvr7vY1zy+jdswf/pXg1z05 +9FokRxGso36SkSv81NYbN/WQrTKogY6jkZXfPP8/sn8KV8uf7jYy2ZyHtakM9c9o +CopWH78mhf9ioUNbgJsAxZmiohQUN5a3GbLS/nsTBOcVxUezvjvfb732iChKoARj +3NiNN7HFHpXEXfiZ10OjrtAb9Y1K9RZsu/MKcFxBhDZusXjee6/x+NluQwT3Rybg +kCyV/i97Sroc37wOqimxtoSJ+MZYZXNAUGNbNySkjvIGL8jWMj6w/zvyiHVbQg+D +qY2Qds7Tdk29swYsMQQlz9v0FS/pGFVWo+5HTm+3MMlaMjSofw6j5/sE4OvJ4RCc +nX8Cj1Zq9PrsMLLSF5MBOCSiclpIC1EYQ9Oi6XrcL3bbyyKGwB/u1X1HHnUmhRdK +dVwKpSHR54XlfBDDoYtVnb1HTTxXMuiGU0XQRLvdnytJX1Lk6NJg/UUUKhrVXiH0 +5CZsxlPFjDlhEhp4Jh+f/mdf6llXvsXn8k9ujBZBBD6PI4X7GkKB45H9zicbwt65 +f/MjhEohkbL5oZAKySzaUuMCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/mdsalDynAuthData.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/mdsalDynAuthData.json new file mode 100644 index 000000000..a1627682b --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/mdsalDynAuthData.json @@ -0,0 +1,694 @@ +{ + "policies": [ + { + "resource": "/restconf/**", + "index": 0, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + } + ] + }, + { + "resource": "/auth/v1/**", + "index": 1, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + } + ] + }, + { + "resource": "/config/aaa*/**", + "index": 2, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + } + ] + }, + { + "resource": "/jolokia/**", + "index": 3, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + }, + { + "role": "raftstate", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250004/**", + "index": 4, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "huawei", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250005/**", + "index": 5, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "huawei", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250006/**", + "index": 6, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "siae", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250007/**", + "index": 7, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "siae", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250008/**", + "index": 8, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "siae", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250009/**", + "index": 9, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "siae", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250010/**", + "index": 10, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "ericsson", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250011/**", + "index": 11, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "ericsson", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513559991A/**", + "index": 14, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "ericsson", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513559991B/**", + "index": 15, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "ericsson", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250012/**", + "index": 12, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "zte", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250013/**", + "index": 13, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "zte", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + }, + { + "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/**", + "index": 16, + "permissions": [ + { + "role": "admin", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "provisioner", + "actions": [ + "put", + "get", + "patch", + "delete", + "post" + ] + }, + { + "role": "planner", + "actions": [ + "get" + ] + }, + { + "role": "monitor", + "actions": [ + "get" + ] + } + ] + } + ] + } diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-groups-response.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-groups-response.json new file mode 100644 index 000000000..85fc37cc8 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-groups-response.json @@ -0,0 +1,112 @@ +[ + { + "id": 51, + "web_url": "https://my-git-server.com/groups/group1", + "name": "Group1", + "path": "group1", + "description": "", + "visibility": "private", + "share_with_group_lock": false, + "require_two_factor_authentication": false, + "two_factor_grace_period": 48, + "project_creation_level": "developer", + "auto_devops_enabled": null, + "subgroup_creation_level": "maintainer", + "emails_disabled": null, + "mentions_disabled": null, + "lfs_enabled": true, + "avatar_url": null, + "request_access_enabled": true, + "full_name": "Group1", + "full_path": "group1", + "parent_id": null + }, + { + "id": 69, + "web_url": "https://my-git-server.com/groups/group2", + "name": "Group2", + "path": "group2", + "description": "", + "visibility": "private", + "share_with_group_lock": false, + "require_two_factor_authentication": false, + "two_factor_grace_period": 48, + "project_creation_level": "developer", + "auto_devops_enabled": null, + "subgroup_creation_level": "owner", + "emails_disabled": null, + "mentions_disabled": null, + "lfs_enabled": true, + "avatar_url": null, + "request_access_enabled": true, + "full_name": "Group2", + "full_path": "group2", + "parent_id": null + }, + { + "id": 24, + "web_url": "https://my-git-server.com/groups/group3", + "name": "group3", + "path": "group3", + "description": "", + "visibility": "private", + "share_with_group_lock": false, + "require_two_factor_authentication": false, + "two_factor_grace_period": 48, + "project_creation_level": "developer", + "auto_devops_enabled": null, + "subgroup_creation_level": "owner", + "emails_disabled": null, + "mentions_disabled": null, + "lfs_enabled": true, + "avatar_url": null, + "request_access_enabled": false, + "full_name": "group3", + "full_path": "group3", + "parent_id": null + }, + { + "id": 22, + "web_url": "https://my-git-server.com/groups/group4", + "name": "group4", + "path": "group4", + "description": "custom desc", + "visibility": "private", + "share_with_group_lock": false, + "require_two_factor_authentication": false, + "two_factor_grace_period": 48, + "project_creation_level": "developer", + "auto_devops_enabled": null, + "subgroup_creation_level": "owner", + "emails_disabled": null, + "mentions_disabled": null, + "lfs_enabled": true, + "avatar_url": "https://my-git-server.com/uploads/-/system/group/avatar/22/Factory_1b.svg.png", + "request_access_enabled": true, + "full_name": "group4", + "full_path": "group4", + "parent_id": null + }, + { + "id": 5, + "web_url": "https://my-git-server.com/groups/group5", + "name": "group5", + "path": "group5", + "description": "my group 5", + "visibility": "private", + "share_with_group_lock": false, + "require_two_factor_authentication": false, + "two_factor_grace_period": 48, + "project_creation_level": "developer", + "auto_devops_enabled": null, + "subgroup_creation_level": "owner", + "emails_disabled": null, + "mentions_disabled": null, + "lfs_enabled": true, + "avatar_url": "https://my-git-server.com/uploads/-/system/group/avatar/5/mylogo.png", + "request_access_enabled": true, + "full_name": "group5", + "full_path": "group5", + "parent_id": null + } +] \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-token-response.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-token-response.json new file mode 100644 index 000000000..0a6bd7231 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-token-response.json @@ -0,0 +1,7 @@ +{ + "access_token":"asfhoipmspaodm-asndfoiasnf-aisjdaisjj", + "expires_in":12345, + "refresh_expires_in":123456, + "refresh_token":"asdsadasd", + "token_type":"bearer" +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-user-response.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-user-response.json new file mode 100644 index 000000000..b08332b41 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/gitlab-user-response.json @@ -0,0 +1,32 @@ +{ + "id": 21, + "name": "me", + "username": "my-username", + "state": "active", + "avatar_url": "https://my-git-server.com/uploads/-/system/user/avatar/21/avatar.png", + "web_url": "https://my-git-server.com/my-username", + "created_at": "2017-05-15T14:49:38.396Z", + "bio": "", + "location": "", + "public_email": "", + "skype": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "", + "last_sign_in_at": "2021-02-12T12:56:34.094Z", + "confirmed_at": "2018-01-18T09:49:08.463Z", + "last_activity_on": "2021-02-15", + "email": "me@my-server.com", + "theme_id": null, + "color_scheme_id": 1, + "projects_limit": 0, + "current_sign_in_at": "2021-02-15T03:17:12.140Z", + "identities": [], + "can_create_group": false, + "can_create_project": false, + "two_factor_enabled": false, + "external": false, + "private_profile": false, + "is_admin": true +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/keycloak-token-response.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/keycloak-token-response.json new file mode 100644 index 000000000..c62ed9458 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oauth/keycloak-token-response.json @@ -0,0 +1,11 @@ +{ + "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkbWFSWXRkaHFkVXFDV2lmRWdNRHFBcWVBcU8tMnFoTDBjdnByelRGdWRRIn0.eyJleHAiOjE2MTExMzU5MjEsImlhdCI6MTYxMTEzNDEyMSwiYXV0aF90aW1lIjoxNjExMTM0MDkxLCJqdGkiOiIzYzFlZmMzZi1lMjFiLTQ3MzktYTY1YS1jNjY1M2ZhOGRjNTQiLCJpc3MiOiJodHRwOi8vMTAuMjAuMTEuMTYwOjgwODAvYXV0aC9yZWFsbXMvb25hcCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI0NDZhMjRiYy1kOGEwLTQzZGQtYWZhNS1lNTZlZWQ3NWRlYjgiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJvZGx1eC5hcHAiLCJzZXNzaW9uX3N0YXRlIjoiMTI5YjRhNjMtNzBhMS00MjFmLWEzM2YtOWFjZDkyZTIzM2ZmIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJwcm92aXNpb24iLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ikx1a2UgU2t5d2Fsa2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoibHVrZS5za3l3YWxrZXIiLCJnaXZlbl9uYW1lIjoiTHVrZSIsImZhbWlseV9uYW1lIjoiU2t5d2Fsa2VyIiwiZW1haWwiOiJsdWtlLnNreXdhbGtlckBzZG5yLm9uYXAub3JnIn0.tn2NrEGYLRq1u0DkqxD2iDM72hFrDBPGA_q23S-htiRH113yt14a0CzJxU9El0YDobbzog9xm0ELbx6W4jYsGguMABqIi4W5wtTqfbaCh7gmF208CqNpwzA7nG2palMLbBPpmGXiagUm4qLWQxrBP_VOaeW_kK0VHLaiTRJ-4vHuOXSNPYEDQZNCI2QCJQS_dn83K_JI4ecBHl8UeHFLB65BqmocpDHUvf2h835xuNFFQpXJWMcPM_j_FmFQeOSUDM4HmqgdVU9_b4APnDEVFiUezQdoEOfEYNsNlhCoXlaEEn2tCZfEkZ7k72DlhqJMQzomdaGKPk2g8XhKJNwMJg", + "expires_in": 1800, + "refresh_expires_in": 1800, + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhOGUzMDUwZS0wZmQxLTRjYjQtYjRiZS1jMDVlOGY4OGJhZGUifQ.eyJleHAiOjE2MTExMzU5MjEsImlhdCI6MTYxMTEzNDEyMSwianRpIjoiZmZiYWE3NDktZGVkNi00ZWMzLWI4MjYtYTI4NWY0ODY1ZGI0IiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL29uYXAiLCJhdWQiOiJodHRwOi8vMTAuMjAuMTEuMTYwOjgwODAvYXV0aC9yZWFsbXMvb25hcCIsInN1YiI6IjQ0NmEyNGJjLWQ4YTAtNDNkZC1hZmE1LWU1NmVlZDc1ZGViOCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJvZGx1eC5hcHAiLCJzZXNzaW9uX3N0YXRlIjoiMTI5YjRhNjMtNzBhMS00MjFmLWEzM2YtOWFjZDkyZTIzM2ZmIiwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCJ9.mt9VHtiBZycHcEuVCOZVjjtyoOGYNaDVvtcA1NPScIQ", + "token_type": "bearer", + "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkbWFSWXRkaHFkVXFDV2lmRWdNRHFBcWVBcU8tMnFoTDBjdnByelRGdWRRIn0.eyJleHAiOjE2MTExMzU5MjEsImlhdCI6MTYxMTEzNDEyMSwiYXV0aF90aW1lIjoxNjExMTM0MDkxLCJqdGkiOiJjZjUzZTc0ZC1kYjZiLTQ4YTUtODkyOS1jYzU3YjY3YjAxN2QiLCJpc3MiOiJodHRwOi8vMTAuMjAuMTEuMTYwOjgwODAvYXV0aC9yZWFsbXMvb25hcCIsImF1ZCI6Im9kbHV4LmFwcCIsInN1YiI6IjQ0NmEyNGJjLWQ4YTAtNDNkZC1hZmE1LWU1NmVlZDc1ZGViOCIsInR5cCI6IklEIiwiYXpwIjoib2RsdXguYXBwIiwic2Vzc2lvbl9zdGF0ZSI6IjEyOWI0YTYzLTcwYTEtNDIxZi1hMzNmLTlhY2Q5MmUyMzNmZiIsImF0X2hhc2giOiJSUXdDclpkQmFKV0VFdmxsRVNxRjV3IiwiYWNyIjoiMSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ikx1a2UgU2t5d2Fsa2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoibHVrZS5za3l3YWxrZXIiLCJnaXZlbl9uYW1lIjoiTHVrZSIsImZhbWlseV9uYW1lIjoiU2t5d2Fsa2VyIiwiZW1haWwiOiJsdWtlLnNreXdhbGtlckBzZG5yLm9uYXAub3JnIn0.rueTNrnvRa4PMo7NS8l4xxRhhNiGzXLmtcUeyWnj3AjFaUoNKuS9l85K3KjRT3zjq494YsepIGuK33I20rvFwDLclcJNHuumAgBnR5dRBi5fLhm7x8YkebhdTHPiYL4hfygpZ7APN1PtcDZnb-uEjjT-RAtjnfk3r-oP6CtqWzI5MjOPnf5HaEwWpkuTjmJf3kyyf_pdhhVkgTwuC-kD8iMjyRIzuZJxVwWVA3S43eL0R7MaIDlpJrOp9EBRfMlObAypc1bLtKwopT0sBla1CM9GmUU2ZYbQb79-hey0rd7CWx1uBkZUxt5myiExBm3pI46boXLP7dzjzxHUKg0m-A", + "not-before-policy": 1611134054, + "session_state": "129b4a63-70a1-421f-a33f-9acd92e233ff", + "scope": "openid profile email" +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oom.test.config.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oom.test.config.json new file mode 100644 index 000000000..4e5707fa1 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/oom.test.config.json @@ -0,0 +1,21 @@ +{ + "tokenSecret": "secret", + "tokenIssuer": "ONAP SDNC", + "publicUrl": "https://sdnc.onap:30205", + "redirectUri": "null", + "supportOdlUsers": "true", + "providers": [ + { + "id": "htgit", + "type": "GITLAB", + "url": "https://git-.com", + "clientId": "f52440b7dcd4bb75", + "secret": "9bd45916f52440b7dcd4bb75", + "scope": "api+openid+read_user+profile", + "title": " Gitlab", + "roleMapping": { + "mygitlabgroup": "admin" + } + } + ] +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.config.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.config.json new file mode 100644 index 000000000..a55576b9e --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.config.json @@ -0,0 +1,20 @@ +{ + "tokenSecret": "secret2134", + "tokenIssuer": "ONAP SDNC", + "publicUrl": "http://nasp.diasf.de", + "redirectUri": "/index.html#redirect=", + "supportOdlUsers": "true", + "tokenLifetime":3600, + "providers": [ + { + "id": "keycloak", + "type": "KEYCLOAK", + "url": "http://10.20.11.160:8080", + "clientId": "odlux.app", + "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", + "scope": "openid", + "title": "OSNL Keycloak Provider", + "realmName":"onap" + } + ] +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256-invalid.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256-invalid.json new file mode 100644 index 000000000..30b80c45a --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256-invalid.json @@ -0,0 +1,24 @@ +{ + "tokenSecret": "", + "tokenPubKey": "file:///src/test/resources/jwtRS256.key.pub", + "algorithm":"RS256", + "tokenIssuer": "ONAP SDNC", + "publicUrl": "http://nasp.diasf.de", + "redirectUri": "/index.html#redirect=", + "supportOdlUsers": "true", + "tokenLifetime":3600, + "providers": [ + { + "id": "keycloak", + "type": "KEYCLOAK", + "url": "http://10.20.11.160:8080", + "clientId": "odlux.app", + "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", + "publickey": "", + "algorithm":"RS256", + "scope": "openid", + "title": "OSNL Keycloak Provider", + "realmName":"onap" + } + ] +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256.json new file mode 100644 index 000000000..02a4e8f5f --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS256.json @@ -0,0 +1,22 @@ +{ + "tokenSecret": "file:///src/test/resources/jwtRS256.key", + "tokenPubKey": "file:///src/test/resources/jwtRS256.key.pub", + "algorithm":"RS256", + "tokenIssuer": "ONAP SDNC", + "publicUrl": "http://nasp.diasf.de", + "redirectUri": "/index.html#redirect=", + "supportOdlUsers": "true", + "tokenLifetime":3600, + "providers": [ + { + "id": "keycloak", + "type": "KEYCLOAK", + "url": "http://10.20.11.160:8080", + "clientId": "odlux.app", + "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", + "scope": "openid", + "title": "OSNL Keycloak Provider", + "realmName":"onap" + } + ] +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS512.json b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS512.json new file mode 100644 index 000000000..eddc6c362 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-core/src/test/resources/test.configRS512.json @@ -0,0 +1,22 @@ +{ + "tokenSecret": "file:///src/test/resources/jwtRS512.key", + "tokenPubKey": "file:///src/test/resources/jwtRS512.key.pub", + "algorithm":"RS512", + "tokenIssuer": "ONAP SDNC", + "publicUrl": "http://nasp.diasf.de", + "redirectUri": "/index.html#redirect=", + "supportOdlUsers": "true", + "tokenLifetime":3600, + "providers": [ + { + "id": "keycloak", + "type": "KEYCLOAK", + "url": "http://10.20.11.160:8080", + "clientId": "odlux.app", + "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", + "scope": "openid", + "title": "OSNL Keycloak Provider", + "realmName":"onap" + } + ] +} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/oauth-realm/pom.xml b/sdnr/wt/oauth-provider/oauth-realm/pom.xml new file mode 100644 index 000000000..ef8706ae0 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-realm/pom.xml @@ -0,0 +1,154 @@ + + + + + 4.0.0 + + + org.onap.ccsdk.parent + binding-parent + 2.6.1 + + + + org.onap.ccsdk.features.sdnr.wt + sdnr-wt-oauth-realm + 1.7.0-SNAPSHOT + bundle + + ccsdk-features :: ${project.artifactId} + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + true + true + + + + + ${project.groupId} + sdnr-wt-oauth-core + ${project.version} + + + org.opendaylight.aaa + aaa-shiro + + + org.opendaylight.aaa + aaa-shiro + + + org.apache.shiro + shiro-web + + + ${project.groupId} + sdnr-wt-common + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.version} + + org.onap.ccsdk.features.sdnr.wt.oauthprovider;version=${project.version}, + org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters;version=${project.version}, + org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;version=${project.version}, + org.onap.ccsdk.features.sdnr.wt.oauthprovider.services;version=${project.version} + + + javax.servlet, + javax.servlet.http, + javax.net.ssl, + javax.crypto, + javax.crypto.spec, + javax.xml.transform, + javax.xml.datatype, + javax.management, + javax.security.auth, + javax.security.auth.login, + javax.security.auth.callback, + javax.xml.parsers, + javax.xml.namespace, + javax.xml.transform.stream, + org.apache.commons.codec.binary, + org.apache.shiro, + org.apache.shiro.authc, + org.apache.shiro.authz, + org.apache.shiro.realm, + org.apache.shiro.subject, + org.apache.shiro.web.filter.authc, + org.apache.shiro.web.filter.authz, + org.apache.shiro.web.util, + org.jolokia.osgi.security, + org.onap.ccsdk.features.sdnr.wt.common.http, + org.opendaylight.aaa.api, + org.opendaylight.aaa.api.shiro.principal, + org.opendaylight.aaa.shiro.realm, + org.opendaylight.mdsal.binding.api, + org.opendaylight.mdsal.common.api, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.policies, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission, + org.opendaylight.yangtools.concepts, + org.opendaylight.yangtools.yang.binding, + org.opendaylight.yangtools.yang.common, + org.slf4j, + com.fasterxml.jackson.databind, + com.fasterxml.jackson.databind.deser.std, + com.fasterxml.jackson.databind.ser.std, + com.fasterxml.jackson.databind.module, + com.fasterxml.jackson.annotation, + com.fasterxml.jackson.core.type, + com.fasterxml.jackson.core, + com.google.common.base, + com.google.common.collect, + com.google.common.util.concurrent + + *;scope=compile|runtime;inline=false + *;scope=compile|runtime;artifactId=!shiro-core;inline=false + true + org.opendaylight.aaa.shiro + + + + + + diff --git a/sdnr/wt/oauth-provider/oauth-web/pom.xml b/sdnr/wt/oauth-provider/oauth-web/pom.xml new file mode 100644 index 000000000..0fa834d2b --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-web/pom.xml @@ -0,0 +1,155 @@ + + + + + 4.0.0 + + + org.onap.ccsdk.parent + binding-parent + 2.6.1 + + + + org.onap.ccsdk.features.sdnr.wt + sdnr-wt-oauth-web + 1.7.0-SNAPSHOT + bundle + + ccsdk-features :: ${project.artifactId} + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + true + true + + + + ${project.groupId} + sdnr-wt-oauth-core + ${project.version} + + + org.opendaylight.aaa + aaa-shiro + + + org.opendaylight.aaa + aaa-shiro + + + org.apache.shiro + shiro-web + + + ${project.groupId} + sdnr-wt-common + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.version} + + org.onap.ccsdk.features.sdnr.wt.oauthprovider.http;version=${project.version}, + org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client;version=${project.version} + + + javax.servlet, + javax.servlet.http, + javax.net.ssl, + javax.crypto, + javax.crypto.spec, + javax.xml.transform, + javax.xml.datatype, + javax.management, + javax.security.auth, + javax.security.auth.login, + javax.security.auth.callback, + javax.xml.parsers, + javax.xml.namespace, + javax.xml.transform.stream, + org.apache.commons.codec.binary, + org.apache.shiro, + org.apache.shiro.authc, + org.apache.shiro.authz, + org.apache.shiro.config, + org.apache.shiro.realm, + org.apache.shiro.subject, + org.apache.shiro.web.env, + org.apache.shiro.web.filter.authz, + org.jolokia.osgi.security, + org.onap.ccsdk.features.sdnr.wt.common.http, + org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions, + org.opendaylight.aaa.api, + org.opendaylight.aaa.api.shiro.principal, + org.opendaylight.aaa.shiro.realm, + org.opendaylight.aaa.shiro.web.env, + org.opendaylight.aaa.tokenauthrealm.auth, + org.opendaylight.mdsal.binding.api, + org.opendaylight.mdsal.common.api, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.policies, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission, + org.opendaylight.yangtools.concepts, + org.opendaylight.yangtools.yang.binding, + org.opendaylight.yangtools.yang.common, + org.osgi.service.http, + org.slf4j, + com.fasterxml.jackson.databind, + com.fasterxml.jackson.databind.deser.std, + com.fasterxml.jackson.databind.ser.std, + com.fasterxml.jackson.databind.module, + com.fasterxml.jackson.dataformat.xml, + com.fasterxml.jackson.annotation, + com.fasterxml.jackson.core.type, + com.fasterxml.jackson.core, + com.google.common.base, + com.google.common.collect, + com.google.common.util.concurrent + + + *;scope=compile|runtime;artifactId=sdnr-wt-oauth-core,java-jwt,bcprov-jdk15on,aaa-shiro;inline=false + true + + + + + + diff --git a/sdnr/wt/oauth-provider/oauth-web/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/wt/oauth-provider/oauth-web/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml new file mode 100644 index 000000000..c782e3ee1 --- /dev/null +++ b/sdnr/wt/oauth-provider/oauth-web/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/sdnr/wt/oauth-provider/pom.xml b/sdnr/wt/oauth-provider/pom.xml index 587d9679f..c4dbef2b8 100755 --- a/sdnr/wt/oauth-provider/pom.xml +++ b/sdnr/wt/oauth-provider/pom.xml @@ -40,8 +40,9 @@ ccsdk-features :: ${project.artifactId} - provider-jar - provider-osgi + oauth-core + oauth-realm + oauth-web diff --git a/sdnr/wt/oauth-provider/provider-jar/pom.xml b/sdnr/wt/oauth-provider/provider-jar/pom.xml deleted file mode 100644 index 6ad79ef8f..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/pom.xml +++ /dev/null @@ -1,188 +0,0 @@ - - - - 4.0.0 - - - org.onap.ccsdk.parent - binding-parent - 2.6.1 - - - - org.onap.ccsdk.features.sdnr.wt - sdnr-wt-oauth-provider-jar - 1.6.0-SNAPSHOT - jar - - ccsdk-features :: ${project.artifactId} - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 - - - - - true - true - - - - ${project.groupId} - sdnr-wt-common - ${project.version} - - - com.fasterxml.jackson.core - jackson-databind - provided - - - com.auth0 - java-jwt - - - org.bouncycastle - bcprov-jdk15on - - - org.opendaylight.aaa - aaa-shiro - - - org.opendaylight.aaa - aaa-cert - - - org.opendaylight.aaa - aaa-filterchain - - - org.opendaylight.aaa - aaa-password-service-api - - - org.opendaylight.aaa.web - web-api - - - org.opendaylight.aaa.web - servlet-api - - - commons-collections - commons-collections - - - commons-text - commons-text - - - com.google.code.gson - gson - - - org.opendaylight.mdsal - mdsal-binding-api - - - com.h2database - h2 - - - com.google.guava - guava - - - ehcache-root - ehcache - - - - - org.opendaylight.mdsal - mdsal-binding-api - provided - - - org.opendaylight.mdsal - yang-binding - provided - - - jakarta.servlet - jakarta.servlet-api - provided - - - org.mockito - mockito-core - test - - - org.eclipse.jetty - jetty-server - test - - - org.eclipse.jetty - jetty-servlet - test - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - test - - - ${project.groupId} - sdnr-wt-yang-utils - ${project.version} - test - - - org.opendaylight.mdsal.binding.model.ietf - rfc6991-ietf-yang-types - test - - - org.opendaylight.netconf - sal-netconf-connector - test - - - org.osgi - org.osgi.core - test - - - org.osgi - osgi.cmpn - 7.0.0 - compile - - - diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/Helper.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/Helper.java deleted file mode 100644 index 38947a124..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/Helper.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider; - -import org.jolokia.osgi.security.Authenticator; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; -import org.opendaylight.aaa.api.IdMService; -import org.opendaylight.mdsal.binding.api.DataBroker; -import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration; -import org.osgi.service.http.HttpService; -import org.osgi.service.http.NamespaceException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletException; -import java.io.IOException; - -public class Helper { - - private static final Logger LOG = LoggerFactory.getLogger(Helper.class); - private AuthHttpServlet authServlet; - - public Helper() throws UnableToConfigureOAuthService, IOException, InvalidConfigurationException { - this.authServlet = new AuthHttpServlet(); - - } - - public void onUnbindService(HttpService httpService) { - httpService.unregister(AuthHttpServlet.BASEURI); - this.authServlet = null; - } - - public void onBindService(HttpService httpService) - throws ServletException, NamespaceException { - if (httpService == null) { - LOG.warn("Unable to inject HttpService into loader."); - } else { - httpService.registerServlet(AuthHttpServlet.BASEURI, authServlet, null, null); - LOG.info("auth servlet registered."); - } - } - - public void setOdlAuthenticator(Authenticator odlAuthenticator) { - authServlet.setOdlAuthenticator(odlAuthenticator); - } - - public void setOdlIdentityService(IdMService odlIdentityService) { - this.authServlet.setOdlIdentityService(odlIdentityService); - } - - public void setShiroConfiguration(ShiroConfiguration shiroConfiguration) { - this.authServlet.setShiroConfiguration(shiroConfiguration); - } - - public void setDataBroker(DataBroker dataBroker) { - this.authServlet.setDataBroker(dataBroker); - } - - public void init() { - - } - - public void close() { - - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java deleted file mode 100644 index b9f3d6119..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider; - -import com.auth0.jwt.interfaces.DecodedJWT; -import java.io.IOException; -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.SimpleAuthenticationInfo; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.authz.SimpleAuthorizationInfo; -import org.apache.shiro.subject.PrincipalCollection; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; -import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal; -import org.apache.shiro.authc.BearerToken; -import org.opendaylight.aaa.shiro.realm.TokenAuthRealm; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class OAuth2Realm extends TokenAuthRealm { - - public static final String REALM_NAME = "OAuth2Realm"; - private static final Logger LOG = LoggerFactory.getLogger(OAuth2Realm.class); - private final TokenCreator tokenCreator; - private final Config config; - - public OAuth2Realm() throws IllegalArgumentException, IOException, InvalidConfigurationException { - super(); - super.setName(REALM_NAME); - this.config = Config.getInstance(); - this.tokenCreator = TokenCreator.getInstance(this.config); - LOG.info("instantiated"); - } - - @Override - public boolean supports(AuthenticationToken token) { - boolean supports = (token instanceof BearerToken) - || (this.config.doSupportOdlUsers() && (token instanceof UsernamePasswordToken)); - LOG.debug("supports {} is {}", token == null ? null : token.getClass().getName(), supports); - return supports; - } - - @Override - public String getName() { - return REALM_NAME; - } - - @Override - protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai) - throws AuthenticationException { - LOG.debug("assertCredentialsMatch"); - if (atoken instanceof BearerToken) { - if (this.tokenCreator.verify(((BearerToken) atoken).getToken()) == null) { - throw new AuthenticationException("Credentials do not match"); - } - } else if (this.config.doSupportOdlUsers() && (atoken instanceof UsernamePasswordToken)) { - //nothing to do - } else { - throw new AuthenticationException("AuthenticationInfo is not an OAuth2AuthenticationInfo"); - } - } - - - // check what I can do - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) { - - LOG.debug("auth info in shiro"); - Object principal = arg.getPrimaryPrincipal(); - if (principal instanceof DecodedJWT) { - LOG.debug("detected jwt token"); - try { - DecodedJWT token = (DecodedJWT) arg.getPrimaryPrincipal(); - String[] roles = token.getClaim("roles").asArray(String.class); - SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); - for (String role : roles) { - LOG.trace("found role {} in token", role); - authorizationInfo.addRole(role); - } - return authorizationInfo; - } catch (ClassCastException e) { - LOG.error("Couldn't decode authorization request", e); - } - } else if (principal instanceof ODLPrincipal) { - LOG.debug("detected basic token"); - ODLPrincipal odlPrincipal = (ODLPrincipal) principal; - return new SimpleAuthorizationInfo(odlPrincipal.getRoles()); - } - return new SimpleAuthorizationInfo(); - } - - - - // check who I am - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { - - LOG.debug("auth token in shiro:"); - if (token instanceof UsernamePasswordToken && this.config.doSupportOdlUsers()) { - LOG.debug("basic auth token found"); - return super.doGetAuthenticationInfo(token); - } else if (token instanceof BearerToken) { - LOG.debug("jwt token found"); - BearerToken oauthToken = (BearerToken) token; - - DecodedJWT jwt = this.tokenCreator.verify(oauthToken.getToken()); - if (jwt != null) { - SimpleAuthenticationInfo authenticationInfo = - new SimpleAuthenticationInfo(jwt, token.getCredentials(), getName()); - return authenticationInfo; - - } - } else { - LOG.debug("no valid token found"); - } - throw new AuthenticationException("unable to verify token " + token); - - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java deleted file mode 100644 index 1caec63e0..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonSetter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Config { - - private static final Logger LOG = LoggerFactory.getLogger(Config.class); - private static final String DEFAULT_CONFIGFILENAME = "etc/oauth-provider.config.json"; - private static final String ENVVARIABLE = "${"; - private static final String REGEXENVVARIABLE = "(\\$\\{[A-Z0-9_-]+\\})"; - private static final Pattern pattern = Pattern.compile(REGEXENVVARIABLE); - private static final String DEFAULT_TOKENISSUER = "Opendaylight"; - private static final String DEFAULT_TOKENSECRET = generateSecret(); - private static final String DEFAULT_REDIRECTURI = "/odlux/index.html#/oauth?token="; - private static final String DEFAULT_SUPPORTODLUSERS = "true"; - public static final String TOKENALG_HS256 = "HS256"; - public static final String TOKENALG_RS256 = "RS256"; - public static final String TOKENALG_RS512 = "RS512"; - private static final String CLIENTALG_PRE = "Client"; - public static final String TOKENALG_CLIENT_RS256 = CLIENTALG_PRE + TOKENALG_RS256; - public static final String TOKENALG_CLIENT_RS512 = CLIENTALG_PRE + TOKENALG_RS512; - private static final String DEFAULT_TOKEN_ALGORITHM = TOKENALG_HS256; - - private static final long DEFAULT_TOKEN_LIFETIME = 30 * 60; - private static final List VALID_ALGORITHMS = - Arrays.asList(TOKENALG_HS256, TOKENALG_RS256, TOKENALG_RS512, TOKENALG_CLIENT_RS256, TOKENALG_CLIENT_RS512); - private static final List VALID_ALGORITHMS_FOR_INTERNAL_LOGIN = - Arrays.asList(TOKENALG_HS256, TOKENALG_RS256, TOKENALG_RS512); - private static SecureRandom random; - private static Config _instance; - - private List providers; - private String redirectUri; - private String supportOdlUsers; - private String tokenSecret; - private String tokenPubKey; - private String algorithm; - private String tokenIssuer; - private String publicUrl; - private long tokenLifetime; - - @Override - public String toString() { - return "Config [providers=" + providers + ", redirectUri=" + redirectUri + ", supportOdlUsers=" - + supportOdlUsers + ", tokenSecret=***, tokenPubKey=" + tokenPubKey + ", algorithm=" + algorithm - + ", tokenIssuer=" + tokenIssuer + ", publicUrl=" + publicUrl + ", tokenLifetime=" + tokenLifetime - + "]"; - } - - public List getProviders() { - return providers; - } - - public void setProviders(List providers) { - this.providers = providers; - } - - public String getRedirectUri() { - return redirectUri; - } - - public void setRedirectUri(String redirectUri) { - this.redirectUri = redirectUri; - } - - public String getSupportOdlUsers() { - return supportOdlUsers; - } - - public void setSupportOdlUsers(String supportOdlUsers) { - this.supportOdlUsers = supportOdlUsers; - } - - public String getTokenSecret() { - return tokenSecret; - } - - public void setTokenSecret(String tokenSecret) { - this.tokenSecret = tokenSecret; - } - - public String getAlgorithm() { - return this.algorithm; - } - - public void setAlgorithm(String alg) { - this.algorithm = alg; - } - - @JsonGetter("tokenPubKey") - public String getPublicKey() { - return this.tokenPubKey; - } - - @JsonSetter("tokenPubKey") - public void setPublicKey(String pubKey) { - this.tokenPubKey = pubKey; - } - - public String getTokenIssuer() { - return tokenIssuer; - } - - public void setTokenIssuer(String tokenIssuer) { - this.tokenIssuer = tokenIssuer; - } - - public String getPublicUrl() { - return publicUrl; - } - - public void setPublicUrl(String publicUrl) { - this.publicUrl = publicUrl; - } - - public long getTokenLifetime() { - return this.tokenLifetime; - } - - public void setTokenLifetime(long lifetime) { - this.tokenLifetime = lifetime; - } - - @JsonIgnore - private void handleEnvironmentVars() { - if (isEnvExpression(this.tokenIssuer)) { - this.tokenIssuer = getProperty(this.tokenIssuer, null); - } - if (isEnvExpression(this.tokenSecret)) { - this.tokenSecret = getProperty(this.tokenSecret, null); - } - if (isEnvExpression(this.tokenPubKey)) { - this.tokenPubKey = getProperty(this.tokenPubKey, null); - } - if (isEnvExpression(this.algorithm)) { - this.algorithm = getProperty(this.algorithm, null); - } - if (isEnvExpression(this.publicUrl)) { - this.publicUrl = getProperty(this.publicUrl, null); - } - if (isEnvExpression(this.redirectUri)) { - this.redirectUri = getProperty(this.redirectUri, null); - } - if (isEnvExpression(this.supportOdlUsers)) { - this.supportOdlUsers = getProperty(this.supportOdlUsers, null); - } - if (this.providers != null && !this.providers.isEmpty()) { - for (OAuthProviderConfig cfg : this.providers) { - cfg.handleEnvironmentVars(); - } - } - } - - @JsonIgnore - private void handleDefaultValues() { - if (this.tokenIssuer == null || this.tokenIssuer.isEmpty()) { - this.tokenIssuer = DEFAULT_TOKENISSUER; - } - if (this.algorithm == null || this.algorithm.isEmpty()) { - this.algorithm = DEFAULT_TOKEN_ALGORITHM; - } - if (TOKENALG_HS256.equals(this.algorithm) && (this.tokenSecret == null || this.tokenSecret.isEmpty())) { - this.tokenSecret = DEFAULT_TOKENSECRET; - } - if (this.redirectUri == null || this.redirectUri.isEmpty() || "null".equals(this.redirectUri)) { - this.redirectUri = DEFAULT_REDIRECTURI; - } - if (this.publicUrl != null && (this.publicUrl.isEmpty() || "null".equals(this.publicUrl))) { - this.publicUrl = null; - } - if (this.supportOdlUsers == null || this.supportOdlUsers.isEmpty()) { - this.supportOdlUsers = DEFAULT_SUPPORTODLUSERS; - } - if (this.tokenLifetime <= 0) { - this.tokenLifetime = DEFAULT_TOKEN_LIFETIME; - } - } - - static boolean isEnvExpression(String key) { - return key != null && key.contains(ENVVARIABLE); - } - - public static String generateSecret() { - return generateSecret(30); - } - - public static String generateSecret(int targetStringLength) { - int leftLimit = 48; // numeral '0' - int rightLimit = 122; // letter 'z' - if (random == null) { - random = new SecureRandom(); - } - String generatedString = random.ints(leftLimit, rightLimit + 1) - .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)).limit(targetStringLength) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); - return generatedString; - } - - /** - * - * @param key environment var - * @param defValue default value if no env var found - * @return - */ - public static String getProperty(final String key, final String defValue) { - String value = defValue; - //try to read env var - boolean found = false; - if (isEnvExpression(key)) { - - LOG.debug("try to find env var(s) for {}", key); - final Matcher matcher = pattern.matcher(key); - String tmp = new String(key); - while (matcher.find() && matcher.groupCount() > 0) { - final String mkey = matcher.group(1); - if (mkey != null) { - try { - LOG.debug("match found for v={} and env key={}", key, mkey); - String envvar = mkey.substring(2, mkey.length() - 1); - String env = System.getenv(envvar); - tmp = tmp.replace(mkey, env == null ? "" : env); - if (env != null && !env.isEmpty()) { - found = true; - } - } catch (SecurityException e) { - LOG.warn("unable to read env {}: {}", key, e); - } - } - } - if (found) { - value = tmp; - } - } - return value; - } - - public static boolean getPropertyBoolean(String key, boolean defaultValue) { - final String value = getProperty(key, String.valueOf(defaultValue)); - return value.equals("true"); - } - - public static Config load(String filename) throws IOException, InvalidConfigurationException { - CustomObjectMapper mapper = new CustomObjectMapper(); - File file = new File(filename); - if (!file.exists()) { - throw new FileNotFoundException(); - } - String content = String.join("", Files.readAllLines(file.toPath())); - Config cfg = mapper.readValue(content, Config.class); - cfg.handleEnvironmentVars(); - cfg.handleDefaultValues(); - cfg.validate(); - return cfg; - } - - - @JsonIgnore - private void validate() throws InvalidConfigurationException { - //verify that algorithm is supported - if (!VALID_ALGORITHMS.contains(this.algorithm)) { - throw new InvalidConfigurationException(String.format("Algorithm '%s' is not supported ", this.algorithm)); - } - //verify that set values are matching the algorithm - //if hs256 check if secret is set - if (this.algorithm.startsWith("HS")) { - if (this.tokenSecret == null || this.tokenSecret.isBlank()) { - throw new InvalidConfigurationException( - String.format("There is no secret set for algorithm '%s'", this.algorithm)); - } - } - //if rs256 or rs512 check if secret(private key) and pubkey are set - if (this.algorithm.startsWith("RS")) { - if (this.tokenSecret == null || this.tokenSecret.isBlank()) { - throw new InvalidConfigurationException( - String.format("There is no secret set for algorithm '%s'", this.algorithm)); - } - if (this.tokenPubKey == null || this.tokenPubKey.isBlank()) { - throw new InvalidConfigurationException( - String.format("There is no public key for algorithm '%s'", this.algorithm)); - } - } - //if client rs256 or client rs512 check if pubkey are set - if (this.algorithm.startsWith("Client")) { - if (this.tokenPubKey == null || this.tokenPubKey.isBlank()) { - throw new InvalidConfigurationException( - String.format("There is no public key for algorithm '%s'", this.algorithm)); - } - } - } - - @JsonIgnore - public boolean doSupportOdlUsers() { - return "true".equals(this.supportOdlUsers); - } - - - public static Config getInstance() throws IOException, InvalidConfigurationException { - return getInstance(DEFAULT_CONFIGFILENAME); - } - - public static Config getInstance(String filename) throws IOException, InvalidConfigurationException { - if (_instance == null) { - _instance = load(filename); - } - return _instance; - } - - public boolean loginActive() { - return VALID_ALGORITHMS_FOR_INTERNAL_LOGIN.contains(this.algorithm); - } - - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java deleted file mode 100644 index aa23d4dc1..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class CustomObjectMapper extends ObjectMapper{ - - private static final long serialVersionUID = 1L; - - - public CustomObjectMapper() { - this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.setSerializationInclusion(Include.NON_NULL); - this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java deleted file mode 100644 index a0e97de74..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/InvalidConfigurationException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class InvalidConfigurationException extends Exception { - - public InvalidConfigurationException(String str) { - super(str); - } - - private static final long serialVersionUID = 1L; - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java deleted file mode 100644 index 67186baa7..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class KeycloakRole { - private String id; - private String name; - private String description; - private boolean composite; - private boolean clientRole; - private String containerId; // realmname - - public String getName() { - return name; - } - - public boolean isClientRole() { - return clientRole; - } - - public void setClientRole(boolean clientRole) { - this.clientRole = clientRole; - } - - public String getContainerId() { - return containerId; - } - - public void setContainerId(String containerId) { - this.containerId = containerId; - } - - public boolean isComposite() { - return composite; - } - - public void setComposite(boolean composite) { - this.composite = composite; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public void setName(String name) { - this.name = name; - } - -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java deleted file mode 100644 index c99ec0d71..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -/** - * { - "exp": 1610362593, - "iat": 1610361393, - "jti": "09bd6f2c-5dba-44a0-bd76-cd0d440137d0", - "iss": "http://10.20.11.160:8080/auth/realms/onap", - "aud": "account", - "sub": "446a24bc-d8a0-43dd-afa5-e56eed75deb8", - "typ": "Bearer", - "azp": "admin-cli", - "session_state": "db2c96f4-cc9b-47e8-a83f-a01c50d656f2", - "acr": "1", - "realm_access": { - "roles": [ - "provision", - "offline_access", - "uma_authorization" - ] - }, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile" - ] - } - }, - "scope": "profile email", - "email_verified": false, - "name": "Luke Skywalker", - "preferred_username": "luke.skywalker", - "given_name": "Luke", - "family_name": "Skywalker", - "email": "luke.skywalker@sdnr.onap.org" -} - * @author jack - * - */ -public class KeycloakUserTokenPayload { - - private long exp; - private long iat; - private String jti; - private String iss; - private String aud; - private String sub; - private String typ; - private String azp; - @JsonProperty("session_state") - private String sessionState; - private String acr; - @JsonProperty("realm_access") - private RealmAccessData realmAccess; - @JsonProperty("resource_access") - private ResourceAccessData resourceAccess; - private String scope; - @JsonProperty("email_verified") - private String emailVerified; - private String name; - @JsonProperty("preferred_username") - private String preferredUsername; - @JsonProperty("given_name") - private String givenName; - @JsonProperty("family_name") - private String familyName; - private String email; - - public long getExp() { - return exp; - } - public void setExp(long exp) { - this.exp = exp; - } - public long getIat() { - return iat; - } - public void setIat(long iat) { - this.iat = iat; - } - public String getJti() { - return jti; - } - public void setJti(String jti) { - this.jti = jti; - } - public String getIss() { - return iss; - } - public void setIss(String iss) { - this.iss = iss; - } - public String getAud() { - return aud; - } - public void setAud(String aud) { - this.aud = aud; - } - public String getSub() { - return sub; - } - public void setSub(String sub) { - this.sub = sub; - } - public String getTyp() { - return typ; - } - public void setTyp(String typ) { - this.typ = typ; - } - public String getAzp() { - return azp; - } - public void setAzp(String azp) { - this.azp = azp; - } - public String getSessionState() { - return sessionState; - } - public void setSessionState(String sessionState) { - this.sessionState = sessionState; - } - public String getAcr() { - return acr; - } - public void setAcr(String acr) { - this.acr = acr; - } - public RealmAccessData getRealmAccess() { - return realmAccess; - } - public void setRealmAccess(RealmAccessData realmAccess) { - this.realmAccess = realmAccess; - } - public ResourceAccessData getResourceAccess() { - return resourceAccess; - } - public void setResourceAccess(ResourceAccessData resourceAccess) { - this.resourceAccess = resourceAccess; - } - public String getScope() { - return scope; - } - public void setScope(String scope) { - this.scope = scope; - } - public String getEmailVerified() { - return emailVerified; - } - public void setEmailVerified(String emailVerified) { - this.emailVerified = emailVerified; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public String getPreferredUsername() { - return preferredUsername; - } - public void setPreferredUsername(String preferredUsername) { - this.preferredUsername = preferredUsername; - } - public String getGivenName() { - return givenName; - } - public void setGivenName(String givenName) { - this.givenName = givenName; - } - public String getFamilyName() { - return familyName; - } - public void setFamilyName(String familyName) { - this.familyName = familyName; - } - public String getEmail() { - return email; - } - public void setEmail(String email) { - this.email = email; - } - - - public static class RealmAccessData { - private List roles; - - public List getRoles(){ - return this.roles; - } - public void setRoles(List roles) { - this.roles = roles; - } - } - public static class ResourceAccessData { - private RealmAccessData account; - - public RealmAccessData getAccount() { - return this.account; - } - public void setAccount(RealmAccessData account) { - this.account = account; - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java deleted file mode 100644 index d13be9602..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class NoDefinitionFoundException extends Exception { - - private static final long serialVersionUID = 1L; - - public NoDefinitionFoundException(String message) { - super(message); - } - - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java deleted file mode 100644 index 4fb0d0069..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import java.util.HashMap; -import java.util.Map; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.OAuthProviderFactory.OAuthProvider; - -public class OAuthProviderConfig { - - private String url; - private String internalUrl; - private String clientId; - private String secret; - private String id; - private String title; - private String scope; - private String realmName; - private String openIdConfigUrl; - - private boolean trustAll; - private OAuthProvider type; - private Map roleMapping; - - public OAuthProvider getType() { - return type; - } - - public OAuthProviderConfig(String id, String url, String internalUrl, String clientId, String secret, String scope, - String title, String realmName, String openIdConfigUrl, boolean trustAll) { - this.id = id; - this.url = url; - this.internalUrl = internalUrl; - this.clientId = clientId; - this.secret = secret; - this.scope = scope; - this.title = title; - this.realmName = realmName; - this.trustAll = trustAll; - this.openIdConfigUrl = openIdConfigUrl; - this.roleMapping = new HashMap<>(); - } - - @Override - public String toString() { - return "OAuthProviderConfig [url=" + url + ", clientId=" + clientId + ", secret=" + secret + ", id=" + id - + ", title=" + title + ", scope=" + scope + ", realmName=" + realmName + ", trustAll=" + trustAll - + ", type=" + type + ", roleMapping=" + roleMapping + "]"; - } - - public void setType(OAuthProvider type) { - this.type = type; - } - - public OAuthProviderConfig() { - this(null, null, null, null, null, null, null, null, null, false); - } - - public void setUrl(String url) { - this.url = url; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public void setSecret(String secret) { - this.secret = secret; - } - - public void setId(String id) { - this.id = id; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setScope(String scope) { - this.scope = scope; - } - - public String getId() { - return this.id; - } - - public String getUrl() { - return this.url; - } - - public String getClientId() { - return this.clientId; - } - - public String getSecret() { - return this.secret; - } - - public String getTitle() { - return this.title; - } - - public String getScope() { - return this.scope; - } - - public String getRealmName() { - return realmName; - } - - public void setRealmName(String realmName) { - this.realmName = realmName; - } - - public boolean trustAll() { - return trustAll; - } - - public void setTrustAll(boolean trustAll) { - this.trustAll = trustAll; - } - - public Map getRoleMapping() { - return roleMapping; - } - - public void setRoleMapping(Map roleMapping) { - this.roleMapping = roleMapping; - } - - public String getInternalUrl() { - return internalUrl; - } - - public void setInternalUrl(String internalUrl) { - this.internalUrl = internalUrl; - } - - public void setOpenIdConfigUrl(String openIdConfigUrl){ this.openIdConfigUrl = openIdConfigUrl;} - - public String getOpenIdConfigUrl() { return this.openIdConfigUrl;} - @JsonIgnore - public void handleEnvironmentVars() { - if (Config.isEnvExpression(this.id)) { - this.id = Config.getProperty(this.id, null); - } - if (Config.isEnvExpression(this.url)) { - this.url = Config.getProperty(this.url, null); - } - if (Config.isEnvExpression(this.internalUrl)) { - this.internalUrl = Config.getProperty(this.internalUrl, null); - } - if (Config.isEnvExpression(this.clientId)) { - this.clientId = Config.getProperty(this.clientId, null); - } - if (Config.isEnvExpression(this.secret)) { - this.secret = Config.getProperty(this.secret, null); - } - if (Config.isEnvExpression(this.scope)) { - this.scope = Config.getProperty(this.scope, null); - } - if (Config.isEnvExpression(this.title)) { - this.title = Config.getProperty(this.title, null); - } - if (Config.isEnvExpression(this.realmName)) { - this.realmName = Config.getProperty(this.realmName, null); - } - if (Config.isEnvExpression(this.openIdConfigUrl)) { - this.openIdConfigUrl = Config.getProperty(this.openIdConfigUrl, null); - } - } - - @JsonIgnore - public String getUrlOrInternal() { - return this.internalUrl != null && this.internalUrl.length() > 0 ? this.internalUrl : this.url; - } - - @JsonIgnore - public boolean hasToBeConfigured(){ - return this.openIdConfigUrl!=null && this.openIdConfigUrl.length()>0; - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java deleted file mode 100644 index 0e25b5b0f..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class OAuthResponseData { - - private String access_token; - private double expires_in; - private double refresh_expires_in; - private String refresh_token; - private String token_type; - private String id_token; - - public OAuthResponseData() { - } - - public OAuthResponseData(String token) { - this.access_token = token; - } - - public String getAccess_token() { - return access_token; - } - - public String getToken_type() { - return token_type; - } - - public void setToken_type(String token_type) { - this.token_type = token_type; - } - - public String getRefresh_token() { - return refresh_token; - } - - public void setRefresh_token(String refresh_token) { - this.refresh_token = refresh_token; - } - - public double getRefresh_expires_in() { - return refresh_expires_in; - } - - public void setRefresh_expires_in(double refresh_expires_in) { - this.refresh_expires_in = refresh_expires_in; - } - - public double getExpires_in() { - return expires_in; - } - - public void setExpires_in(double expires_in) { - this.expires_in = expires_in; - } - - public void setAccess_token(String access_token) { - this.access_token = access_token; - } - - public void setId_token(String id_token){ this.id_token = id_token;} - public String getId_token(){ return this.id_token;} - @Override - public String toString() { - return "OAuthResponseData [access_token=" + access_token + ", expires_in=" + expires_in - + ", refresh_expires_in=" + refresh_expires_in + ", refresh_token=" + refresh_token + ", token_type=" - + token_type + "]"; - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java deleted file mode 100644 index 0371f377d..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -import com.auth0.jwt.JWT; -import com.auth0.jwt.interfaces.DecodedJWT; -import org.apache.shiro.authc.BearerToken; - -public class OAuthToken { - private final String access_token; - private final String token_type; - private final long expires_at; - private final long issued_at; - - public OAuthToken(BearerToken btoken) { - this.access_token = btoken.getToken(); - this.token_type = "Bearer"; - DecodedJWT token = JWT.decode(this.access_token); - this.expires_at = token.getExpiresAt().getTime() / 1000L; - this.issued_at = token.getIssuedAt().getTime() / 1000L; - } - - public String getAccess_token() { - return access_token; - } - - public String getToken_type() { - return token_type; - } - - public long getExpires_at() { - return expires_at; - } - public long getIssued_at() { - return issued_at; - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java deleted file mode 100644 index 19eb4b68e..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class OdlPolicy { - - private String path; - private PolicyMethods methods; - - - public OdlPolicy() { - - } - - public OdlPolicy(String path, PolicyMethods methods) { - this.path = path; - this.methods = methods; - } - - public PolicyMethods getMethods() { - return methods; - } - - public void setMethods(PolicyMethods methods) { - this.methods = methods; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public static OdlPolicy allowAll(String path) { - return new OdlPolicy(path, PolicyMethods.allowAll()); - } - - public static OdlPolicy denyAll(String path) { - return new OdlPolicy(path, PolicyMethods.denyAll()); - } - - public static class PolicyMethods { - private boolean get; - private boolean post; - private boolean put; - private boolean delete; - private boolean patch; - - public PolicyMethods() { - this(false, false, false, false, false); - } - - public PolicyMethods(boolean get, boolean post, boolean put, boolean del, boolean patch) { - this.get = get; - this.post = post; - this.put = put; - this.delete = del; - this.patch = patch; - } - - public boolean isGet() { - return get; - } - - public void setGet(boolean get) { - this.get = get; - } - - public boolean isPost() { - return post; - } - - public void setPost(boolean post) { - this.post = post; - } - - public boolean isPut() { - return put; - } - - public void setPut(boolean put) { - this.put = put; - } - - public boolean isDelete() { - return delete; - } - - public void setDelete(boolean delete) { - this.delete = delete; - } - - public boolean isPatch() { - return patch; - } - - public void setPatch(boolean patch) { - this.patch = patch; - } - - public static PolicyMethods allowAll() { - return new PolicyMethods(true, true, true, true, true); - } - - public static PolicyMethods denyAll() { - return new PolicyMethods(false, false, false, false, false); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java deleted file mode 100644 index d94631fe3..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OpenIdConfigResponseData.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class OpenIdConfigResponseData { - - private String issuer; - private String authorization_endpoint; - private String token_endpoint; - private String userinfo_endpoint; - - private String end_session_endpoint; - private String jwks_uri; - - public OpenIdConfigResponseData(){ - - } - - public String getIssuer() { - return issuer; - } - - public void setIssuer(String issuer) { - this.issuer = issuer; - } - - public String getAuthorization_endpoint() { - return authorization_endpoint; - } - - public void setAuthorization_endpoint(String authorization_endpoint) { - this.authorization_endpoint = authorization_endpoint; - } - - public String getToken_endpoint() { - return token_endpoint; - } - - public void setToken_endpoint(String token_endpoint) { - this.token_endpoint = token_endpoint; - } - - public String getUserinfo_endpoint() { - return userinfo_endpoint; - } - - public void setUserinfo_endpoint(String userinfo_endpoint) { - this.userinfo_endpoint = userinfo_endpoint; - } - - public String getJwks_uri() { - return jwks_uri; - } - - public void setJwks_uri(String jwks_uri) { - this.jwks_uri = jwks_uri; - } - - public String getEnd_session_endpoint() { - return end_session_endpoint; - } - - public void setEnd_session_endpoint(String end_session_endpoint) { - this.end_session_endpoint = end_session_endpoint; - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java deleted file mode 100644 index b791a4040..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UnableToConfigureOAuthService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -public class UnableToConfigureOAuthService extends Exception { - - public UnableToConfigureOAuthService(String configUrl){ - super(String.format("Unable to configure OAuth service from url %s", configUrl)); - } - public UnableToConfigureOAuthService(String configUrl, int responseCode){ - super(String.format("Unable to configure OAuth service from url %s. bad response with code %d", configUrl, responseCode)); - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java deleted file mode 100644 index f7731f0b8..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data; - -import java.util.List; - -public class UserTokenPayload { - - public static final String PROVIDERID_INTERNAL="Internal"; - - private List roles; - private String preferredUsername; - private String givenName; - private String familyName; - private long exp; - private long iat; - - private String providerId; - - public long getExp() { - return exp; - } - - public long getIat() { - return this.iat; - } - - public void setPreferredUsername(String preferredUsername) { - this.preferredUsername = preferredUsername; - } - - public void setGivenName(String givenName) { - this.givenName = givenName; - } - - public void setFamilyName(String familyName) { - this.familyName = familyName; - } - - public void setExp(long exp) { - this.exp = exp; - } - - public void setIat(long iat) { - this.iat = iat; - } - - public String getPreferredUsername() { - return preferredUsername; - } - - public String getGivenName() { - return givenName; - } - - public String getFamilyName() { - return familyName; - } - - public List getRoles() { - return this.roles; - } - - public void setRoles(List roles) { - this.roles = roles; - } - - public void setProviderId(String providerId){ this.providerId = providerId;} - - public String getProviderId(){ return this.providerId;} - - public static UserTokenPayload createInternal(String username, List roles) { - UserTokenPayload data = new UserTokenPayload(); - data.setPreferredUsername(username); - data.setRoles(roles); - data.setProviderId(PROVIDERID_INTERNAL); - return data; - } - - - public boolean isInternal() { - return PROVIDERID_INTERNAL.equals(this.providerId); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java deleted file mode 100644 index 0dc58efff..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/AnyRoleHttpAuthenticationFilter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters; - -import java.util.Arrays; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import org.apache.shiro.subject.Subject; -import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Requires the requesting user to be {@link org.apache.shiro.subject.Subject#isAuthenticated() authenticated} for the - * request to continue, and if they're not, requires the user to login via the HTTP Bearer protocol-specific challenge. - * Upon successful login, they're allowed to continue on to the requested resource/url. - *

- * The {@link #onAccessDenied(ServletRequest, ServletResponse)} method will only be called if the subject making the - * request is not {@link org.apache.shiro.subject.Subject#isAuthenticated() authenticated} - * - * @see RFC 2617 - * @see OAuth2 Authorization Request Header Field - * @since 1.5 - */ - -public class AnyRoleHttpAuthenticationFilter extends RolesAuthorizationFilter { - - /** - * This class's private logger. - */ - private static final Logger LOG = LoggerFactory.getLogger(AnyRoleHttpAuthenticationFilter.class); - - @Override - public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { - final Subject subject = getSubject(request, response); - final String[] rolesArray = (String[]) mappedValue; - LOG.debug("isAccessAllowed {}", Arrays.asList(rolesArray)); - - if (rolesArray == null || rolesArray.length == 0) { - //no roles specified, so nothing to check - allow access. - LOG.debug("no role specified: access allowed"); - return true; - } - - for (String roleName : rolesArray) { - LOG.debug("checking role {}", roleName); - if (subject.hasRole(roleName)) { - LOG.debug("role matched to {}: access allowed", roleName); - return true; - } - } - LOG.debug("no role matched: access denied"); - return false; - } -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java deleted file mode 100644 index 6fb41d799..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/BearerAndBasicHttpAuthenticationFilter.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters; - -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.web.filter.authc.BearerHttpAuthenticationFilter; -import org.apache.shiro.web.util.WebUtils; -import org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BearerAndBasicHttpAuthenticationFilter extends BearerHttpAuthenticationFilter{ - - // defined in lower-case for more efficient string comparison - private static final Logger LOG = LoggerFactory.getLogger(BearerAndBasicHttpAuthenticationFilter.class); - private ODLHttpAuthenticationHelperFilter basicAuthFilter; - - public BearerAndBasicHttpAuthenticationFilter() { - this.basicAuthFilter = new ODLHttpAuthenticationHelperFilter(); - } - - protected static final String OPTIONS_HEADER = "OPTIONS"; - - @Override - protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { - final String authHeader = this.getAuthzHeader(request); - if (authHeader != null && authHeader.startsWith("Basic")) { - return this.createBasicAuthToken(request, response); - } - return super.createToken(request, response); - } - - @Override - protected String[] getPrincipalsAndCredentials(String scheme, String token) { - LOG.debug("getPrincipalsAndCredentials with scheme {} and token {}", scheme, token); - if (scheme.toLowerCase().equals("basic")) { - return this.basicAuthFilter.getPrincipalsAndCredentials(scheme, token); - } - return super.getPrincipalsAndCredentials(scheme, token); - } - - @Override - protected boolean isLoginAttempt(String authzHeader) { - LOG.debug("isLoginAttempt with header {}", authzHeader); - if (this.basicAuthFilter.isLoginAttempt(authzHeader)) { - return true; - } - return super.isLoginAttempt(authzHeader); - } - - @Override - protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { - final HttpServletRequest httpRequest = WebUtils.toHttp(request); - final String httpMethod = httpRequest.getMethod(); - if (OPTIONS_HEADER.equalsIgnoreCase(httpMethod)) { - return true; - } else { - if (this.basicAuthFilter.isAccessAllowed(httpRequest, response, mappedValue)) { - LOG.debug("isAccessAllowed succeeded on basicAuth"); - return true; - } - } - return super.isAccessAllowed(request, response, mappedValue); - } - - protected AuthenticationToken createBasicAuthToken(ServletRequest request, ServletResponse response) { - String authorizationHeader = getAuthzHeader(request); - if (authorizationHeader == null || authorizationHeader.length() == 0) { - // Create an empty authentication token since there is no - // Authorization header. - return createToken("", "", request, response); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("Attempting to execute login with headers [" + authorizationHeader + "]"); - } - - String[] prinCred = getPrincipalsAndCredentials(authorizationHeader, request); - if (prinCred == null || prinCred.length < 2) { - // Create an authentication token with an empty password, - // since one hasn't been provided in the request. - String username = prinCred == null || prinCred.length == 0 ? "" : prinCred[0]; - return createToken(username, "", request, response); - } - - String username = prinCred[0]; - String password = prinCred[1]; - - return createToken(username, password, request, response); - } - - - private static class ODLHttpAuthenticationHelperFilter extends ODLHttpAuthenticationFilter{ - - ODLHttpAuthenticationHelperFilter(){ - super(); - } - - @Override - protected boolean isLoginAttempt(String authzHeader) { - return super.isLoginAttempt(authzHeader); - } - @Override - protected String[] getPrincipalsAndCredentials(String scheme, String encoded) { - return super.getPrincipalsAndCredentials(scheme, encoded); - } - @Override - protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { - return super.isAccessAllowed(request, response, mappedValue); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java deleted file mode 100644 index 26cdbe773..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/filters/CustomizedMDSALDynamicAuthorizationFilter.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters; - -import com.google.common.collect.Iterables; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import org.apache.shiro.subject.Subject; -import org.apache.shiro.web.filter.authz.AuthorizationFilter; -import org.opendaylight.mdsal.binding.api.*; -import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.HttpAuthorization; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.policies.Policies; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.Filter; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.ExecutionException; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Objects.requireNonNull; - -public class CustomizedMDSALDynamicAuthorizationFilter extends AuthorizationFilter - implements ClusteredDataTreeChangeListener { - - private static final Logger LOG = LoggerFactory.getLogger(CustomizedMDSALDynamicAuthorizationFilter.class); - - private static final DataTreeIdentifier AUTHZ_CONTAINER = DataTreeIdentifier.create( - LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(HttpAuthorization.class)); - - private final DataBroker dataBroker; - - private ListenerRegistration reg; - private volatile ListenableFuture> authContainer; - private static final ThreadLocal DATABROKER_TL = new ThreadLocal<>(); - - public CustomizedMDSALDynamicAuthorizationFilter() { - dataBroker = requireNonNull(DATABROKER_TL.get()); - } - - @Override - public Filter processPathConfig(final String path, final String config) { - try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) { - authContainer = tx.read(AUTHZ_CONTAINER.getDatastoreType(), AUTHZ_CONTAINER.getRootIdentifier()); - } - this.reg = dataBroker.registerDataTreeChangeListener(AUTHZ_CONTAINER, this); - return super.processPathConfig(path, config); - } - - @Override - public void destroy() { - if (reg != null) { - reg.close(); - reg = null; - } - super.destroy(); - } - - @Override - public void onDataTreeChanged(final Collection> changes) { - final HttpAuthorization newVal = Iterables.getLast(changes).getRootNode().getDataAfter(); - LOG.debug("Updating authorization information to {}", newVal); - authContainer = Futures.immediateFuture(Optional.ofNullable(newVal)); - } - - @Override - public boolean isAccessAllowed(final ServletRequest request, final ServletResponse response, - final Object mappedValue) { - checkArgument(request instanceof HttpServletRequest, "Expected HttpServletRequest, received {}", request); - - - final boolean defaultReturnValue=false; - final Subject subject = getSubject(request, response); - final HttpServletRequest httpServletRequest = (HttpServletRequest)request; - final String requestURI = httpServletRequest.getRequestURI(); - LOG.debug("isAccessAllowed for user={} to requestURI={}", subject, requestURI); - - final Optional authorizationOptional; - try { - authorizationOptional = authContainer.get(); - } catch (ExecutionException | InterruptedException e) { - // Something went completely wrong trying to read the authz container. Deny access. - LOG.warn("MDSAL attempt to read Http Authz Container failed, disallowing access", e); - return false; - } - - if (!authorizationOptional.isPresent()) { - // The authorization container does not exist-- hence no authz rules are present - // Allow access. - LOG.debug("Authorization Container does not exist"); - return defaultReturnValue; - } - - final HttpAuthorization httpAuthorization = authorizationOptional.get(); - final var policies = httpAuthorization.getPolicies(); - List policiesList = policies != null ? policies.getPolicies() : null; - if (policiesList == null || policiesList.isEmpty()) { - // The authorization container exists, but no rules are present. Allow access. - LOG.debug("Exiting early since no authorization rules exist"); - sendError(response, 403, ""); - return defaultReturnValue; - } - - // Sort the Policies list based on index - policiesList = new ArrayList<>(policiesList); - policiesList.sort(Comparator.comparing(Policies::getIndex)); - - for (Policies policy : policiesList) { - final String resource = policy.getResource(); - final boolean pathsMatch = pathsMatch(resource, requestURI); - if (pathsMatch) { - LOG.debug("paths match for policy {} pattern={} and requestURI={}", policy.getIndex(), resource, requestURI); - final String method = httpServletRequest.getMethod(); - LOG.trace("method={}", method); - List permissions = policy.getPermissions(); - LOG.trace("perm={}", permissions); - if(permissions !=null) { - for (Permissions permission : permissions) { - final String role = permission.getRole(); - LOG.trace("role={}", role); - Set actions = permission.getActions(); - if (actions != null) { - for (Permissions.Actions action : actions) { - LOG.trace("action={}", action.getName()); - if (action.getName().equalsIgnoreCase(method)) { - final boolean hasRole = subject.hasRole(role); - LOG.trace("hasRole({})={}", role, hasRole); - if (hasRole) { - return true; - } - } - } - } - else{ - LOG.trace("no actions found"); - } - } - } - else { - LOG.trace("no permissions found"); - } - LOG.debug("couldn't authorize the user for access"); - sendError(response, 403, ""); - return false; - } - } - LOG.debug("no path found that matches {}", requestURI); - sendError(response, 403, ""); - return defaultReturnValue; - } - - private void sendError(ServletResponse response, int code, String message) { - if(response instanceof HttpServletResponse){ - try { - ((HttpServletResponse)response).sendError(code, message); - } catch (IOException e) { - LOG.warn("unable to send {} {} response: ", code, message, e); - } - } - else{ - LOG.warn("unable to send {} {} response", code, message); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java deleted file mode 100644 index 338da179a..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java +++ /dev/null @@ -1,507 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.ShiroException; -import org.apache.shiro.authc.BearerToken; -import org.apache.shiro.codec.Base64; -import org.apache.shiro.session.Session; -import org.apache.shiro.subject.Subject; -import org.jolokia.osgi.security.Authenticator; -import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.NoDefinitionFoundException; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthToken; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService.PublicOAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.MdSalAuthorizationStore; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.OAuthProviderFactory; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; -import org.opendaylight.aaa.api.IdMService; -import org.opendaylight.mdsal.binding.api.DataBroker; -import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration; -import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.shiro.ini.Main; -import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.shiro.ini.Urls; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AuthHttpServlet extends HttpServlet { - - private static final Logger LOG = LoggerFactory.getLogger(AuthHttpServlet.class.getName()); - private static final long serialVersionUID = 1L; - public static final String BASEURI = "/oauth"; - private static final String LOGINURI = BASEURI + "/login"; - private static final String LOGOUTURI = BASEURI + "/logout"; - private static final String PROVIDERSURI = BASEURI + "/providers"; - public static final String REDIRECTURI = BASEURI + "/redirect"; - private static final String REDIRECTURI_FORMAT = REDIRECTURI + "/%s"; - private static final String POLICIESURI = BASEURI + "/policies"; - private static final String REDIRECTID_REGEX = "^\\" + BASEURI + "\\/redirect\\/([^\\/]+)$"; - private static final String LOGIN_REDIRECT_REGEX = "^\\" + LOGINURI + "\\/([^\\/]+)$"; - private static final Pattern REDIRECTID_PATTERN = Pattern.compile(REDIRECTID_REGEX); - private static final Pattern LOGIN_REDIRECT_PATTERN = Pattern.compile(LOGIN_REDIRECT_REGEX); - - private static final String DEFAULT_DOMAIN = "sdn"; - private static final String HEAEDER_AUTHORIZATION = "Authorization"; - - private static final String LOGOUT_REDIRECT_URL_PARAMETER = "redirect_uri"; - private static final String CLASSNAME_ODLBASICAUTH = - "org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter"; - private static final String CLASSNAME_ODLBEARERANDBASICAUTH = - "org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter2"; - private static final String CLASSNAME_ODLMDSALAUTH = - "org.opendaylight.aaa.shiro.realm.MDSALDynamicAuthorizationFilter"; - public static final String LOGIN_REDIRECT_FORMAT = LOGINURI + "/%s"; - - private final ObjectMapper mapper; - /* state <=> AuthProviderService> */ - private final Map providerStore; - private final TokenCreator tokenCreator; - private final Config config; - private static Authenticator odlAuthenticator; - private static IdMService odlIdentityService; - private static ShiroConfiguration shiroConfiguration; - private static MdSalAuthorizationStore mdsalAuthStore; - - public AuthHttpServlet() throws IllegalArgumentException, IOException, InvalidConfigurationException, - UnableToConfigureOAuthService { - this.config = Config.getInstance(); - this.tokenCreator = TokenCreator.getInstance(this.config); - this.mapper = new ObjectMapper(); - this.providerStore = new HashMap<>(); - for (OAuthProviderConfig pc : config.getProviders()) { - this.providerStore.put(pc.getId(), OAuthProviderFactory.create(pc.getType(), pc, - this.config.getRedirectUri(), TokenCreator.getInstance(this.config))); - } - } - - public void setOdlAuthenticator(Authenticator odlAuthenticator2) { - odlAuthenticator = odlAuthenticator2; - } - - public void setOdlIdentityService(IdMService odlIdentityService2) { - odlIdentityService = odlIdentityService2; - } - - public void setShiroConfiguration(ShiroConfiguration shiroConfiguration2) { - shiroConfiguration = shiroConfiguration2; - } - - public void setDataBroker(DataBroker dataBroker) { - mdsalAuthStore = new MdSalAuthorizationStore(dataBroker); - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - LOG.debug("GET request for {}", req.getRequestURI()); - getHost(req); - if (PROVIDERSURI.equals(req.getRequestURI())) { - this.sendResponse(resp, HttpServletResponse.SC_OK, getConfigs(this.providerStore.values())); - } else if (req.getRequestURI().startsWith(LOGINURI)) { - this.handleLoginRedirect(req, resp); - } else if (req.getRequestURI().equals(LOGOUTURI)) { - this.handleLogout(req, resp); - } else if (POLICIESURI.equals(req.getRequestURI())) { - this.sendResponse(resp, HttpServletResponse.SC_OK, this.getPoliciesForUser(req)); - } else if (req.getRequestURI().startsWith(REDIRECTURI)) { - this.handleRedirect(req, resp); - } else { - resp.sendError(HttpServletResponse.SC_NOT_FOUND); - } - - } - - private void handleLogout(HttpServletRequest req, HttpServletResponse resp) throws IOException { - final String bearerToken = this.tokenCreator.getBearerToken(req, true); - String redirectUrl = req.getParameter(LOGOUT_REDIRECT_URL_PARAMETER); - if (redirectUrl == null) { - redirectUrl = this.config.getPublicUrl(); - } - // if nothing configured and nothing from request - if(redirectUrl == null || redirectUrl.isBlank()){ - redirectUrl="/"; - } - UserTokenPayload userInfo = this.tokenCreator.decode(bearerToken); - if (bearerToken != null && userInfo != null && !userInfo.isInternal()) { - AuthService provider = this.providerStore.getOrDefault(userInfo.getProviderId(), null); - - if (provider != null) { - provider.sendLogoutRedirectResponse(bearerToken, resp, redirectUrl); - this.logout(); - return; - } - } - this.logout(); - resp.sendRedirect(redirectUrl); - - } - - private void handleLoginRedirect(HttpServletRequest req, HttpServletResponse resp) throws IOException { - final String uri = req.getRequestURI(); - final Matcher matcher = LOGIN_REDIRECT_PATTERN.matcher(uri); - if (matcher.find()) { - final String id = matcher.group(1); - AuthService provider = this.providerStore.getOrDefault(id, null); - if (provider != null) { - String redirectUrl = getHost(req) + String.format(REDIRECTURI_FORMAT, id); - provider.sendLoginRedirectResponse(resp, redirectUrl); - return; - } - } - this.sendResponse(resp, HttpServletResponse.SC_NOT_FOUND, ""); - } - - /** - * find out what urls can be accessed by user and which are forbidden - * - * urlEntries: "anon" -> any access allowed "authcXXX" -> no grouping rule -> any access for user allowed "authcXXX, - * roles[abc] -> user needs to have role abc "authcXXX, roles["abc,def"] -> user needs to have roles abc AND def - * "authcXXX, anyroles[abc] -> user needs to have role abc "authcXXX, anyroles["abc,def"] -> user needs to have - * roles abc OR def - * - * - * @param req - * @return - */ - private List getPoliciesForUser(HttpServletRequest req) { - List urlRules = shiroConfiguration.getUrls(); - UserTokenPayload data = this.getUserInfo(req); - List policies = new ArrayList<>(); - if (urlRules != null) { - LOG.debug("try to find rules for user {} with roles {}", - data == null ? "null" : data.getPreferredUsername(), data == null ? "null" : data.getRoles()); - final String regex = "^([^,]+)[,]?[\\ ]?([anyroles]+)?(\\[\"?([a-zA-Z,]+)\"?\\])?"; - final Pattern pattern = Pattern.compile(regex); - Matcher matcher; - for (Urls urlRule : urlRules) { - matcher = pattern.matcher(urlRule.getPairValue()); - if (matcher.find()) { - try { - final String authClass = getAuthClass(matcher.group(1)); - Optional policy = Optional.empty(); - //anon access allowed - if (authClass == null) { - policy = Optional.of(OdlPolicy.allowAll(urlRule.getPairKey())); - } else if (authClass.equals(CLASSNAME_ODLBASICAUTH)) { - policy = isBasic(req) ? this.getTokenBasedPolicy(urlRule, matcher, data) - : Optional.of(OdlPolicy.denyAll(urlRule.getPairKey())); - } else if (authClass.equals(CLASSNAME_ODLBEARERANDBASICAUTH)) { - policy = this.getTokenBasedPolicy(urlRule, matcher, data); - } else if (authClass.equals(CLASSNAME_ODLMDSALAUTH)) { - policy = this.getMdSalBasedPolicy(urlRule, data); - } - if (policy.isPresent()) { - policies.add(policy.get()); - } else { - LOG.warn("unable to get policy for authClass {} for entry {}", authClass, - urlRule.getPairValue()); - policies.add(OdlPolicy.denyAll(urlRule.getPairKey())); - } - } catch (NoDefinitionFoundException e) { - LOG.warn("unknown authClass: ", e); - } - - } else { - LOG.warn("unable to detect url role value: {}", urlRule.getPairValue()); - } - } - } else { - LOG.debug("no url rules found"); - } - return policies; - } - - /** - * extract policy rule for user from MD-SAL not yet supported - * - * @param urlRule - * @param data - * @return - */ - private Optional getMdSalBasedPolicy(Urls urlRule, UserTokenPayload data) { - if (mdsalAuthStore != null) { - return data != null ? mdsalAuthStore.getPolicy(urlRule.getPairKey(), data.getRoles()) - : Optional.of(OdlPolicy.denyAll(urlRule.getPairKey())); - } - return Optional.empty(); - } - - /** - * extract policy rule for user from url rules of config - * - * @param urlRule - * @param matcher - * @param data - * @return - */ - private Optional getTokenBasedPolicy(Urls urlRule, Matcher matcher, UserTokenPayload data) { - final String url = urlRule.getPairKey(); - final String rule = urlRule.getPairValue(); - if (!rule.contains(",")) { - LOG.debug("found rule without roles for '{}'", matcher.group(1)); - //not important if anon or authcXXX - if (data != null || "anon".equals(matcher.group(1))) { - return Optional.of(OdlPolicy.allowAll(url)); - } - } - if (data != null) { - LOG.debug("found rule with roles '{}'", matcher.group(4)); - if ("roles".equals(matcher.group(2))) { - if (this.rolesMatch(data.getRoles(), Arrays.asList(matcher.group(4).split(",")), false)) { - return Optional.of(OdlPolicy.allowAll(url)); - } else { - return Optional.of(OdlPolicy.denyAll(url)); - } - } else if ("anyroles".equals(matcher.group(2))) { - if (this.rolesMatch(data.getRoles(), Arrays.asList(matcher.group(4).split(",")), true)) { - return Optional.of(OdlPolicy.allowAll(url)); - } else { - return Optional.of(OdlPolicy.denyAll(url)); - } - } else { - LOG.warn("unable to detect url role value: {}", urlRule.getPairValue()); - } - } else { - return Optional.of(OdlPolicy.denyAll(url)); - } - return Optional.empty(); - } - - private String getAuthClass(String key) throws NoDefinitionFoundException { - if ("anon".equals(key)) { - return null; - } - List

list = shiroConfiguration.getMain(); - Optional
main = - list == null ? Optional.empty() : list.stream().filter(e -> e.getPairKey().equals(key)).findFirst(); - if (main.isPresent()) { - return main.get().getPairValue(); - } - throw new NoDefinitionFoundException("unable to find def for " + key); - } - - private UserTokenPayload getUserInfo(HttpServletRequest req) { - if (isBearer(req)) { - UserTokenPayload data = this.tokenCreator.decode(req); - if (data != null) { - return data; - } - } else if (isBasic(req)) { - String username = getBasicAuthUsername(req); - if (username != null) { - final String domain = getBasicAuthDomain(username); - if (!username.contains("@")) { - username = String.format("%s@%s", username, domain); - } - List roles = odlIdentityService.listRoles(username, domain); - return UserTokenPayload.createInternal(username, roles); - } - } - return null; - } - - private static String getBasicAuthDomain(String username) { - if (username.contains("@")) { - return username.split("@")[1]; - } - return DEFAULT_DOMAIN; - } - - private static String getBasicAuthUsername(HttpServletRequest req) { - final String header = req.getHeader(HEAEDER_AUTHORIZATION); - final String decoded = Base64.decodeToString(header.substring(6)); - // attempt to decode username/password; otherwise decode as token - if (decoded.contains(":")) { - return decoded.split(":")[0]; - } - LOG.warn("unable to detect username from basicauth header {}", header); - return null; - } - - private static boolean isBasic(HttpServletRequest req) { - final String header = req.getHeader(HEAEDER_AUTHORIZATION); - return header == null ? false : header.startsWith("Basic"); - } - - private static boolean isBearer(HttpServletRequest req) { - final String header = req.getHeader(HEAEDER_AUTHORIZATION); - return header == null ? false : header.startsWith("Bearer"); - } - - private boolean rolesMatch(List userRoles, List policyRoles, boolean any) { - if (any) { - for (String policyRole : policyRoles) { - if (userRoles.contains(policyRole)) { - return true; - } - } - return false; - } else { - for (String policyRole : policyRoles) { - if (!userRoles.contains(policyRole)) { - return false; - } - } - return true; - } - - } - - public String getHost(HttpServletRequest req) { - String hostUrl = this.config.getPublicUrl(); - if (hostUrl == null) { - final String tmp = req.getRequestURL().toString(); - final String regex = "^(http[s]{0,1}:\\/\\/[^\\/]+)"; - final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); - final Matcher matcher = pattern.matcher(tmp); - if (matcher.find()) { - hostUrl = matcher.group(1); - } - } - LOG.debug("host={}", hostUrl); - return hostUrl; - - } - - private List getConfigs(Collection values) { - List configs = new ArrayList<>(); - for (AuthService svc : values) { - configs.add(svc.getConfig()); - } - return configs; - } - - /** - * GET /oauth/redirect/{providerID} - * - * @param req - * @param resp - * @throws IOException - */ - private void handleRedirect(HttpServletRequest req, HttpServletResponse resp) throws IOException { - final String uri = req.getRequestURI(); - final Matcher matcher = REDIRECTID_PATTERN.matcher(uri); - if (matcher.find()) { - AuthService provider = this.providerStore.getOrDefault(matcher.group(1), null); - if (provider != null) { - //provider.setLocalHostUrl(getHost(req)); - provider.handleRedirect(req, resp, getHost(req)); - return; - } - } - resp.sendError(HttpServletResponse.SC_FORBIDDEN); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - - LOG.debug("POST request for {}", req.getRequestURI()); - if (this.config.loginActive() && this.config.doSupportOdlUsers() && LOGINURI.equals(req.getRequestURI())) { - final String username = req.getParameter("username"); - final String domain = req.getParameter("domain"); - BearerToken token = - this.doLogin(username, req.getParameter("password"), domain != null ? domain : DEFAULT_DOMAIN); - if (token != null) { - sendResponse(resp, HttpServletResponse.SC_OK, new OAuthToken(token)); - LOG.debug("login for odluser {} succeeded", username); - return; - } else { - LOG.debug("login failed"); - } - - } - resp.sendError(HttpServletResponse.SC_NOT_FOUND); - } - - private BearerToken doLogin(String username, String password, String domain) { - if (!username.contains("@")) { - username = String.format("%s@%s", username, domain); - } - HttpServletRequest req = new HeadersOnlyHttpServletRequest( - Map.of("Authorization", BaseHTTPClient.getAuthorizationHeaderValue(username, password))); - if (odlAuthenticator.authenticate(req)) { - List roles = odlIdentityService.listRoles(username, domain); - UserTokenPayload data = new UserTokenPayload(); - data.setPreferredUsername(username); - data.setFamilyName(""); - data.setGivenName(username); - data.setIat(this.tokenCreator.getDefaultIat()); - data.setExp(this.tokenCreator.getDefaultExp()); - data.setRoles(roles); - return this.tokenCreator.createNewJWT(data); - - } - return null; - } - - - private void sendResponse(HttpServletResponse resp, int code) throws IOException { - this.sendResponse(resp, code, null); - } - - private void sendResponse(HttpServletResponse resp, int code, Object data) throws IOException { - byte[] output = data != null ? mapper.writeValueAsString(data).getBytes() : new byte[0]; - // output - resp.setStatus(code); - resp.setContentLength(output.length); - resp.setContentType("application/json"); - ServletOutputStream os = null; - os = resp.getOutputStream(); - os.write(output); - - } - - private void logout() { - final Subject subject = SecurityUtils.getSubject(); - try { - subject.logout(); - Session session = subject.getSession(false); - if (session != null) { - session.stop(); - } - } catch (ShiroException e) { - LOG.debug("Couldn't log out {}", subject, e); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java deleted file mode 100644 index 31b6d696f..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.Principal; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Locale; -import java.util.Map; -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; - -public class HeadersOnlyHttpServletRequest implements HttpServletRequest{ - - private final Map headers; - - public HeadersOnlyHttpServletRequest(Map headers) { - this.headers = headers; - } - @Override - public Object getAttribute(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Enumeration getAttributeNames() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getCharacterEncoding() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setCharacterEncoding(String env) throws UnsupportedEncodingException { - // TODO Auto-generated method stub - - } - - @Override - public int getContentLength() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public long getContentLengthLong() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getContentType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public ServletInputStream getInputStream() throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getParameter(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Enumeration getParameterNames() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getParameterValues(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getParameterMap() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getProtocol() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getScheme() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getServerName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getServerPort() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public BufferedReader getReader() throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRemoteAddr() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRemoteHost() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setAttribute(String name, Object o) { - // TODO Auto-generated method stub - - } - - @Override - public void removeAttribute(String name) { - // TODO Auto-generated method stub - - } - - @Override - public Locale getLocale() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Enumeration getLocales() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isSecure() { - // TODO Auto-generated method stub - return false; - } - - @Override - public RequestDispatcher getRequestDispatcher(String path) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRealPath(String path) { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getRemotePort() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getLocalName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLocalAddr() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getLocalPort() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public ServletContext getServletContext() { - // TODO Auto-generated method stub - return null; - } - - @Override - public AsyncContext startAsync() throws IllegalStateException { - // TODO Auto-generated method stub - return null; - } - - @Override - public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) - throws IllegalStateException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isAsyncStarted() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isAsyncSupported() { - // TODO Auto-generated method stub - return false; - } - - @Override - public AsyncContext getAsyncContext() { - // TODO Auto-generated method stub - return null; - } - - @Override - public DispatcherType getDispatcherType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getAuthType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Cookie[] getCookies() { - // TODO Auto-generated method stub - return null; - } - - @Override - public long getDateHeader(String name) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getHeader(String name) { - return this.headers.getOrDefault(name,null); - } - - @Override - public Enumeration getHeaders(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Enumeration getHeaderNames() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getIntHeader(String name) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getMethod() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getPathInfo() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getPathTranslated() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getContextPath() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getQueryString() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRemoteUser() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isUserInRole(String role) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Principal getUserPrincipal() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRequestedSessionId() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRequestURI() { - // TODO Auto-generated method stub - return null; - } - - @Override - public StringBuffer getRequestURL() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getServletPath() { - // TODO Auto-generated method stub - return null; - } - - @Override - public HttpSession getSession(boolean create) { - // TODO Auto-generated method stub - return null; - } - - @Override - public HttpSession getSession() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String changeSessionId() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isRequestedSessionIdValid() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isRequestedSessionIdFromCookie() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isRequestedSessionIdFromURL() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isRequestedSessionIdFromUrl() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void login(String username, String password) throws ServletException { - // TODO Auto-generated method stub - - } - - @Override - public void logout() throws ServletException { - // TODO Auto-generated method stub - - } - - @Override - public Collection getParts() throws IOException, ServletException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Part getPart(String name) throws IOException, ServletException { - // TODO Auto-generated method stub - return null; - } - - @Override - public T upgrade(Class handlerClass) throws IOException, ServletException { - // TODO Auto-generated method stub - return null; - } - - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java deleted file mode 100644 index 6b1a8eddd..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPResponse; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.CustomObjectMapper; - -public class MappedBaseHttpResponse { - - - public static final int CODE404 = 404; - public static final int CODE200 = 200; - public static final MappedBaseHttpResponse UNKNOWN = new MappedBaseHttpResponse<>(-1, null); - private static final ObjectMapper mapper = new CustomObjectMapper(); - public final int code; - public final T body; - - public MappedBaseHttpResponse(int code, String body, Class clazz) - throws JsonMappingException, JsonProcessingException { - this(code, body != null ? mapper.readValue(body, clazz) : null); - } - - private MappedBaseHttpResponse(int code, T body) { - this.code = code; - this.body = body; - } - - public MappedBaseHttpResponse(BaseHTTPResponse response, Class clazz) - throws JsonMappingException, JsonProcessingException { - this(response.code, response.body, clazz); - } - - @Override - public String toString() { - return "BaseHTTPResponse [code=" + code + ", body=" + body + "]"; - } - - public boolean isSuccess() { - return this.code == CODE200; - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java deleted file mode 100644 index ca455dc72..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client; - -import java.io.IOException; -import java.util.Map; -import java.util.Optional; -import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MappingBaseHttpClient extends BaseHTTPClient { - - private static Logger LOG = LoggerFactory.getLogger(MappingBaseHttpClient.class); - - public MappingBaseHttpClient(String base, boolean trustAllCerts) { - super(base, trustAllCerts); - } - - public MappingBaseHttpClient(String host) { - super(host); - } - - public Optional> sendMappedRequest(String uri, String method, String body, - Map headers) { - return this.sendMappedRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers, String.class); - } - - public Optional> sendMappedRequest(String uri, String method, String body, - Map headers, Class clazz) { - return this.sendMappedRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers, clazz); - } - - protected Optional> sendMappedRequest(String uri, String method, byte[] body, - Map headers, Class clazz) { - try { - return Optional.of(new MappedBaseHttpResponse(this.sendRequest(uri, method, body, headers), clazz)); - } catch (IOException e) { - LOG.warn("problem during request for {}: ", uri, e); - } - return Optional.empty(); - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java deleted file mode 100644 index 2dc0b5746..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import com.auth0.jwt.JWT; -import com.auth0.jwt.exceptions.JWTDecodeException; -import com.auth0.jwt.interfaces.DecodedJWT; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.stream.Collectors; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.*; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappingBaseHttpClient; -import org.apache.shiro.authc.BearerToken; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AuthService { - - - private static final Logger LOG = LoggerFactory.getLogger(AuthService.class); - private final MappingBaseHttpClient httpClient; - protected final ObjectMapper mapper; - protected final OAuthProviderConfig config; - protected final TokenCreator tokenCreator; - private final String redirectUri; - private final String tokenEndpointRelative; - private final String authEndpointAbsolute; - private final String logoutEndpointAbsolute; - - private final Map logoutTokenMap; - protected abstract String getTokenVerifierUri(); - - protected abstract Map getAdditionalTokenVerifierParams(); - - protected abstract ResponseType getResponseType(); - - protected abstract boolean doSeperateRolesRequest(); - - protected abstract UserTokenPayload mapAccessToken(String spayload) - throws JsonMappingException, JsonProcessingException; - - protected abstract String getLoginUrl(String callbackUrl); - protected abstract String getLogoutUrl(); - - protected abstract UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at); - - protected abstract boolean verifyState(String state); - - public AuthService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - this.config = config; - this.tokenCreator = tokenCreator; - this.redirectUri = redirectUri; - this.mapper = new ObjectMapper(); - this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.httpClient = new MappingBaseHttpClient(this.config.getUrlOrInternal(), this.config.trustAll()); - this.logoutTokenMap = new HashMap<>(); - if (this.config.hasToBeConfigured()){ - Optional> oresponse = this.httpClient.sendMappedRequest( - this.config.getOpenIdConfigUrl(), "GET", null, null, OpenIdConfigResponseData.class); - if(oresponse.isEmpty()){ - throw new UnableToConfigureOAuthService(this.config.getOpenIdConfigUrl()); - } - MappedBaseHttpResponse response = oresponse.get(); - if(!response.isSuccess()){ - throw new UnableToConfigureOAuthService(this.config.getOpenIdConfigUrl(), response.code); - } - this.tokenEndpointRelative = trimUrl(this.config.getUrlOrInternal(),response.body.getToken_endpoint()); - this.authEndpointAbsolute = extendUrl(this.config.getUrlOrInternal(),response.body.getAuthorization_endpoint()); - this.logoutEndpointAbsolute = extendUrl(this.config.getUrlOrInternal(),response.body.getEnd_session_endpoint()); - } - else{ - this.tokenEndpointRelative = null; - this.authEndpointAbsolute = null; - this.logoutEndpointAbsolute = null; - } - } - - public static String trimUrl(String baseUrl, String endpoint) { - if(endpoint.startsWith(baseUrl)){ - return endpoint.substring(baseUrl.length()); - } - if(endpoint.startsWith("http")){ - return endpoint.substring(endpoint.indexOf("/",8)); - } - return endpoint; - } - public static String extendUrl(String baseUrl, String endpoint) { - if(endpoint.startsWith("http")){ - endpoint= endpoint.substring(endpoint.indexOf("/",8)); - } - if(baseUrl.endsWith("/")){ - baseUrl=baseUrl.substring(0,baseUrl.length()-2); - } - return baseUrl+endpoint; - } - - public PublicOAuthProviderConfig getConfig() { - return new PublicOAuthProviderConfig(this); - } - - protected MappingBaseHttpClient getHttpClient() { - return this.httpClient; - } - - public void handleRedirect(HttpServletRequest req, HttpServletResponse resp, String host) throws IOException { - switch (this.getResponseType()) { - case CODE: - this.handleRedirectCode(req, resp, host); - break; - case TOKEN: - sendErrorResponse(resp, "not yet implemented"); - break; - case SESSION_STATE: - break; - } - } - - public void sendLoginRedirectResponse(HttpServletResponse resp, String callbackUrl) { - resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); - String url = this.authEndpointAbsolute !=null?String.format( - "%s?client_id=%s&response_type=code&scope=%s&redirect_uri=%s", - this.authEndpointAbsolute, urlEncode(this.config.getClientId()), this.config.getScope(), - urlEncode(callbackUrl)):this.getLoginUrl(callbackUrl); - resp.setHeader("Location", url); - } - public void sendLogoutRedirectResponse(String token, HttpServletResponse resp, String redirectUrl) - throws IOException { - String idToken = this.logoutTokenMap.getOrDefault(token, null); - String logoutEndpoint = this.logoutEndpointAbsolute!=null?this.logoutEndpointAbsolute:this.getLogoutUrl(); - if(idToken==null) { - LOG.debug("unable to find token in map. Do unsafe logout."); - resp.sendRedirect(this.logoutEndpointAbsolute); - return; - } - LOG.debug("id token found. redirect to specific logout"); - resp.sendRedirect(String.format("%s?id_token_hint=%s&post_logout_redirect_uri=%s",logoutEndpoint, idToken, - urlEncode(redirectUrl))); - } - - - - private static void sendErrorResponse(HttpServletResponse resp, String message) throws IOException { - resp.sendError(HttpServletResponse.SC_NOT_FOUND, message); - } - - private void handleRedirectCode(HttpServletRequest req, HttpServletResponse resp, String host) throws IOException { - final String code = req.getParameter("code"); - final String state = req.getParameter("state"); - OAuthResponseData response = null; - if(this.verifyState(state)) { - response = this.getTokenForUser(code, host); - } - if (response != null) { - if (this.doSeperateRolesRequest()) { - LOG.debug("do a seperate role request"); - long expiresAt = this.tokenCreator.getDefaultExp(); - long issuedAt = this.tokenCreator.getDefaultIat(); - UserTokenPayload data = this.requestUserRoles(response.getAccess_token(), issuedAt, expiresAt); - if (data != null) { - BearerToken createdToken = this.handleUserInfoToken(data, resp, host); - this.logoutTokenMap.put(createdToken.getToken(),response.getId_token()); - } else { - sendErrorResponse(resp, "unable to verify user"); - } - } else { - BearerToken createdToken = this.handleUserInfoToken(response.getAccess_token(), resp, host); - this.logoutTokenMap.put(createdToken.getToken(),response.getId_token()); - } - } else { - sendErrorResponse(resp, "unable to verify code"); - } - } - - private BearerToken handleUserInfoToken(UserTokenPayload data, HttpServletResponse resp, String localHostUrl) - throws IOException { - BearerToken onapToken = this.tokenCreator.createNewJWT(data); - sendTokenResponse(resp, onapToken, localHostUrl); - return onapToken; - } - - private BearerToken handleUserInfoToken(String accessToken, HttpServletResponse resp, String localHostUrl) - throws IOException { - try { - DecodedJWT jwt = JWT.decode(accessToken); - String spayload = base64Decode(jwt.getPayload()); - LOG.debug("payload in jwt='{}'", spayload); - UserTokenPayload data = this.mapAccessToken(spayload); - return this.handleUserInfoToken(data, resp, localHostUrl); - } catch (JWTDecodeException | JsonProcessingException e) { - LOG.warn("unable to decode jwt token {}: ", accessToken, e); - sendErrorResponse(resp, e.getMessage()); - } - return null; - } - - - protected List mapRoles(List roles) { - final Map map = this.config.getRoleMapping(); - return roles.stream().map(r -> map.getOrDefault(r, r)).collect(Collectors.toList()); - } - - private void sendTokenResponse(HttpServletResponse resp, BearerToken data, String localHostUrl) throws IOException { - if (this.redirectUri == null) { - byte[] output = data != null ? mapper.writeValueAsString(data).getBytes() : new byte[0]; - resp.setStatus(200); - resp.setContentLength(output.length); - resp.setContentType("application/json"); - resp.addCookie(this.tokenCreator.createAuthCookie(data)); - ServletOutputStream os = null; - os = resp.getOutputStream(); - os.write(output); - } else { - resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); - resp.setHeader("Location", assembleUrl(localHostUrl, this.redirectUri, data.getToken())); - resp.addCookie(this.tokenCreator.createAuthCookie(data)); - } - } - - - - private static String base64Decode(String data) { - return new String(Base64.getDecoder().decode(data), StandardCharsets.UTF_8); - } - - private OAuthResponseData getTokenForUser(String code, String localHostUrl) { - - Map headers = new HashMap<>(); - headers.put("Content-Type", "application/x-www-form-urlencoded"); - headers.put("Accept", "application/json"); - Map params = this.getAdditionalTokenVerifierParams(); - params.put("code", code); - params.put("client_id", this.config.getClientId()); - params.put("client_secret", this.config.getSecret()); - params.put("redirect_uri", assembleRedirectUrl(localHostUrl, AuthHttpServlet.REDIRECTURI, this.config.getId())); - StringBuilder body = new StringBuilder(); - for (Entry p : params.entrySet()) { - body.append(String.format("%s=%s&", p.getKey(), urlEncode(p.getValue()))); - } - - String url = this.tokenEndpointRelative !=null?this.tokenEndpointRelative :this.getTokenVerifierUri(); - Optional> response = - this.httpClient.sendMappedRequest(url, "POST", - body.substring(0, body.length() - 1), headers, OAuthResponseData.class); - if (response.isPresent() && response.get().isSuccess()) { - return response.get().body; - } - LOG.warn("problem get token for code {}", code); - - return null; - } - - /** - * Assemble callback url for service provider {host}{baseUri}/{serviceId} e.g. - * http://10.20.0.11:8181/oauth/redirect/keycloak - * - * @param host - * @param baseUri - * @param serviceId - * @return - */ - public static String assembleRedirectUrl(String host, String baseUri, String serviceId) { - return String.format("%s%s/%s", host, baseUri, serviceId); - } - - private static String assembleUrl(String host, String uri, String token) { - return String.format("%s%s%s", host, uri, token); - } - - public static String urlEncode(String s) { - return URLEncoder.encode(s, StandardCharsets.UTF_8); - } - - - - public enum ResponseType { - CODE, TOKEN, SESSION_STATE - } - - - public static class PublicOAuthProviderConfig { - - private String id; - private String title; - private String loginUrl; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getLoginUrl() { - return loginUrl; - } - - public void setLoginUrl(String loginUrl) { - this.loginUrl = loginUrl; - } - - public PublicOAuthProviderConfig(AuthService authService) { - this.id = authService.config.getId(); - this.title = authService.config.getTitle(); - this.loginUrl = String.format(AuthHttpServlet.LOGIN_REDIRECT_FORMAT, authService.config.getId()); - } - - } - - - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java deleted file mode 100644 index fc6869751..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/GitlabProviderService.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class GitlabProviderService extends AuthService { - - private static final Logger LOG = LoggerFactory.getLogger(GitlabProviderService.class); - private Map additionalTokenVerifierParams; - protected final List randomIds; - private static final String API_USER_URI = "/api/v4/user"; - private static final String API_GROUP_URI = "/api/v4/groups?min_access_level=10"; - - public GitlabProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - super(config, redirectUri, tokenCreator); - this.additionalTokenVerifierParams = new HashMap<>(); - this.additionalTokenVerifierParams.put("grant_type", "authorization_code"); - this.randomIds = new ArrayList<>(); - } - - @Override - protected String getTokenVerifierUri() { - return "/oauth/token"; - } - - @Override - protected String getLoginUrl(String callbackUrl) { - return String.format("%s/oauth/authorize?client_id=%s&response_type=code&state=%s&redirect_uri=%s", - this.config.getUrl(), urlEncode(this.config.getClientId()), this.createRandomId(), callbackUrl); - } - - @Override - protected String getLogoutUrl() { - return String.format("%s/oauth/logout", this.config.getUrl()); - } - - private String createRandomId() { - String rnd = null; - while(true) { - rnd=Config.generateSecret(20); - if(!this.randomIds.contains(rnd)) { - break; - } - } - this.randomIds.add(rnd); - return rnd; - } - - @Override - protected ResponseType getResponseType() { - return ResponseType.CODE; - } - - @Override - protected Map getAdditionalTokenVerifierParams() { - return this.additionalTokenVerifierParams; - - } - - @Override - protected boolean doSeperateRolesRequest() { - return true; - } - - @Override - protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException { - return null; - } - - @Override - protected UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at) { - LOG.debug("reqesting user roles with token={}", access_token); - Map authHeaders = new HashMap<>(); - authHeaders.put("Authorization", String.format("Bearer %s", access_token)); - Optional> userInfo = - this.getHttpClient().sendMappedRequest(API_USER_URI, "GET", null, authHeaders, GitlabUserInfo.class); - if (userInfo.isEmpty()) { - LOG.warn("unable to read user data"); - return null; - } - Optional> groupInfos = this.getHttpClient() - .sendMappedRequest(API_GROUP_URI, "GET", null, authHeaders, GitlabGroupInfo[].class); - if (groupInfos.isEmpty()) { - LOG.warn("unable to read group information for user"); - return null; - } - UserTokenPayload data = new UserTokenPayload(); - GitlabUserInfo uInfo = userInfo.get().body; - data.setPreferredUsername(uInfo.getUsername()); - data.setGivenName(uInfo.getName()); - data.setFamilyName(uInfo.getName()); - data.setIat(issued_at); - data.setExp(expires_at); - List roles = new ArrayList<>(); - GitlabGroupInfo[] uRoles = groupInfos.get().body; - for (GitlabGroupInfo uRole : uRoles) { - roles.add(uRole.getName()); - } - data.setRoles(this.mapRoles(roles)); - return data; - } - - - - @SuppressWarnings("unused") - private static class GitlabUserInfo { - - private String username; - private String name; - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - @SuppressWarnings("unused") - private static class GitlabGroupInfo { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - @Override - protected boolean verifyState(String state) { - if(this.randomIds.contains(state)) { - this.randomIds.remove(state); - return true; - } - return false; - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java deleted file mode 100644 index bdbf9286a..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.KeycloakUserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; - -public class KeycloakProviderService extends AuthService { - - public static final String ID = "keycloak"; - private Map additionalTokenVerifierParams; - - public KeycloakProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - super(config, redirectUri, tokenCreator); - this.additionalTokenVerifierParams = new HashMap<>(); - this.additionalTokenVerifierParams.put("grant_type", "authorization_code"); - } - - @Override - protected String getTokenVerifierUri() { - return String.format("/auth/realms/%s/protocol/openid-connect/token", urlEncode(this.config.getRealmName())); - } - - @Override - protected String getLoginUrl(String callbackUrl) { - return String.format( - "%s/auth/realms/%s/protocol/openid-connect/auth?client_id=%s&response_type=code&scope=%s&redirect_uri=%s", - this.config.getUrl(), urlEncode(this.config.getRealmName()), urlEncode(this.config.getClientId()), - this.config.getScope(), urlEncode(callbackUrl)); - } - - @Override - protected String getLogoutUrl() { - return String.format("%s/auth/realms/%s/protocol/openid-connect/logout", this.config.getUrl(), - urlEncode(this.config.getRealmName())); - } - - @Override - protected List mapRoles(List data) { - final Map map = this.config.getRoleMapping(); - List filteredRoles = - data.stream().filter(role -> !role.equals("uma_authorization") && !role.equals("offline_access")) - .map(r -> map.getOrDefault(r, r)).collect(Collectors.toList()); - return filteredRoles; - } - - @Override - protected ResponseType getResponseType() { - return ResponseType.CODE; - } - - @Override - protected Map getAdditionalTokenVerifierParams() { - return this.additionalTokenVerifierParams; - - } - - @Override - protected boolean doSeperateRolesRequest() { - return false; - } - - @Override - protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException { - KeycloakUserTokenPayload payload = mapper.readValue(spayload, KeycloakUserTokenPayload.class); - UserTokenPayload data = new UserTokenPayload(); - data.setIat(payload.getIat() * 1000L); - data.setExp(payload.getExp() * 1000L); - data.setFamilyName(payload.getFamilyName()); - data.setGivenName(payload.getGivenName()); - data.setProviderId(this.config.getId()); - data.setPreferredUsername(payload.getPreferredUsername()); - data.setRoles(this.mapRoles(payload.getRealmAccess().getRoles())); - return data; - } - - @Override - protected UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at) { - return null; - } - - @Override - protected boolean verifyState(String state) { - return true; - } - - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java deleted file mode 100644 index 4bf35e72d..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/MdSalAuthorizationStore.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy.PolicyMethods; -import org.opendaylight.mdsal.binding.api.DataBroker; -import org.opendaylight.mdsal.binding.api.ReadTransaction; -import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.HttpAuthorization; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.Policies; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions.Actions; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MdSalAuthorizationStore { - - private static final Logger LOG = LoggerFactory.getLogger(MdSalAuthorizationStore.class.getName()); - - private final DataBroker dataBroker; - - public MdSalAuthorizationStore(DataBroker dataBroker) { - this.dataBroker = dataBroker; - } - - public Optional getPolicy(String path, List userRoles) { - InstanceIdentifier iif = InstanceIdentifier.create(HttpAuthorization.class).child(Policies.class); - Optional odata = Optional.empty(); - // The implicite close is not handled correctly by underlaying opendaylight netconf service - ReadTransaction transaction = this.dataBroker.newReadOnlyTransaction(); - try { - odata = transaction.read(LogicalDatastoreType.CONFIGURATION, iif).get(); - } catch (ExecutionException e) { - LOG.warn("unable to read policies from mdsal: ", e); - } catch (InterruptedException e) { - LOG.warn("Interrupted!", e); - // Restore interrupted state... - Thread.currentThread().interrupt(); - } - if (odata.isEmpty()) { - return Optional.empty(); - } - List data = - odata.get().getPolicies(); - if (data == null) { - return Optional.empty(); - } - Optional entry = - data.stream().filter(e -> path.equals(e.getResource())).findFirst(); - if (entry.isEmpty()) { - return Optional.empty(); - } - List permissions = entry.get().getPermissions(); - if (permissions == null) { - return Optional.empty(); - } - Optional rolePm = permissions.stream().filter((e) -> userRoles.contains(e.getRole())).findFirst(); - if (rolePm.isEmpty()) { - return Optional.empty(); - } - return Optional.of(mapPolicy(path, rolePm.get().getActions())); - } - - private OdlPolicy mapPolicy(String path, Set actions) { - PolicyMethods methods = new PolicyMethods(); - String action; - for (Actions a : actions) { - action = a.getName().toLowerCase(); - switch (action) { - case "get": - methods.setGet(true); - break; - case "post": - methods.setPost(true); - break; - case "put": - methods.setPut(true); - break; - case "delete": - methods.setDelete(true); - break; - case "patch": - methods.setPatch(true); - break; - default: - LOG.warn("unknown http method {}", action); - break; - } - } - return new OdlPolicy(path, methods); - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java deleted file mode 100644 index 73bae5d4c..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import java.util.Map; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; - -public class NextcloudProviderService extends AuthService { - - public NextcloudProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - super(config, redirectUri, tokenCreator); - // TODO Auto-generated constructor stub - } - - @Override - protected String getTokenVerifierUri() { - // TODO Auto-generated method stub - return null; - } - - @Override - protected Map getAdditionalTokenVerifierParams() { - // TODO Auto-generated method stub - return null; - } - - @Override - protected ResponseType getResponseType() { - // TODO Auto-generated method stub - return ResponseType.TOKEN; - } - - @Override - protected boolean doSeperateRolesRequest() { - // TODO Auto-generated method stub - return false; - } - - @Override - protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException { - // TODO Auto-generated method stub - return null; - } - - @Override - protected String getLoginUrl(String callbackUrl) { - // TODO Auto-generated method stub - return null; - } - - @Override - protected String getLogoutUrl() { - return null; - } - - @Override - protected UserTokenPayload requestUserRoles(String access_token, long issued_at, long expires_at) { - // TODO Auto-generated method stub - return null; - } - - @Override - protected boolean verifyState(String state) { - // TODO Auto-generated method stub - return false; - } - -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java deleted file mode 100644 index 152569930..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; - -public class OAuthProviderFactory { - - - public static AuthService create(OAuthProvider key, OAuthProviderConfig config, String redirectUri, - TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - switch (key) { - case KEYCLOAK: - return new KeycloakProviderService(config, redirectUri, tokenCreator); - case NEXTCLOUD: - return new NextcloudProviderService(config, redirectUri, tokenCreator); - case GITLAB: - return new GitlabProviderService(config, redirectUri, tokenCreator); - } - return null; - } - - public static enum OAuthProvider { - KEYCLOAK, NEXTCLOUD, GITLAB - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java deleted file mode 100644 index fac46f6b1..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/PemUtils.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.EncodedKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import org.bouncycastle.util.io.pem.PemObject; -import org.bouncycastle.util.io.pem.PemReader; - -public class PemUtils { - - private static byte[] parsePEMFile(File pemFile) throws IOException { - if (!pemFile.isFile() || !pemFile.exists()) { - throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath())); - } - return parsePEMFile(new FileReader(pemFile)); - } - private static byte[] parsePEMFile(Reader inputReader) throws IOException { - PemReader reader = new PemReader(inputReader); - PemObject pemObject = reader.readPemObject(); - byte[] content = pemObject.getContent(); - reader.close(); - return content; - } - private static PublicKey getPublicKey(byte[] keyBytes, String algorithm) { - PublicKey publicKey = null; - try { - KeyFactory kf = KeyFactory.getInstance(algorithm); - EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); - publicKey = kf.generatePublic(keySpec); - } catch (NoSuchAlgorithmException e) { - System.out.println("Could not reconstruct the public key, the given algorithm could not be found."); - } catch (InvalidKeySpecException e) { - System.out.println("Could not reconstruct the public key"); - } - - return publicKey; - } - - private static PrivateKey getPrivateKey(byte[] keyBytes, String algorithm) { - PrivateKey privateKey = null; - try { - KeyFactory kf = KeyFactory.getInstance(algorithm); - EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); - privateKey = kf.generatePrivate(keySpec); - } catch (NoSuchAlgorithmException e) { - System.out.println("Could not reconstruct the private key, the given algorithm could not be found."); - } catch (InvalidKeySpecException e) { - System.out.println("Could not reconstruct the private key"); - } - - return privateKey; - } - - public static PublicKey readPublicKeyFromFile(String filepath, String algorithm) throws IOException { - byte[] bytes = PemUtils.parsePEMFile(new File(filepath)); - return PemUtils.getPublicKey(bytes, algorithm); - } - - public static PublicKey readPublicKey(String filecontent, String algorithm) throws IOException { - byte[] bytes = PemUtils.parsePEMFile(new StringReader(filecontent)); - return PemUtils.getPublicKey(bytes, algorithm); - } - - public static PrivateKey readPrivateKeyFromFile(String filepath, String algorithm) throws IOException { - byte[] bytes = PemUtils.parsePEMFile(new File(filepath)); - return PemUtils.getPrivateKey(bytes, algorithm); - } - - public static PrivateKey readPrivateKey(String filecontent, String algorithm) throws IOException { - byte[] bytes = PemUtils.parsePEMFile(new StringReader(filecontent)); - return PemUtils.getPrivateKey(bytes, algorithm); - } - -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java deleted file mode 100644 index 028dff9dd..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/RSAKeyReader.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import java.io.IOException; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; - -public class RSAKeyReader { - - private static final String PREFIX_FILEURL = "file://"; - - public static RSAPrivateKey getPrivateKey(String filenameOrContent) throws IOException { - if (filenameOrContent.startsWith(PREFIX_FILEURL)) { - return (RSAPrivateKey) PemUtils.readPrivateKeyFromFile(filenameOrContent.substring(PREFIX_FILEURL.length()), - "RSA"); - } - return (RSAPrivateKey) PemUtils.readPrivateKey(filenameOrContent, "RSA"); - } - - public static RSAPublicKey getPublicKey(String filenameOrContent) throws IOException { - if (filenameOrContent.startsWith(PREFIX_FILEURL)) { - return (RSAPublicKey) PemUtils.readPublicKeyFromFile(filenameOrContent.substring(PREFIX_FILEURL.length()), - "RSA"); - } - return (RSAPublicKey) PemUtils.readPublicKey(filenameOrContent, "RSA"); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java deleted file mode 100644 index 436d47827..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers; - -import com.auth0.jwt.JWT; -import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.JWTDecodeException; -import com.auth0.jwt.exceptions.JWTVerificationException; -import com.auth0.jwt.interfaces.DecodedJWT; -import com.auth0.jwt.interfaces.JWTVerifier; -import java.io.IOException; -import java.security.Security; -import java.util.Arrays; -import java.util.Date; -import java.util.Optional; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; -import org.apache.shiro.authc.BearerToken; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TokenCreator { - - private static final Logger LOG = LoggerFactory.getLogger(AuthHttpServlet.class.getName()); - private final String issuer; - private static TokenCreator _instance; - private final long tokenLifetimeSeconds; - private final Algorithm algorithm; - - private static final String ROLES_CLAIM = "roles"; - private static final String FAMILYNAME_CLAIM = "family_name"; - private static final String NAME_CLAIM = "name"; - private static final String PROVIDERID_CLAIM = "provider_id"; - private static final String COOKIE_NAME_AUTH = "token"; - - static { - Security.addProvider( - new BouncyCastleProvider() - ); - } - public static TokenCreator getInstance(Config config) throws IllegalArgumentException, IOException { - if (_instance == null) { - _instance = new TokenCreator(config); - } - return _instance; - } - - public static TokenCreator getInstance(String alg, String secret, String issuer, long tokenLifetime) - throws IllegalArgumentException, IOException { - return getInstance(alg, secret, null, issuer, tokenLifetime); - } - - public static TokenCreator getInstance(String alg, String secret, String pubkey, String issuer, long tokenLifetime) - throws IllegalArgumentException, IOException { - if (_instance == null) { - _instance = new TokenCreator(alg, secret, pubkey, issuer, tokenLifetime); - } - return _instance; - } - - private TokenCreator(Config config) throws IllegalArgumentException, IOException { - this(config.getAlgorithm(), config.getTokenSecret(), config.getPublicKey(), config.getTokenIssuer(), - config.getTokenLifetime()); - } - - private TokenCreator(String alg, String secret, String pubkey, String issuer, long tokenLifetime) - throws IllegalArgumentException, IOException { - this.issuer = issuer; - this.tokenLifetimeSeconds = tokenLifetime; - this.algorithm = this.createAlgorithm(alg, secret, pubkey); - } - - private Algorithm createAlgorithm(String alg, String secret, String pubkey) - throws IllegalArgumentException, IOException { - if (alg == null) { - alg = Config.TOKENALG_HS256; - } - switch (alg) { - case Config.TOKENALG_HS256: - return Algorithm.HMAC256(secret); - case Config.TOKENALG_RS256: - return Algorithm.RSA256(RSAKeyReader.getPublicKey(pubkey), RSAKeyReader.getPrivateKey(secret)); - case Config.TOKENALG_RS512: - return Algorithm.RSA512(RSAKeyReader.getPublicKey(pubkey), RSAKeyReader.getPrivateKey(secret)); - case Config.TOKENALG_CLIENT_RS256: - return Algorithm.RSA256(RSAKeyReader.getPublicKey(pubkey), null); - case Config.TOKENALG_CLIENT_RS512: - return Algorithm.RSA512(RSAKeyReader.getPublicKey(pubkey), null); - } - throw new IllegalArgumentException(String.format("unable to find algorithm for %s", alg)); - - } - - public BearerToken createNewJWT(UserTokenPayload data) { - final String token = JWT.create().withIssuer(issuer).withExpiresAt(new Date(data.getExp())) - .withIssuedAt(new Date(data.getIat())).withSubject(data.getPreferredUsername()) - .withClaim(NAME_CLAIM, data.getGivenName()).withClaim(FAMILYNAME_CLAIM, data.getFamilyName()) - .withClaim(PROVIDERID_CLAIM, data.getProviderId()) - .withArrayClaim(ROLES_CLAIM, data.getRoles().toArray(new String[data.getRoles().size()])) - .sign(this.algorithm); - LOG.trace("token created: {}", token); - return new BearerToken(token); - } - - public DecodedJWT verify(String token) { - DecodedJWT jwt = null; - LOG.debug("try to verify token {}", token); - try { - JWTVerifier verifier = JWT.require(this.algorithm).withIssuer(issuer).build(); - jwt = verifier.verify(token); - - } catch (JWTVerificationException e) { - LOG.warn("unable to verify token {}:", token, e); - } - return jwt; - } - - public long getDefaultExp() { - return new Date().getTime() + (this.tokenLifetimeSeconds * 1000); - } - - public long getDefaultExp(long expIn) { - return new Date().getTime() + expIn; - } - - public long getDefaultIat() { - return new Date().getTime(); - } - - public String getBearerToken(HttpServletRequest req) { - return this.getBearerToken(req, false); - } - - public String getBearerToken(HttpServletRequest req, boolean checkCookie) { - final String authHeader = req.getHeader("Authorization"); - if ((authHeader == null || !authHeader.startsWith("Bearer")) && checkCookie) { - if(req!=null) { - Cookie[] cookies = req.getCookies(); - Optional ocookie = Optional.empty(); - if (cookies != null) { - ocookie = Arrays.stream(cookies).filter(c -> c != null && COOKIE_NAME_AUTH.equals(c.getName())) - .findFirst(); - } - if (ocookie.isEmpty()) { - return null; - } - return ocookie.get().getValue(); - } - } - return authHeader.substring(7); - } - - public UserTokenPayload decode(HttpServletRequest req) throws JWTDecodeException { - final String token = this.getBearerToken(req); - return token != null ? this.decode(token) : null; - } - - public UserTokenPayload decode(String token) { - if (token == null) { - return null; - } - DecodedJWT jwt = JWT.decode(token); - UserTokenPayload data = new UserTokenPayload(); - data.setRoles(Arrays.asList(jwt.getClaim(ROLES_CLAIM).asArray(String.class))); - data.setExp(jwt.getExpiresAt().getTime()); - data.setFamilyName(jwt.getClaim(FAMILYNAME_CLAIM).asString()); - data.setGivenName(jwt.getClaim(NAME_CLAIM).asString()); - data.setPreferredUsername(jwt.getClaim(NAME_CLAIM).asString()); - data.setProviderId(jwt.getClaim(PROVIDERID_CLAIM).asString()); - return data; - } - - public Cookie createAuthCookie(BearerToken data) { - Cookie cookie = new Cookie(COOKIE_NAME_AUTH, data.getToken()); - cookie.setMaxAge((int) this.tokenLifetimeSeconds); - cookie.setPath("/"); - cookie.setHttpOnly(true); - cookie.setSecure(true); - return cookie; - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java deleted file mode 100644 index 7b4adefda..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestAuthHttpServlet.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.google.common.util.concurrent.FluentFuture; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.jolokia.osgi.security.Authenticator; -import org.json.JSONArray; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient; -import org.onap.ccsdk.features.sdnr.wt.common.test.ServletOutputStreamToByteArrayOutputStream; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.CustomObjectMapper; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.HeadersOnlyHttpServletRequest; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper.OdlJsonMapper; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper.OdlXmlMapper; -import org.opendaylight.aaa.api.IdMService; -import org.apache.shiro.authc.BearerToken; -import org.opendaylight.mdsal.binding.api.DataBroker; -import org.opendaylight.mdsal.binding.api.ReadTransaction; -import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration; -import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfigurationBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.HttpAuthorization; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.Policies; -import org.opendaylight.yangtools.util.concurrent.FluentFutures; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - - -public class TestAuthHttpServlet { - - private static final String TESTCONFIGFILE = TestConfig.TEST_CONFIG_FILENAME; - private static final String TESTSHIROCONFIGFILE = "src/test/resources/aaa-app-config.test.xml"; - private static final String MDSALDYNAUTHFILENAME = "src/test/resources/mdsalDynAuthData.json"; - private static TestServlet servlet; - private static DataBroker dataBroker = loadDynamicMdsalAuthDataBroker(); - private static Authenticator odlAuthenticator = mock(Authenticator.class); - private static IdMService odlIdentityService = mock(IdMService.class); - private static ShiroConfiguration shiroConfiguration = null; - private static TokenCreator tokenCreator; -// private static final HttpServletRequest authreq = new HeadersOnlyHttpServletRequest( -// Map.of("Authorization", BaseHTTPClient.getAuthorizationHeaderValue("admin@sdn", "admin"))); - - @BeforeClass - public static void init() throws IllegalArgumentException, Exception { - - try { - Config config = createConfigFile(); - tokenCreator = TokenCreator.getInstance(config); - servlet = new TestServlet(); - shiroConfiguration = loadShiroConfig(TESTSHIROCONFIGFILE); - } catch (IOException | InvalidConfigurationException e) { - fail(e.getMessage()); - } - servlet.setDataBroker(dataBroker); - servlet.setOdlAuthenticator(odlAuthenticator); - servlet.setOdlIdentityService(odlIdentityService); - servlet.setShiroConfiguration(shiroConfiguration); - } - - private static DataBroker loadDynamicMdsalAuthDataBroker() { - DataBroker dataBroker = mock(DataBroker.class); - ReadTransaction rotx = mock(ReadTransaction.class); - InstanceIdentifier iif = InstanceIdentifier.create(HttpAuthorization.class).child(Policies.class); - try { - when(rotx.read(LogicalDatastoreType.CONFIGURATION, iif)) - .thenReturn(loadDataBrokerFile(MDSALDYNAUTHFILENAME, Policies.class)); - } catch (IOException e) { - fail("problem init databroker read" + e.getMessage()); - } - when(dataBroker.newReadOnlyTransaction()).thenReturn(rotx); - return dataBroker; - } - - private static FluentFuture> loadDataBrokerFile(String fn, Class clazz) throws IOException { - return FluentFutures.immediateFluentFuture(Optional.ofNullable(readJson(new File(fn), clazz))); - } - - private static ShiroConfiguration loadShiroConfig(String filename) - throws JsonParseException, JsonMappingException, IOException { - OdlXmlMapper mapper = new OdlXmlMapper(); - return mapper.readValue(new File(filename), ShiroConfigurationBuilder.class).build(); - } - - private static Config createConfigFile() throws IOException, InvalidConfigurationException { - return Config.getInstance(TESTCONFIGFILE); - - } - - @Test - public void testValidLoginRedirect() { - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/login/keycloak"); - HttpServletResponse resp = mock(HttpServletResponse.class); - try { - servlet.doGet(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(302); - verify(resp).setHeader("Location", - "http://10.20.11.160:8080/auth/realms/onap/protocol/openid-connect/auth?client_id=odlux.app&response" - + "_type=code&scope=openid&redirect_uri=http%3A%2F%2Fnasp.diasf.de%2Foauth%2Fredirect%2Fkeycloak"); - } - - @Test - public void testInValidLoginRedirect() { - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/login/unknownproviderid"); - HttpServletResponse resp = mock(HttpServletResponse.class); - ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); - try { - when(resp.getOutputStream()).thenReturn(printOut); - servlet.doGet(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(404); - } - - @Test - public void testValidLogin() { - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/login"); - when(req.getParameter("username")).thenReturn("admin"); - when(req.getParameter("password")).thenReturn("admin"); - when(odlAuthenticator.authenticate(any(HeadersOnlyHttpServletRequest.class))).thenReturn(true); - HttpServletResponse resp = mock(HttpServletResponse.class); - ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); - try { - when(resp.getOutputStream()).thenReturn(printOut); - servlet.doPost(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(200); - } - - @Test - public void testGetProviders() { - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/providers"); - HttpServletResponse resp = mock(HttpServletResponse.class); - ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); - try { - when(resp.getOutputStream()).thenReturn(printOut); - servlet.doGet(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(200); - String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); - System.out.println(responseBody); - JSONArray a = new JSONArray(responseBody); - assertEquals(1, a.length()); - assertEquals("keycloak", a.getJSONObject(0).getString("id")); - assertEquals("OSNL Keycloak Provider", a.getJSONObject(0).getString("title")); - assertEquals("/oauth/login/keycloak", a.getJSONObject(0).getString("loginUrl")); - - } - - @Test - public void testPoliciesAnon() { - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/policies"); - HttpServletResponse resp = mock(HttpServletResponse.class); - ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); - try { - when(resp.getOutputStream()).thenReturn(printOut); - servlet.doGet(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(200); - String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); - System.out.println(responseBody); - OdlPolicy[] anonPolicies = null; - try { - anonPolicies = readJson(responseBody, OdlPolicy[].class); - } catch (JsonProcessingException e) { - fail("unable to read anon policies response"); - } - assertEquals(9, anonPolicies.length); - OdlPolicy pApidoc = find(anonPolicies, "/apidoc/**"); - assertNotNull(pApidoc); - assertAllEquals(false, pApidoc); - OdlPolicy pOauth = find(anonPolicies, "/oauth/**"); - assertNotNull(pOauth); - assertAllEquals(true, pOauth); - OdlPolicy pRestconf = find(anonPolicies, "/rests/**"); - assertNotNull(pRestconf); - assertAllEquals(false, pRestconf); - } - - @Test - public void testPoliciesBasicAuth() { - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/policies"); - when(req.getHeader("Authorization")).thenReturn(BaseHTTPClient.getAuthorizationHeaderValue("admin", "admin")); - when(odlIdentityService.listRoles("admin@sdn", "sdn")).thenReturn(Arrays.asList("admin")); - HttpServletResponse resp = mock(HttpServletResponse.class); - ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); - try { - when(resp.getOutputStream()).thenReturn(printOut); - servlet.doGet(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(200); - String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); - System.out.println(responseBody); - OdlPolicy[] anonPolicies = null; - try { - anonPolicies = readJson(responseBody, OdlPolicy[].class); - } catch (JsonProcessingException e) { - fail("unable to read anon policies response"); - } - assertEquals(9, anonPolicies.length); - OdlPolicy pApidoc = find(anonPolicies, "/apidoc/**"); - assertNotNull(pApidoc); - assertAllEquals(true, pApidoc); - OdlPolicy pOauth = find(anonPolicies, "/oauth/**"); - assertNotNull(pOauth); - assertAllEquals(true, pOauth); - OdlPolicy pRestconf = find(anonPolicies, "/rests/**"); - assertNotNull(pRestconf); - assertAllEquals(true, pRestconf); - } - - @Test - public void testPoliciesBearer() { - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/oauth/policies"); - String token = createToken("admin", Arrays.asList("admin", "provision")).getToken(); - when(req.getHeader("Authorization")).thenReturn(String.format("Bearer %s", token)); - HttpServletResponse resp = mock(HttpServletResponse.class); - ServletOutputStreamToByteArrayOutputStream printOut = new ServletOutputStreamToByteArrayOutputStream(); - try { - when(resp.getOutputStream()).thenReturn(printOut); - servlet.doGet(req, resp); - } catch (ServletException | IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(200); - String responseBody = printOut.getByteArrayOutputStream().toString(StandardCharsets.UTF_8); - System.out.println(responseBody); - OdlPolicy[] anonPolicies = null; - try { - anonPolicies = readJson(responseBody, OdlPolicy[].class); - } catch (JsonProcessingException e) { - fail("unable to read anon policies response"); - } - assertEquals(9, anonPolicies.length); - OdlPolicy pApidoc = find(anonPolicies, "/apidoc/**"); - assertNotNull(pApidoc); - assertAllEquals(false, pApidoc); - OdlPolicy pOauth = find(anonPolicies, "/oauth/**"); - assertNotNull(pOauth); - assertAllEquals(true, pOauth); - OdlPolicy pRestconf = find(anonPolicies, "/rests/**"); - assertNotNull(pRestconf); - assertAllEquals(true, pRestconf); - } - - private static BearerToken createToken(String username, List roles) { - UserTokenPayload data = new UserTokenPayload(); - data.setPreferredUsername(username); - data.setFamilyName(""); - data.setGivenName(username); - data.setExp(tokenCreator.getDefaultExp()); - data.setRoles(roles); - return tokenCreator.createNewJWT(data); - } - - private static void assertAllEquals(boolean b, OdlPolicy p) { - assertEquals(b, p.getMethods().isGet()); - assertEquals(b, p.getMethods().isPost()); - assertEquals(b, p.getMethods().isPut()); - assertEquals(b, p.getMethods().isDelete()); - assertEquals(b, p.getMethods().isPatch()); - } - - private static OdlPolicy find(OdlPolicy[] policies, String path) { - for (OdlPolicy p : policies) { - if (path.equals(p.getPath())) { - return p; - } - } - return null; - } - - private static T readJson(String data, Class clazz) throws JsonMappingException, JsonProcessingException { - CustomObjectMapper mapper = new CustomObjectMapper(); - return mapper.readValue(data, clazz); - } - - private static T readJson(File file, Class clazz) throws IOException { - OdlJsonMapper mapper = new OdlJsonMapper(); - return mapper.readValue(file, clazz); - } - - private static class TestServlet extends AuthHttpServlet { - - private static final long serialVersionUID = 1L; - - public TestServlet() throws IllegalArgumentException, Exception { - super(); - } - - @Override - public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doGet(req, resp); - } - - @Override - public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doPost(req, resp); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java deleted file mode 100644 index 80ae8cf95..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import java.io.IOException; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.InvalidConfigurationException; - -public class TestConfig { - - public static String TEST_CONFIG_FILENAME = "src/test/resources/test.config.json"; - public static String TEST_OOMCONFIG_FILENAME = "src/test/resources/oom.test.config.json"; - public static String TEST_RS256_FILENAME = "src/test/resources/test.configRS256.json"; - public static String TEST_RS256INVALID_FILENAME = "src/test/resources/test.configRS256-invalid.json"; - public static String TEST_RS512_FILENAME = "src/test/resources/test.configRS512.json"; - - - @Test - public void test() throws IOException, InvalidConfigurationException { - - Config config = Config.load(TEST_CONFIG_FILENAME); - System.out.println("config="+config); - assertEquals(60*60,config.getTokenLifetime()); - assertNotNull(config.getAlgorithm()); - assertNotNull(config.getTokenSecret()); - //assertNotNull(config.getPublicKey()); - assertEquals(Config.TOKENALG_HS256, config.getAlgorithm()); - } - @Test - public void testOom() throws IOException, InvalidConfigurationException { - - Config config = Config.load(TEST_OOMCONFIG_FILENAME); - System.out.println("config="+config); - assertEquals(30*60,config.getTokenLifetime()); - - } - @Test - public void testRS256() throws IOException, InvalidConfigurationException { - - Config config = Config.load(TEST_RS256_FILENAME); - System.out.println("config="+config); - assertEquals(60*60,config.getTokenLifetime()); - - } - @Test - public void testRS512() throws IOException, InvalidConfigurationException { - - Config config = Config.load(TEST_RS512_FILENAME); - System.out.println("config="+config); - assertEquals(60*60,config.getTokenLifetime()); - - } - @Test(expected = InvalidConfigurationException.class) - public void testRS256Invalid() throws IOException, InvalidConfigurationException { - - Config.load(TEST_RS256INVALID_FILENAME); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java deleted file mode 100644 index 421b61919..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPResponse; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.KeycloakUserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthResponseData; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse; - -public class TestDeserializer { - - @Test - public void test1() throws IOException { - final String token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTME" - + "RNIn0.eyJleHAiOjE2MTAzNjE2OTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiOWRhOThmMTYtOTEyOS00N2NmLTgzOGQtNWQzYmVkYzYyZTJjIiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJjYzcxZmMxZi1hZGQ0LTRhODYtYWU1ZS1jMzRkZjQwM2M3NzIiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.PUT4NzCM1ej3sNMMCkQa1NuQQwDgn19G-OnWL4NgLvZ3ocJUZ1Yfr9KAPkrJHaiK_HXQqwTA-Ma6Qn7BBMoXNdFjwu0k_HpqyUbBDilGN4wpkGiUeS1p5SW4T_hnWJtwCJ5BYkEvF6WaEbi7MFCbEVO9LVcUvsa-7St1WZ8V8RVfbWgjAu7ejlxe6RYUDMYzIKDj5F5y1-qCyoKzGIjt5ajcA9FWrexHifLJECKO8ZG08Wp7xQld1sYPOdde6XHMwiyNelTwd_EzCBgUw_8664rETGDVtyfuYchowo5Z6fmn4U87L6EGjEuxiAE8f3USy_jh6UF0LnvyTyq_9I" - + "M1VA"; - final String response = - "{\"access_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTME" - + "RNIn0.eyJleHAiOjE2MTAzNjE2OTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiOWRhOThmMTYtOTEyOS00N2NmLTgzOGQtNWQzYmVkYzYyZTJjIiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6I" - + "mFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJjYzcxZmMxZi1hZGQ0LTRhODYtYWU1ZS1jMzRkZjQwM2M3NzIiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.PUT4NzCM1ej3sNMMCkQa1NuQQwDgn19G-OnWL4NgLvZ3ocJUZ1Yfr9KAPkrJHaiK_HX" - + "QqwTA-Ma6Qn7BBMoXNdFjwu0k_HpqyUbBDilGN4wpkGiUeS1p5SW4T_hnWJtwCJ5BYkEvF6WaEbi7MFCbEVO9LVcUvsa-7St1WZ8V8RVfbWgjAu7ejlxe6RYUDMYzIKDj5F5y1-qCyoKzGIjt5ajcA9FWrexHifLJECKO8ZG08Wp7xQld1sYPOdde6XHMwiyNelTwd_EzCBgUw_8664rETGDVtyfuYchowo5Z6fmn4U87L6EGjEuxiAE8f3USy_jh6UF0LnvyTyq_9I" - + "M1VA\",\"expires_in\":300,\"refresh_expires_in\":1800,\"refresh_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1NzdiN2Q3MC00NzMwLTQ0MDMtODk4My04ZjJmYTg4M2U2M2EifQ.eyJleHAiOjE2MTAzNjMxOTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiMmNjMGY4YWYtNWY2OC00YmFhLWEyOTctNjMxMjk2YzhmY2" - + "U5IiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6Imh0dHA6Ly8xMC4yMC4xMS4xNjA6ODA4MC9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiIxODM4YzRmMi01ZmUzLTRmMGMtYjJkMi1kMzY0YjI3YTQ5OTciLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYWRtaW4tY2xpIiwic2Vzc2lvbl9zdGF0ZSI6I" - + "mNjNzFmYzFmLWFkZDQtNGE4Ni1hZTVlLWMzNGRmNDAzYzc3MiIsInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.qutqcFuQW-GzaCVNMfiYrbmHYD34GYwBqIbaQbJSY-g\",\"token_type\":\"bearer\",\"not-before-policy\":0,\"session_state\":\"cc71fc1f-add4-4a86-ae5e-c34df403c772\",\"scope\":\"email profile\"} "; - - BaseHTTPResponse res = new BaseHTTPResponse(200, response); - OAuthResponseData data = new MappedBaseHttpResponse<>(res,OAuthResponseData.class).body; - assertEquals(token,data.getAccess_token()); - - } - - @Test - public void testUserPayloadDeser() throws JsonMappingException, JsonProcessingException { - final String payload = "{\n" - + " \"exp\": 1610362593,\n" - + " \"iat\": 1610361393,\n" - + " \"jti\": \"09bd6f2c-5dba-44a0-bd76-cd0d440137d0\",\n" - + " \"iss\": \"http://10.20.11.160:8080/auth/realms/onap\",\n" - + " \"aud\": \"account\",\n" - + " \"sub\": \"446a24bc-d8a0-43dd-afa5-e56eed75deb8\",\n" - + " \"typ\": \"Bearer\",\n" - + " \"azp\": \"admin-cli\",\n" - + " \"session_state\": \"db2c96f4-cc9b-47e8-a83f-a01c50d656f2\",\n" - + " \"acr\": \"1\",\n" - + " \"realm_access\": {\n" - + " \"roles\": [\n" - + " \"provision\",\n" - + " \"offline_access\",\n" - + " \"uma_authorization\"\n" - + " ]\n" - + " },\n" - + " \"resource_access\": {\n" - + " \"account\": {\n" - + " \"roles\": [\n" - + " \"manage-account\",\n" - + " \"manage-account-links\",\n" - + " \"view-profile\"\n" - + " ]\n" - + " }\n" - + " },\n" - + " \"scope\": \"profile email\",\n" - + " \"email_verified\": false,\n" - + " \"name\": \"Luke Skywalker\",\n" - + " \"preferred_username\": \"luke.skywalker\",\n" - + " \"given_name\": \"Luke\",\n" - + " \"family_name\": \"Skywalker\",\n" - + " \"email\": \"luke.skywalker@sdnr.onap.org\"\n" - + "}"; - - ObjectMapper mapper = new ObjectMapper(); - KeycloakUserTokenPayload data = mapper.readValue(payload,KeycloakUserTokenPayload.class); - assertNotNull(data.getRealmAccess()); - assertEquals(3, data.getRealmAccess().getRoles().size()); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java deleted file mode 100644 index 6c2390ea0..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestGitlabAuthService.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.nio.file.Files; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.GitlabProviderService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; - -public class TestGitlabAuthService { - - private static HttpServer server; - private static ExecutorService httpThreadPool; - private static GitlabProviderServiceToTest oauthService; - private static final int PORT = randomPort(50000, 55000); - private static final String GITURL = String.format("http://127.0.0.1:%d", PORT); - private static final String OAUTH_SECRET = "oauthsecret"; - private static final String TOKENCREATOR_SECRET = "secret"; - private static final String REDIRECT_URI = "/odlux/token?"; - - @BeforeClass - public static void init() throws IllegalArgumentException, Exception { - - TokenCreator tokenCreator = TokenCreator.getInstance(Config.TOKENALG_HS256, TOKENCREATOR_SECRET, "issuer", 30*60); - OAuthProviderConfig config = new OAuthProviderConfig("git", GITURL, null, "odlux.app", OAUTH_SECRET, "openid", - "gitlab test", "", null, false); - oauthService = new GitlabProviderServiceToTest(config, REDIRECT_URI, tokenCreator); - try { - initGitlabTestWebserver(PORT, "/"); - } catch (IOException e) { - fail(e.getMessage()); - } - } - - @AfterClass - public static void close() { - stopTestWebserver(); - } - - @Test - public void test() { - HttpServletRequest req; - HttpServletResponse resp = null; - String host = "http://localhost:8412"; - final String state = "stateabc"; - try { - req = mock(HttpServletRequest.class); - resp = mock(HttpServletResponse.class); - when(req.getParameter("code")).thenReturn("abcdefg"); - when(req.getParameter("state")).thenReturn(state); - oauthService.addState(state); - oauthService.handleRedirect(req, resp, host); - } catch (IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(302); - //verify(resp).setHeader("Location",any(String.class)); - } - - public void test2() { - oauthService.sendLoginRedirectResponse(null, null); - } - - public static class GitlabProviderServiceToTest extends GitlabProviderService { - - public GitlabProviderServiceToTest(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - super(config, redirectUri, tokenCreator); - } - - public void addState(String state) { - this.randomIds.add(state); - } - } - - private static int randomPort(int min, int max) { - Random random = new Random(); - return random.nextInt(max + 1 - min) + min; - } - - public static void initGitlabTestWebserver(int port, String baseUri) throws IOException { - server = HttpServer.create(new InetSocketAddress("127.0.0.1", port), 0); - httpThreadPool = Executors.newFixedThreadPool(5); - server.setExecutor(httpThreadPool); - server.createContext(baseUri, new MyHandler()); - //server.createContext("/", new MyRootHandler()); - server.setExecutor(null); // creates a default executor - server.start(); - System.out.println("http server started"); - } - - public static void stopTestWebserver() { - if (server != null) { - server.stop(0); - httpThreadPool.shutdownNow(); - System.out.println("http server stopped"); - } - } - - private static String loadResourceFileContent(String filename) { - try { - return Files.readString(new File(filename).toPath()); - } catch (IOException e) { - fail(e.getMessage()); - } - return null; - } - - public static class MyHandler implements HttpHandler { - private static final String GITLAB_TOKEN_ENDPOINT = "/oauth/token"; - private static final String GITLAB_USER_ENDPOINT = "/api/v4/user"; - private static final String GITLAB_GROUP_ENDPOINT = "/api/v4/groups?min_access_level=10"; - private static final String GITLAB_TOKEN_RESPONSE = - loadResourceFileContent("src/test/resources/oauth/gitlab-token-response.json"); - private static final String GITLAB_USER_RESPONSE = - loadResourceFileContent("src/test/resources/oauth/gitlab-user-response.json"); - private static final String GITLAB_GROUP_RESPONSE = - loadResourceFileContent("src/test/resources/oauth/gitlab-groups-response.json"); - - @Override - public void handle(HttpExchange t) throws IOException { - final String method = t.getRequestMethod(); - final String uri = t.getRequestURI().toString(); - System.out.println(String.format("req received: %s %s", method, t.getRequestURI())); - OutputStream os = null; - try { - if (method.equals("GET")) { - if (uri.equals(GITLAB_USER_ENDPOINT)) { - t.sendResponseHeaders(200, GITLAB_USER_RESPONSE.length()); - os = t.getResponseBody(); - os.write(GITLAB_USER_RESPONSE.getBytes()); - } else if (uri.equals(GITLAB_GROUP_ENDPOINT)) { - t.sendResponseHeaders(200, GITLAB_GROUP_RESPONSE.length()); - os = t.getResponseBody(); - os.write(GITLAB_GROUP_RESPONSE.getBytes()); - } - } else if (method.equals("POST")) { - if (uri.equals(GITLAB_TOKEN_ENDPOINT)) { - t.sendResponseHeaders(200, GITLAB_TOKEN_RESPONSE.length()); - os = t.getResponseBody(); - os.write(GITLAB_TOKEN_RESPONSE.getBytes()); - } else { - t.sendResponseHeaders(404, 0); - } - } else { - t.sendResponseHeaders(404, 0); - } - System.out.println("req handled successful"); - - } catch (Exception e) { - System.out.println(e.getMessage()); - } finally { - if (os != null) { - os.close(); - } - } - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java deleted file mode 100644 index acc7c6b36..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestKeycloakAuthService.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.nio.file.Files; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UnableToConfigureOAuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.KeycloakProviderService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; - -public class TestKeycloakAuthService { - - private static HttpServer server; - private static ExecutorService httpThreadPool; - private static KeycloakProviderServiceToTest oauthService; - private static final int PORT = randomPort(50000, 55000); - private static final String KEYCLOAKURL = String.format("http://127.0.0.1:%d", PORT); - private static final String OAUTH_SECRET = "oauthsecret"; - private static final String TOKENCREATOR_SECRET = "secret"; - private static final String REDIRECT_URI = "/odlux/token?"; - - @BeforeClass - public static void init() throws IllegalArgumentException, Exception { - - TokenCreator tokenCreator = TokenCreator.getInstance(Config.TOKENALG_HS256, TOKENCREATOR_SECRET, "issuer", 30*60); - OAuthProviderConfig config = new OAuthProviderConfig("kc", KEYCLOAKURL, null, "odlux.app", OAUTH_SECRET, - "openid", "keycloak test", "onap",null, false); - oauthService = new KeycloakProviderServiceToTest(config, REDIRECT_URI, tokenCreator); - try { - initKeycloakTestWebserver(PORT, "/"); - } catch (IOException e) { - fail(e.getMessage()); - } - } - - @AfterClass - public static void close() { - stopTestWebserver(); - } - - @Test - public void test() { - HttpServletRequest req; - HttpServletResponse resp = null; - String host = "http://localhost:8412"; - final String state = "stateabc"; - try { - req = mock(HttpServletRequest.class); - resp = mock(HttpServletResponse.class); - when(req.getParameter("code")).thenReturn("abcdefg"); - when(req.getParameter("state")).thenReturn(state); - oauthService.handleRedirect(req, resp, host); - } catch (IOException e) { - fail(e.getMessage()); - } - verify(resp).setStatus(302); - //verify(resp).setHeader("Location",any(String.class)); - } - - public void test2() { - oauthService.sendLoginRedirectResponse(null, null); - } - @Ignore - @Test - public void test3() { - HttpServletResponse resp = mock(HttpServletResponse.class); - String token = ""; - try { - oauthService.sendLogoutRedirectResponse(token, resp,"http://sdnr.onap/odlux/index.html"); - verify(resp).setStatus(302); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - public static class KeycloakProviderServiceToTest extends KeycloakProviderService { - - public KeycloakProviderServiceToTest(OAuthProviderConfig config, String redirectUri, - TokenCreator tokenCreator) throws UnableToConfigureOAuthService { - super(config, redirectUri, tokenCreator); - } - } - - private static int randomPort(int min, int max) { - Random random = new Random(); - return random.nextInt(max + 1 - min) + min; - } - - public static void initKeycloakTestWebserver(int port, String baseUri) throws IOException { - server = HttpServer.create(new InetSocketAddress("127.0.0.1", port), 0); - httpThreadPool = Executors.newFixedThreadPool(5); - server.setExecutor(httpThreadPool); - server.createContext(baseUri, new MyHandler()); - //server.createContext("/", new MyRootHandler()); - server.setExecutor(null); // creates a default executor - server.start(); - System.out.println("http server started"); - } - - public static void stopTestWebserver() { - if (server != null) { - server.stop(0); - httpThreadPool.shutdownNow(); - System.out.println("http server stopped"); - } - } - - private static String loadResourceFileContent(String filename) { - try { - return Files.readString(new File(filename).toPath()); - } catch (IOException e) { - fail(e.getMessage()); - } - return null; - } - - public static class MyHandler implements HttpHandler { - private static final String KEYCLOAK_TOKEN_ENDPOINT = "/auth/realms/onap/protocol/openid-connect/token"; - private static final String KEYCLOAK_LOGOUT_ENDPOINT = "/auth/realms/onap/protocol/openid-connect/logout"; - private static final String KEYCLOAK_TOKEN_RESPONSE = - loadResourceFileContent("src/test/resources/oauth/keycloak-token-response.json"); - - @Override - public void handle(HttpExchange t) throws IOException { - final String method = t.getRequestMethod(); - final String uri = t.getRequestURI().toString(); - System.out.println(String.format("req received: %s %s", method, t.getRequestURI())); - OutputStream os = null; - try { - if("GET".equals(method)){ - if(KEYCLOAK_LOGOUT_ENDPOINT.equals(uri)){ - t.sendResponseHeaders(200, 0); - } - } - else if ("POST".equals(method)) { - if (uri.equals(KEYCLOAK_TOKEN_ENDPOINT)) { - t.sendResponseHeaders(200, KEYCLOAK_TOKEN_RESPONSE.length()); - os = t.getResponseBody(); - os.write(KEYCLOAK_TOKEN_RESPONSE.getBytes()); - } else { - t.sendResponseHeaders(404, 0); - } - } else { - t.sendResponseHeaders(404, 0); - } - System.out.println("req handled successful"); - - } catch (Exception e) { - System.out.println(e.getMessage()); - } finally { - if (os != null) { - os.close(); - } - } - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java deleted file mode 100644 index 31d72944c..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestPolicy.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy; - -public class TestPolicy { - - private static final String PATH_1 = "/p1/**"; - - @Test - public void testPolicyAllowAll() { - OdlPolicy p = OdlPolicy.allowAll(PATH_1); - assertTrue(p.getMethods().isGet()); - assertTrue(p.getMethods().isPost()); - assertTrue(p.getMethods().isPut()); - assertTrue(p.getMethods().isDelete()); - assertTrue(p.getMethods().isPatch()); - assertEquals(PATH_1,p.getPath()); - } - - @Test - public void testPolicyDenyAll() { - OdlPolicy p = OdlPolicy.denyAll(PATH_1); - assertFalse(p.getMethods().isGet()); - assertFalse(p.getMethods().isPost()); - assertFalse(p.getMethods().isPut()); - assertFalse(p.getMethods().isDelete()); - assertFalse(p.getMethods().isPatch()); - assertEquals(PATH_1,p.getPath()); - } - -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java deleted file mode 100644 index 2d03bab1d..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import org.junit.Ignore; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; - -public class TestProperty { - - @Ignore - @Test - public void test() { - String hostname = Config.getProperty("${HOSTNAME}", null); - System.out.println(hostname); - assertNotNull(hostname); - hostname = Config.getProperty("${HOSTNAME2}", null); - System.out.println(hostname); - assertNull(hostname); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java deleted file mode 100644 index 84d8e0a96..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRSAAlgorithms.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.fail; -import com.auth0.jwt.JWT; -import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.JWTVerificationException; -import com.auth0.jwt.interfaces.JWTVerifier; -import java.io.IOException; -import java.security.Security; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.util.Date; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.RSAKeyReader; - -/** - * - * @author jack - * - */ -public class TestRSAAlgorithms { - - private static final String ISSUER = "jwttest"; - private static final String SUBJECT = "meandmymonkey"; - - @BeforeClass - public static void init() { - Security.addProvider( - new BouncyCastleProvider() - ); - } - - /** - * private and public key were generated in ubuntu 20.04 with - * $ ssh-keygen -t rsa -b 4096 -m PEM -P "" -f jwtRS512.key - * $ openssl rsa -in jwtRS512.key -pubout -outform PEM -out jwtRS512.key.pub - */ - @Test - public void testRSA512() { - RSAPrivateKey privKey = null; - RSAPublicKey pubKey = null; - try { - privKey = RSAKeyReader.getPrivateKey("file://src/test/resources/jwtRS512.key"); - pubKey = RSAKeyReader.getPublicKey("file://src/test/resources/jwtRS512.key.pub"); - } catch (IOException e) { - e.printStackTrace(); - fail(e.getMessage()); - } - verifyAlg(Algorithm.RSA512(pubKey, privKey)); - } - - /** - * private and public key were generated in ubuntu 20.04 with - * $ openssl genrsa 2048 -out rsa-2048bit-jwtRS256.key - * $ openssl rsa -in jwtRS256.key -pubout > jwtRS256.key.pub - */ - @Test - public void testRSA256() { - RSAPrivateKey privKey = null; - RSAPublicKey pubKey = null; - try { - privKey = RSAKeyReader.getPrivateKey("file://src/test/resources/jwtRS256.key"); - pubKey = RSAKeyReader.getPublicKey("file://src/test/resources/jwtRS256.key.pub"); - } catch (IOException e) { - e.printStackTrace(); - fail(e.getMessage()); - } - verifyAlg(Algorithm.RSA512(pubKey, privKey)); - } - - private static void verifyAlg(Algorithm a) { - long now = new Date().getTime(); - final String token = JWT.create().withIssuer(ISSUER).withExpiresAt(new Date(now+10000)) - .withIssuedAt(new Date(now)) - .withSubject(SUBJECT) - .sign(a); - try { - JWTVerifier verifier = JWT.require(a).withIssuer(ISSUER).build(); - verifier.verify(token); - - } catch (JWTVerificationException e) { - fail(e.getMessage()); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java deleted file mode 100644 index c1d3fd1ea..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestRealm.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import com.auth0.jwt.interfaces.DecodedJWT; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.function.Supplier; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.BearerToken; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.subject.PrincipalCollection; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.OAuth2Realm; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService; -import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator; -import org.opendaylight.aaa.api.Authentication; -import org.opendaylight.aaa.api.AuthenticationService; -import org.opendaylight.aaa.api.TokenStore; -import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal; -import org.opendaylight.aaa.shiro.realm.TokenAuthRealm; -import org.opendaylight.aaa.tokenauthrealm.auth.AuthenticationManager; -import org.opendaylight.aaa.tokenauthrealm.auth.TokenAuthenticators; -import org.opendaylight.mdsal.binding.api.DataBroker; - -public class TestRealm { - - private static OAuth2RealmToTest realm; - private static TokenCreator tokenCreator; - - private static final AuthenticationManager authManager = new AuthenticationManager(); - private static final TokenAuthenticators tokenAuth = new TokenAuthenticators(); - - private static final TokenStore tokenStore = new TokenStore(){ - - @Override - public void put(String token, Authentication auth) { - - } - - @Override - public Authentication get(String token) { - return null; - } - - @Override - public boolean delete(String token) { - return false; - } - - @Override - public long tokenExpiration() { - return 0; - } - }; - @BeforeClass - public static void init() throws IllegalArgumentException, Exception { - TokenAuthRealm.prepareForLoad(authManager,tokenAuth,tokenStore); - try { - Config config = Config.getInstance(TestConfig.TEST_CONFIG_FILENAME); - tokenCreator = TokenCreator.getInstance(config); - realm = new OAuth2RealmToTest(); - } catch (IOException e) { - fail(e.getMessage()); - } - } - - - @Test - public void testTokenSupport() { - assertTrue(realm.supports(new UsernamePasswordToken())); - assertTrue(realm.supports(new BearerToken(""))); - } - - - @Test - public void testAuthorizationInfo() { - //bearer token use case - PrincipalCollection c = mock(PrincipalCollection.class); - final List roles = Arrays.asList("admin", "provision"); - UserTokenPayload userData = createUserData("", roles); - - DecodedJWT decodedJwt = tokenCreator.verify(tokenCreator.createNewJWT(userData).getToken()); - when(c.getPrimaryPrincipal()).thenReturn(decodedJwt); - - AuthorizationInfo ai = realm.doGetAuthorizationInfo(c); - for (String role : roles) { - assertTrue(ai.getRoles().contains(role)); - } - assertEquals(roles.size(), ai.getRoles().size()); - //odl token use case - ODLPrincipal principal = mock(ODLPrincipal.class); - when(principal.getRoles()).thenReturn(new HashSet(roles)); - PrincipalCollection c2 = mock(PrincipalCollection.class); - when(c2.getPrimaryPrincipal()).thenReturn(principal); - ai = realm.doGetAuthorizationInfo(c2); - for (String role : roles) { - assertTrue(ai.getRoles().contains(role)); - } - assertEquals(roles.size(), ai.getRoles().size()); - - } - - @Test - public void testUrlTrimming(){ - final String internalUrl="https://test.identity.onap:49333"; - final String externalUrl="https://test.identity.onap:49333"; - final String testUrl1 = "/my/token/endpoint"; - final String testUrl2 = internalUrl+testUrl1; - final String testUrl3 = externalUrl+testUrl1; - - assertEquals(testUrl1, AuthService.trimUrl(internalUrl, testUrl1)); - assertEquals(testUrl1, AuthService.trimUrl(internalUrl, testUrl2)); - assertEquals(testUrl1, AuthService.trimUrl(externalUrl, testUrl3)); - - assertEquals(testUrl2, AuthService.extendUrl(internalUrl, testUrl3)); - - - - } - @Test - public void testAssertCredentialsMatch() { - //bearer token use case - UserTokenPayload userData = createUserData("", Arrays.asList("admin", "provision")); - AuthenticationToken atoken = new BearerToken(tokenCreator.createNewJWT(userData).getToken()); - AuthenticationInfo ai = null; - try { - realm.assertCredentialsMatch(atoken, ai); - } catch (AuthenticationException e) { - fail(e.getMessage()); - } - //odl token use case - atoken = new UsernamePasswordToken("admin", "admin"); - try { - realm.assertCredentialsMatch(atoken, ai); - } catch (AuthenticationException e) { - fail(e.getMessage()); - } - } - - @Test - public void testAuthenticationInfo() { - //bearer token use case - UserTokenPayload userData = createUserData("", Arrays.asList("admin", "provision")); - AuthenticationToken atoken = new BearerToken(tokenCreator.createNewJWT(userData).getToken()); - AuthenticationInfo ai = null; - try { - ai = realm.doGetAuthenticationInfo(atoken); - } catch (AuthenticationException e) { - fail(e.getMessage()); - } - //odl token use case - ai=null; - atoken = new UsernamePasswordToken("admin", "admin"); - try { - ai = realm.doGetAuthenticationInfo(atoken); - } catch (AuthenticationException e) { - fail(e.getMessage()); - } - } - - private static UserTokenPayload createUserData(String username, List roles) { - UserTokenPayload userData = new UserTokenPayload(); - userData.setExp(tokenCreator.getDefaultExp()); - userData.setFamilyName(""); - userData.setGivenName(""); - userData.setPreferredUsername(username); - userData.setRoles(roles); - return userData; - } - - public static class OAuth2RealmToTest extends OAuth2Realm { - - public OAuth2RealmToTest() throws IllegalArgumentException, Exception { - super(); - } - - @Override - public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) { - return super.doGetAuthorizationInfo(arg); - } - - @Override - public void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai) - throws AuthenticationException { - super.assertCredentialsMatch(atoken, ai); - } - - @Override - public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { - return super.doGetAuthenticationInfo(token); - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java deleted file mode 100644 index b0cc0253b..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlJsonMapper.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; -import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsModule; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission.Permissions; - -public class OdlJsonMapper extends ObjectMapper { - - private static final long serialVersionUID = 1L; - - - public OdlJsonMapper() { - this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.setSerializationInclusion(Include.NON_NULL); - this.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); - this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); - YangToolsBuilderAnnotationIntrospector introspector = new YangToolsBuilderAnnotationIntrospector(); - //introspector.addDeserializer(Main.class, ShiroMainBuilder.class.getName()); - introspector.addDeserializer(Permissions.class,PermissionsBuilder.class.getName()); - this.setAnnotationIntrospector(introspector); - this.registerModule(new YangToolsModule()); - } - - public static class PermissionsBuilder { - private Permissions _value; - - public PermissionsBuilder() { - - } - public PermissionsBuilder(Permissions value) { - this._value = value; - } - - - public Permissions build() { - return this._value; - } - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java deleted file mode 100644 index b965878e8..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/helper/OdlXmlMapper.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : ccsdk features - * ================================================================================ - * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. - * All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - */ -package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test.helper; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; - -public class OdlXmlMapper extends XmlMapper{ - - private static final long serialVersionUID = 1L; - - - public OdlXmlMapper() { - this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.setSerializationInclusion(Include.NON_NULL); - this.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); - this.enable(MapperFeature.USE_GETTERS_AS_SETTERS); - YangToolsBuilderAnnotationIntrospector introspector = new YangToolsBuilderAnnotationIntrospector(); - //introspector.addDeserializer(Main.class, ShiroMainBuilder.class.getName()); - - this.setAnnotationIntrospector(introspector); - } -} diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/aaa-app-config.test.xml b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/aaa-app-config.test.xml deleted file mode 100644 index 1929fde8e..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/aaa-app-config.test.xml +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - -
- tokenAuthRealm - org.onap.ccsdk.features.sdnr.wt.oauthprovider.OAuth2Realm -
- - - - - - - - - - - -
- securityManager.realms - $tokenAuthRealm -
- -
- authcBasic - org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter -
-
- anyroles - org.opendaylight.aaa.shiro.filters.AnyRoleHttpAuthenticationFilter -
-
- authcBearer - org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter2 -
- - - - -
- accountingListener - org.opendaylight.aaa.shiro.filters.AuthenticationListener -
-
- securityManager.authenticator.authenticationListeners - $accountingListener -
- - -
- dynamicAuthorization - org.opendaylight.aaa.shiro.realm.MDSALDynamicAuthorizationFilter -
- - - - - - - - - /**/operations/cluster-admin** - dynamicAuthorization - - - /**/v1/** - authcBearer, roles[admin] - - - /**/config/aaa*/** - authcBearer, roles[admin] - - - /oauth/** - anon - - - /odlux/** - anon - - - /apidoc/** - authcBasic, roles[admin] - - - /test123/** - authcBasic - - - /rests/** - authcBearer, anyroles["admin,provision"] - - - /** - authcBearer, anyroles["admin,provision"] - -
- diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key deleted file mode 100644 index c0c15e014..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAyzd6BwZLS1UKchZENYyVycHZWp9iRTtLx31dZHfG8h0PLawG -y+dXPEW8W/zVB13/Rdci9HXCnskBhzkFu9Ep+nI7X5C+lO3vxxNnGQ1CrRyHxHbb -BYlm6J55l6tQox5qVcWe4iMbLm7F2eNKFPqEUu8OInjmLFZvS9C0qtfpqdeoyt4G -XucUHcGZ/0E6yeq882+zYyb4pWN5PogAsP2KYeT1T6P0VCw4tda9GtokD3zOSaOg -IvhIqe9jLAVcqWkxpuhV+IQdULBOxcJziW3AdQcB5IFQ7/SfZ9SnO5OpDTe02R5q -bjH9k0iihrpI9HnlVrHqIEtFwDjuoPSeAOBjjwIDAQABAoIBAQCOfNeTFVa1+2rX -k8U/xtNAJCvC3v6IjIsV1VEmoNVd7gI2g+hAEHWaTUtFNIIqKD5VOgPIZMmRjF8F -8XWTu5UzheUbnOIEitEVRQWFC0c1GkwX9T6dIzqE4JlhPz3LIghtG6PL69GjPQh9 -PmEzVHRzsiq3AQ5jCDgBcNU89SdhbhPsfNpDq9+GaWUaVJ4MmJw52qLeSW0nh4NZ -fMSINAfGZ/3Q2Nfe55zIk4KICyatKYLUMdcwynMwWYdZzg1e/4gxemdWdgFVUdPl -rE6y404m+FrHl/nntL153u0C24jtEU0CJvLasu7hLjzAoANBzohcXxLY46jeNqk9 -yS4juMgBAoGBAPxn9hRH5vMxFCfT23/s1RnUB9Sal6OL8/hZ8OpwrnLaLmWDvvr5 -FBcDThhrHnJTLj0pOAxFX8kLjKgQdWB0ZqrEsG1R9AAVHxM4hXc92kDsAk4QJgCG -tKDtzk9PKy8Jt1LnOF9n6NDLZuZim9Sv7qim6tt0L7K/mGrlCN4Gq6E3AoGBAM4c -N2r0vObiSboryfY4xNSUZ1qLWAEJz4gyUQljSrlu2Gj5DK4rrTEd8Qyk9ehUdjuR -giejpdjIvmjQ7NNPUogJbIoSbtKmx+k8qF7ieRulJjVBiJZLwNtGhiB4e6oZdhNl -fJETn8MhkbOt8Sa1eEiR9u2O7IAYVwZLU/khkNxpAoGARxqKSgBPYSbsRKP767et -+I6wfgXmvd3JJqc/pOuFWTl5ZIOOo2jTbgAyWdKjSxV/qx8XeO16JEqqnxWz2y4v -Vd/+y20QzY0lqeZ8QrEb8LoLlC4cZn2MGOGlAtaMlb2o9SPJz6aYAWmrXS9eMrY1 -BzGua4/5d+Ndbo+CxfkfFFUCgYEAjFimW8w+/TDFZ2H96g2J6f8LyZns2PgnOuSY -Tb4w2cfi0MgVnFvdWP68bxG86PDqeXGBoSBMBCvdjF4HhXQUDNHt+K7Ii+RJaEaH -l+S69tokBEuViFIZBrclCeNAwfkIb/jBM8CbHzIylpkxBly3hSLvc5/I5wir6XtN -uOzkSVECgYEAy2oGf68OkNL74/WKDmQvnRxWkn78rCTzVAe0iJmJ3rAdak/Jb2Lj -iihXn0XPsedZOZStbZYCG6GtcZCRypPi9HjO6DRRYFv3+aicjS7tVuJ3u39e5nIR -K6eMAgFn1TAToc3gt/hUCnmreZ4ZUfQfuFK21Lqmn1FYJtck9ZHx0sw= ------END RSA PRIVATE KEY----- diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key.pub b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key.pub deleted file mode 100644 index add863aef..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS256.key.pub +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyzd6BwZLS1UKchZENYyV -ycHZWp9iRTtLx31dZHfG8h0PLawGy+dXPEW8W/zVB13/Rdci9HXCnskBhzkFu9Ep -+nI7X5C+lO3vxxNnGQ1CrRyHxHbbBYlm6J55l6tQox5qVcWe4iMbLm7F2eNKFPqE -Uu8OInjmLFZvS9C0qtfpqdeoyt4GXucUHcGZ/0E6yeq882+zYyb4pWN5PogAsP2K -YeT1T6P0VCw4tda9GtokD3zOSaOgIvhIqe9jLAVcqWkxpuhV+IQdULBOxcJziW3A -dQcB5IFQ7/SfZ9SnO5OpDTe02R5qbjH9k0iihrpI9HnlVrHqIEtFwDjuoPSeAOBj -jwIDAQAB ------END PUBLIC KEY----- diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key deleted file mode 100644 index 6b4e8c7bc..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKQIBAAKCAgEA5vZBjfLjlUPK0b/F8FbGAyT1jXNVv2vjl+ZGUlThDX1jn0Wh -XER5CL9CfkHKjJE47r8pQsO6nX9s5y+XzmAU9+QggtaDA+g0Px+cvCJQzJbtDbh0 -94m3uC50S+SSnYvr7vY1zy+jdswf/pXg1z059FokRxGso36SkSv81NYbN/WQrTKo -gY6jkZXfPP8/sn8KV8uf7jYy2ZyHtakM9c9oCopWH78mhf9ioUNbgJsAxZmiohQU -N5a3GbLS/nsTBOcVxUezvjvfb732iChKoARj3NiNN7HFHpXEXfiZ10OjrtAb9Y1K -9RZsu/MKcFxBhDZusXjee6/x+NluQwT3RybgkCyV/i97Sroc37wOqimxtoSJ+MZY -ZXNAUGNbNySkjvIGL8jWMj6w/zvyiHVbQg+DqY2Qds7Tdk29swYsMQQlz9v0FS/p -GFVWo+5HTm+3MMlaMjSofw6j5/sE4OvJ4RCcnX8Cj1Zq9PrsMLLSF5MBOCSiclpI -C1EYQ9Oi6XrcL3bbyyKGwB/u1X1HHnUmhRdKdVwKpSHR54XlfBDDoYtVnb1HTTxX -MuiGU0XQRLvdnytJX1Lk6NJg/UUUKhrVXiH05CZsxlPFjDlhEhp4Jh+f/mdf6llX -vsXn8k9ujBZBBD6PI4X7GkKB45H9zicbwt65f/MjhEohkbL5oZAKySzaUuMCAwEA -AQKCAgBF7uLCnH0UwUY0ZKEGuP+UDCjd/8JDB+QOJoe8fj722rTDkU3epk0PvPnh -SQKPtZlLkU5pDOMAtYjAJ8ULlERFGypM868QC8tmIahPvwRALqLwuJ2SJn0eo9JK -+Jb8ZVW3MY3xgjc4zW4SpEdEZSGbP4AklNF1X+n5UxxnRb1QIGcCSoiDUjFs77h8 -u70JyzXSh7GRa4/SHHdrJhjqhTa3mlOhoTuE72Np+P9H3adKLc70zKeifVxLx73j -mFiV73LEHYXrYC2zpA12BN0zvqCOSnPYHVfWfvrKiW/romt5j0IoA/Riabva3SiY -BRdBdUnnKvYS9Z+K/itI18QYI0lzSuLiaCTCo/3N/2MkuRMwS3Mvae7kK43/6c3w -sXobp8KBRMnpnT+AHENIHVJ35XKkWfTY9xMg/JkKbAXY06TitKW53ds03vb9Y9n2 -3SKBUcpbTkJJbJ50E/BiglLVxlllzVJiUIMNDGUmZO7eYQx9fs16cz4JkhzKcN+F -zYg4BVXL8blWU6AjXzexjTNuic/IxkqJruG05tCFwVxHjhajb9xQ1ANDMcXnwPmt -VKpU4KxrGqFgsVdZ5SE9gdu1g+zf96DdhXjHhZCfq6fsf2TYXD2SsUhx4kk9zOE/ -I4tXwf7Q7Ol24qlV9W8enc3gr1nk+buutl+I55LSM4bG4M3uQQKCAQEA/rkulfhl -wxStbVIICRl6iuC1nhqlxOBZAbc45pRgEDyTO5IfxnVA6kVCa5DkQ5cWZOoshKg9 -MNfHbo9JIYZzElnM/XxpmqIsHpQ+ZXe5XVaaYz9DogNnH2iLtQGVVLPphtxJxTqW -A6944GuhmZ9DmRwn0nN2nU0nUqBtLFio9+b7nChDaJj5aIkLHjx3p9ytjzzJP5nM -0lKSo9BD97+AhCaIT7NxjKSRWRs7ftf7Bv5vxPXrpgUN8ltkg4YVIzGX7UMXT+ga -H2kf+QkAJX1+9kbNMjkqhOH7zkv1DVqCVup9XewA2GltxoJZIVH04+QmgNWcS+XP -cbxe0r95tuMTqQKCAQEA6B6WYpC9UxXLPfOJdWDzSO3oh13RgQo1uEHdU9rc9vfi -vYZZsSL06uR7v6fuiuyAAayZgCTS1xr69MCAJR2056E3RthktAzOkfCJrcIyEHmy -b9yekRyL+R8P4HxV76AYqY52PhdgDntGoXb7hcGKt6hvkmcR41cnRHRjrb7zkEVy -55JY1woEVtt6otxHKZSnx5nlQct73Lv65QDfosfkESOmbE2W4G87XBk36I2YBywU -kNEr49tnI09qyEPJLjTTGxFdMeqXbnCgzSwqlBlrQE8NYJBsy2GBL0EWOYeRXkuz -RFug3o89uAOircy2virMhl6EOA0EKakWR4ZQCKlJqwKCAQEA40aBnYhL6/sIHtGh -n9Te9Qk4o4AtRnPSluhPWdUrvXD/AZkIxv+Z0y3G7MkUEoa9kX8sB5VBO9Jb/HbW -jpYzGD2N3OLkKvfmG8azwb9IYlLCYClzhBw7J9gVR4TJJBF/HThyjgsPDOzFEqCW -SMbE/tkTYwBo5kOQAXZo0res07yB5bw7IRnU94PHqsvTC7CoH3TiL+Bf042fj5Bl -BKoW1lK3Lz3x48Z2daYJuMynC398ZKX0A2bhIcyP65Z4R7WZVDaXl1GF9V7MC10P -h2PpI37a2aQOHxCvp0s4tBh80WZaQ7Iusumm7Acj1coVkjzgafWuhj3fkSC9DpeP -1zHXOQKCAQBCiVIOWvMKN/sUfRTwAqR6SUgYVXpShPy1Hpw1B03DtXbXYQWg0yZl -lq0qWRb116kx0aoGo4eUhXVeZzfUa9mJdBsGQc1MF0e3ab3tgvca5eeSTSle61Hs -TU0dykZP9BJduCqIzeaJAClU62haBQqgbrXcv5LPGhJ1eu9/xHbI6j9vxfGVYpev -1iYnPQFhF+2oN6MR4yRUN8ZJkqCIZsgnaZKxBOS03O2lDs2J6dykYaxbfroYDLJZ -2s//K/8lMZs57RZL0rUpwTs21Ow3m7m0q3RoM74b5o1DYGLghs3Su9xdQe6xHVpR -vykIrN/NTzNlaP55mrGQx5lNU2Dpuq0VAoIBAQDVCfAJlu+wkZmeXm1zUOFjOMvq -el3t55RCQ/SuhIpaNf2CWD6SOZfHfTxJ8nuYE+FJmjL6r9Z4a8ND0VPttuyBG6gY -siuZUE31+2OBvdKBhi4stqGZWMKJqYsDFH7QIfu7wSS1kuJ/vA7MB9f7IsrHJb2z -QBJoVMZoXhh4tqyFVatEp6yYSE4uKLvlKQSJ6W8DEuPggoiNPbhxQq2ctFUyup/S -9MsfJ9tj99mjlPSelMUXsHcsprIZBuhskfeidTe+gy43TBm0G8l7xeAGWkBlWQMR -L843JjebD6QCnPIS4nrW7kCRM8lv1ZId6D5Jq1Coc8b1ZrezfII7/eNgZZCv ------END RSA PRIVATE KEY----- diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key.pub b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key.pub deleted file mode 100644 index 7191c95f8..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/jwtRS512.key.pub +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5vZBjfLjlUPK0b/F8FbG -AyT1jXNVv2vjl+ZGUlThDX1jn0WhXER5CL9CfkHKjJE47r8pQsO6nX9s5y+XzmAU -9+QggtaDA+g0Px+cvCJQzJbtDbh094m3uC50S+SSnYvr7vY1zy+jdswf/pXg1z05 -9FokRxGso36SkSv81NYbN/WQrTKogY6jkZXfPP8/sn8KV8uf7jYy2ZyHtakM9c9o -CopWH78mhf9ioUNbgJsAxZmiohQUN5a3GbLS/nsTBOcVxUezvjvfb732iChKoARj -3NiNN7HFHpXEXfiZ10OjrtAb9Y1K9RZsu/MKcFxBhDZusXjee6/x+NluQwT3Rybg -kCyV/i97Sroc37wOqimxtoSJ+MZYZXNAUGNbNySkjvIGL8jWMj6w/zvyiHVbQg+D -qY2Qds7Tdk29swYsMQQlz9v0FS/pGFVWo+5HTm+3MMlaMjSofw6j5/sE4OvJ4RCc -nX8Cj1Zq9PrsMLLSF5MBOCSiclpIC1EYQ9Oi6XrcL3bbyyKGwB/u1X1HHnUmhRdK -dVwKpSHR54XlfBDDoYtVnb1HTTxXMuiGU0XQRLvdnytJX1Lk6NJg/UUUKhrVXiH0 -5CZsxlPFjDlhEhp4Jh+f/mdf6llXvsXn8k9ujBZBBD6PI4X7GkKB45H9zicbwt65 -f/MjhEohkbL5oZAKySzaUuMCAwEAAQ== ------END PUBLIC KEY----- diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/mdsalDynAuthData.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/mdsalDynAuthData.json deleted file mode 100644 index a1627682b..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/mdsalDynAuthData.json +++ /dev/null @@ -1,694 +0,0 @@ -{ - "policies": [ - { - "resource": "/restconf/**", - "index": 0, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - } - ] - }, - { - "resource": "/auth/v1/**", - "index": 1, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - } - ] - }, - { - "resource": "/config/aaa*/**", - "index": 2, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - } - ] - }, - { - "resource": "/jolokia/**", - "index": 3, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - }, - { - "role": "raftstate", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250004/**", - "index": 4, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "huawei", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250005/**", - "index": 5, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "huawei", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250006/**", - "index": 6, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "siae", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250007/**", - "index": 7, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "siae", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250008/**", - "index": 8, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "siae", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250009/**", - "index": 9, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "siae", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250010/**", - "index": 10, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "ericsson", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250011/**", - "index": 11, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "ericsson", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513559991A/**", - "index": 14, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "ericsson", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513559991B/**", - "index": 15, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "ericsson", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250012/**", - "index": 12, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "zte", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/node=513250013/**", - "index": 13, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "zte", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - }, - { - "resource": "/rests/data/network-topology:network-topology/topology=topology-netconf/**", - "index": 16, - "permissions": [ - { - "role": "admin", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "provisioner", - "actions": [ - "put", - "get", - "patch", - "delete", - "post" - ] - }, - { - "role": "planner", - "actions": [ - "get" - ] - }, - { - "role": "monitor", - "actions": [ - "get" - ] - } - ] - } - ] - } diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-groups-response.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-groups-response.json deleted file mode 100644 index 85fc37cc8..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-groups-response.json +++ /dev/null @@ -1,112 +0,0 @@ -[ - { - "id": 51, - "web_url": "https://my-git-server.com/groups/group1", - "name": "Group1", - "path": "group1", - "description": "", - "visibility": "private", - "share_with_group_lock": false, - "require_two_factor_authentication": false, - "two_factor_grace_period": 48, - "project_creation_level": "developer", - "auto_devops_enabled": null, - "subgroup_creation_level": "maintainer", - "emails_disabled": null, - "mentions_disabled": null, - "lfs_enabled": true, - "avatar_url": null, - "request_access_enabled": true, - "full_name": "Group1", - "full_path": "group1", - "parent_id": null - }, - { - "id": 69, - "web_url": "https://my-git-server.com/groups/group2", - "name": "Group2", - "path": "group2", - "description": "", - "visibility": "private", - "share_with_group_lock": false, - "require_two_factor_authentication": false, - "two_factor_grace_period": 48, - "project_creation_level": "developer", - "auto_devops_enabled": null, - "subgroup_creation_level": "owner", - "emails_disabled": null, - "mentions_disabled": null, - "lfs_enabled": true, - "avatar_url": null, - "request_access_enabled": true, - "full_name": "Group2", - "full_path": "group2", - "parent_id": null - }, - { - "id": 24, - "web_url": "https://my-git-server.com/groups/group3", - "name": "group3", - "path": "group3", - "description": "", - "visibility": "private", - "share_with_group_lock": false, - "require_two_factor_authentication": false, - "two_factor_grace_period": 48, - "project_creation_level": "developer", - "auto_devops_enabled": null, - "subgroup_creation_level": "owner", - "emails_disabled": null, - "mentions_disabled": null, - "lfs_enabled": true, - "avatar_url": null, - "request_access_enabled": false, - "full_name": "group3", - "full_path": "group3", - "parent_id": null - }, - { - "id": 22, - "web_url": "https://my-git-server.com/groups/group4", - "name": "group4", - "path": "group4", - "description": "custom desc", - "visibility": "private", - "share_with_group_lock": false, - "require_two_factor_authentication": false, - "two_factor_grace_period": 48, - "project_creation_level": "developer", - "auto_devops_enabled": null, - "subgroup_creation_level": "owner", - "emails_disabled": null, - "mentions_disabled": null, - "lfs_enabled": true, - "avatar_url": "https://my-git-server.com/uploads/-/system/group/avatar/22/Factory_1b.svg.png", - "request_access_enabled": true, - "full_name": "group4", - "full_path": "group4", - "parent_id": null - }, - { - "id": 5, - "web_url": "https://my-git-server.com/groups/group5", - "name": "group5", - "path": "group5", - "description": "my group 5", - "visibility": "private", - "share_with_group_lock": false, - "require_two_factor_authentication": false, - "two_factor_grace_period": 48, - "project_creation_level": "developer", - "auto_devops_enabled": null, - "subgroup_creation_level": "owner", - "emails_disabled": null, - "mentions_disabled": null, - "lfs_enabled": true, - "avatar_url": "https://my-git-server.com/uploads/-/system/group/avatar/5/mylogo.png", - "request_access_enabled": true, - "full_name": "group5", - "full_path": "group5", - "parent_id": null - } -] \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-token-response.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-token-response.json deleted file mode 100644 index 0a6bd7231..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-token-response.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "access_token":"asfhoipmspaodm-asndfoiasnf-aisjdaisjj", - "expires_in":12345, - "refresh_expires_in":123456, - "refresh_token":"asdsadasd", - "token_type":"bearer" -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-user-response.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-user-response.json deleted file mode 100644 index b08332b41..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/gitlab-user-response.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "id": 21, - "name": "me", - "username": "my-username", - "state": "active", - "avatar_url": "https://my-git-server.com/uploads/-/system/user/avatar/21/avatar.png", - "web_url": "https://my-git-server.com/my-username", - "created_at": "2017-05-15T14:49:38.396Z", - "bio": "", - "location": "", - "public_email": "", - "skype": "", - "linkedin": "", - "twitter": "", - "website_url": "", - "organization": "", - "last_sign_in_at": "2021-02-12T12:56:34.094Z", - "confirmed_at": "2018-01-18T09:49:08.463Z", - "last_activity_on": "2021-02-15", - "email": "me@my-server.com", - "theme_id": null, - "color_scheme_id": 1, - "projects_limit": 0, - "current_sign_in_at": "2021-02-15T03:17:12.140Z", - "identities": [], - "can_create_group": false, - "can_create_project": false, - "two_factor_enabled": false, - "external": false, - "private_profile": false, - "is_admin": true -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/keycloak-token-response.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/keycloak-token-response.json deleted file mode 100644 index c62ed9458..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oauth/keycloak-token-response.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkbWFSWXRkaHFkVXFDV2lmRWdNRHFBcWVBcU8tMnFoTDBjdnByelRGdWRRIn0.eyJleHAiOjE2MTExMzU5MjEsImlhdCI6MTYxMTEzNDEyMSwiYXV0aF90aW1lIjoxNjExMTM0MDkxLCJqdGkiOiIzYzFlZmMzZi1lMjFiLTQ3MzktYTY1YS1jNjY1M2ZhOGRjNTQiLCJpc3MiOiJodHRwOi8vMTAuMjAuMTEuMTYwOjgwODAvYXV0aC9yZWFsbXMvb25hcCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI0NDZhMjRiYy1kOGEwLTQzZGQtYWZhNS1lNTZlZWQ3NWRlYjgiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJvZGx1eC5hcHAiLCJzZXNzaW9uX3N0YXRlIjoiMTI5YjRhNjMtNzBhMS00MjFmLWEzM2YtOWFjZDkyZTIzM2ZmIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJwcm92aXNpb24iLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ikx1a2UgU2t5d2Fsa2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoibHVrZS5za3l3YWxrZXIiLCJnaXZlbl9uYW1lIjoiTHVrZSIsImZhbWlseV9uYW1lIjoiU2t5d2Fsa2VyIiwiZW1haWwiOiJsdWtlLnNreXdhbGtlckBzZG5yLm9uYXAub3JnIn0.tn2NrEGYLRq1u0DkqxD2iDM72hFrDBPGA_q23S-htiRH113yt14a0CzJxU9El0YDobbzog9xm0ELbx6W4jYsGguMABqIi4W5wtTqfbaCh7gmF208CqNpwzA7nG2palMLbBPpmGXiagUm4qLWQxrBP_VOaeW_kK0VHLaiTRJ-4vHuOXSNPYEDQZNCI2QCJQS_dn83K_JI4ecBHl8UeHFLB65BqmocpDHUvf2h835xuNFFQpXJWMcPM_j_FmFQeOSUDM4HmqgdVU9_b4APnDEVFiUezQdoEOfEYNsNlhCoXlaEEn2tCZfEkZ7k72DlhqJMQzomdaGKPk2g8XhKJNwMJg", - "expires_in": 1800, - "refresh_expires_in": 1800, - "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhOGUzMDUwZS0wZmQxLTRjYjQtYjRiZS1jMDVlOGY4OGJhZGUifQ.eyJleHAiOjE2MTExMzU5MjEsImlhdCI6MTYxMTEzNDEyMSwianRpIjoiZmZiYWE3NDktZGVkNi00ZWMzLWI4MjYtYTI4NWY0ODY1ZGI0IiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL29uYXAiLCJhdWQiOiJodHRwOi8vMTAuMjAuMTEuMTYwOjgwODAvYXV0aC9yZWFsbXMvb25hcCIsInN1YiI6IjQ0NmEyNGJjLWQ4YTAtNDNkZC1hZmE1LWU1NmVlZDc1ZGViOCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJvZGx1eC5hcHAiLCJzZXNzaW9uX3N0YXRlIjoiMTI5YjRhNjMtNzBhMS00MjFmLWEzM2YtOWFjZDkyZTIzM2ZmIiwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCJ9.mt9VHtiBZycHcEuVCOZVjjtyoOGYNaDVvtcA1NPScIQ", - "token_type": "bearer", - "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkbWFSWXRkaHFkVXFDV2lmRWdNRHFBcWVBcU8tMnFoTDBjdnByelRGdWRRIn0.eyJleHAiOjE2MTExMzU5MjEsImlhdCI6MTYxMTEzNDEyMSwiYXV0aF90aW1lIjoxNjExMTM0MDkxLCJqdGkiOiJjZjUzZTc0ZC1kYjZiLTQ4YTUtODkyOS1jYzU3YjY3YjAxN2QiLCJpc3MiOiJodHRwOi8vMTAuMjAuMTEuMTYwOjgwODAvYXV0aC9yZWFsbXMvb25hcCIsImF1ZCI6Im9kbHV4LmFwcCIsInN1YiI6IjQ0NmEyNGJjLWQ4YTAtNDNkZC1hZmE1LWU1NmVlZDc1ZGViOCIsInR5cCI6IklEIiwiYXpwIjoib2RsdXguYXBwIiwic2Vzc2lvbl9zdGF0ZSI6IjEyOWI0YTYzLTcwYTEtNDIxZi1hMzNmLTlhY2Q5MmUyMzNmZiIsImF0X2hhc2giOiJSUXdDclpkQmFKV0VFdmxsRVNxRjV3IiwiYWNyIjoiMSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ikx1a2UgU2t5d2Fsa2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoibHVrZS5za3l3YWxrZXIiLCJnaXZlbl9uYW1lIjoiTHVrZSIsImZhbWlseV9uYW1lIjoiU2t5d2Fsa2VyIiwiZW1haWwiOiJsdWtlLnNreXdhbGtlckBzZG5yLm9uYXAub3JnIn0.rueTNrnvRa4PMo7NS8l4xxRhhNiGzXLmtcUeyWnj3AjFaUoNKuS9l85K3KjRT3zjq494YsepIGuK33I20rvFwDLclcJNHuumAgBnR5dRBi5fLhm7x8YkebhdTHPiYL4hfygpZ7APN1PtcDZnb-uEjjT-RAtjnfk3r-oP6CtqWzI5MjOPnf5HaEwWpkuTjmJf3kyyf_pdhhVkgTwuC-kD8iMjyRIzuZJxVwWVA3S43eL0R7MaIDlpJrOp9EBRfMlObAypc1bLtKwopT0sBla1CM9GmUU2ZYbQb79-hey0rd7CWx1uBkZUxt5myiExBm3pI46boXLP7dzjzxHUKg0m-A", - "not-before-policy": 1611134054, - "session_state": "129b4a63-70a1-421f-a33f-9acd92e233ff", - "scope": "openid profile email" -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oom.test.config.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oom.test.config.json deleted file mode 100644 index 4e5707fa1..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/oom.test.config.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "tokenSecret": "secret", - "tokenIssuer": "ONAP SDNC", - "publicUrl": "https://sdnc.onap:30205", - "redirectUri": "null", - "supportOdlUsers": "true", - "providers": [ - { - "id": "htgit", - "type": "GITLAB", - "url": "https://git-.com", - "clientId": "f52440b7dcd4bb75", - "secret": "9bd45916f52440b7dcd4bb75", - "scope": "api+openid+read_user+profile", - "title": " Gitlab", - "roleMapping": { - "mygitlabgroup": "admin" - } - } - ] -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json deleted file mode 100644 index a55576b9e..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "tokenSecret": "secret2134", - "tokenIssuer": "ONAP SDNC", - "publicUrl": "http://nasp.diasf.de", - "redirectUri": "/index.html#redirect=", - "supportOdlUsers": "true", - "tokenLifetime":3600, - "providers": [ - { - "id": "keycloak", - "type": "KEYCLOAK", - "url": "http://10.20.11.160:8080", - "clientId": "odlux.app", - "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", - "scope": "openid", - "title": "OSNL Keycloak Provider", - "realmName":"onap" - } - ] -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256-invalid.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256-invalid.json deleted file mode 100644 index 30b80c45a..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256-invalid.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "tokenSecret": "", - "tokenPubKey": "file:///src/test/resources/jwtRS256.key.pub", - "algorithm":"RS256", - "tokenIssuer": "ONAP SDNC", - "publicUrl": "http://nasp.diasf.de", - "redirectUri": "/index.html#redirect=", - "supportOdlUsers": "true", - "tokenLifetime":3600, - "providers": [ - { - "id": "keycloak", - "type": "KEYCLOAK", - "url": "http://10.20.11.160:8080", - "clientId": "odlux.app", - "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", - "publickey": "", - "algorithm":"RS256", - "scope": "openid", - "title": "OSNL Keycloak Provider", - "realmName":"onap" - } - ] -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256.json deleted file mode 100644 index 02a4e8f5f..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS256.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "tokenSecret": "file:///src/test/resources/jwtRS256.key", - "tokenPubKey": "file:///src/test/resources/jwtRS256.key.pub", - "algorithm":"RS256", - "tokenIssuer": "ONAP SDNC", - "publicUrl": "http://nasp.diasf.de", - "redirectUri": "/index.html#redirect=", - "supportOdlUsers": "true", - "tokenLifetime":3600, - "providers": [ - { - "id": "keycloak", - "type": "KEYCLOAK", - "url": "http://10.20.11.160:8080", - "clientId": "odlux.app", - "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", - "scope": "openid", - "title": "OSNL Keycloak Provider", - "realmName":"onap" - } - ] -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS512.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS512.json deleted file mode 100644 index eddc6c362..000000000 --- a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.configRS512.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "tokenSecret": "file:///src/test/resources/jwtRS512.key", - "tokenPubKey": "file:///src/test/resources/jwtRS512.key.pub", - "algorithm":"RS512", - "tokenIssuer": "ONAP SDNC", - "publicUrl": "http://nasp.diasf.de", - "redirectUri": "/index.html#redirect=", - "supportOdlUsers": "true", - "tokenLifetime":3600, - "providers": [ - { - "id": "keycloak", - "type": "KEYCLOAK", - "url": "http://10.20.11.160:8080", - "clientId": "odlux.app", - "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd", - "scope": "openid", - "title": "OSNL Keycloak Provider", - "realmName":"onap" - } - ] -} \ No newline at end of file diff --git a/sdnr/wt/oauth-provider/provider-osgi/pom.xml b/sdnr/wt/oauth-provider/provider-osgi/pom.xml deleted file mode 100644 index 99634cbeb..000000000 --- a/sdnr/wt/oauth-provider/provider-osgi/pom.xml +++ /dev/null @@ -1,156 +0,0 @@ - - - - 4.0.0 - - - org.onap.ccsdk.parent - binding-parent - 2.6.1 - - - - org.onap.ccsdk.features.sdnr.wt - sdnr-wt-oauth-provider - 1.6.0-SNAPSHOT - bundle - - ccsdk-features :: ${project.artifactId} - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 - - - - - true - true - - - - - ${project.groupId} - sdnr-wt-oauth-provider-jar - ${project.version} - - - org.opendaylight.aaa - aaa-shiro - - - org.opendaylight.aaa - aaa-shiro - - - org.apache.shiro - shiro-web - - - ${project.groupId} - sdnr-wt-common - - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - ${project.artifactId} - ${project.version} - - org.onap.ccsdk.features.sdnr.wt.oauthprovider;version=${project.version}, - org.onap.ccsdk.features.sdnr.wt.oauthprovider.filters;version=${project.version}, - org.onap.ccsdk.features.sdnr.wt.oauthprovider.http;version=${project.version}, - org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client;version=${project.version}, - org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;version=${project.version}, - org.onap.ccsdk.features.sdnr.wt.oauthprovider.services;version=${project.version} - - - javax.servlet, - javax.servlet.http, - javax.net.ssl, - javax.crypto, - javax.crypto.spec, - javax.xml.transform, - javax.xml.datatype, - javax.management, - javax.security.auth, - javax.security.auth.login, - javax.security.auth.callback, - javax.xml.parsers, - javax.xml.namespace, - javax.xml.transform.stream, - org.apache.shiro.authc, - org.apache.shiro.authz, - org.apache.shiro.realm, - org.apache.shiro.subject, - org.apache.shiro.web.filter.authz, - org.jolokia.osgi.security, - org.onap.ccsdk.features.sdnr.wt.common.http, - org.opendaylight.aaa.api, - org.opendaylight.aaa.api.shiro.principal, - org.opendaylight.aaa.shiro.realm, - org.opendaylight.aaa.shiro.filters, - org.opendaylight.aaa.shiro.web.env, - org.opendaylight.mdsal.binding.api, - org.opendaylight.mdsal.common.api, - org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619, - org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.shiro.configuration, - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214, - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization, - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.authorization.policies, - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.aaa.rev161214.http.permission, - org.opendaylight.yangtools.concepts, - org.opendaylight.yangtools.yang.binding, - org.opendaylight.yangtools.yang.common, - org.osgi.service.http, - com.fasterxml.jackson.databind, - com.fasterxml.jackson.databind.deser.std, - com.fasterxml.jackson.databind.ser.std, - com.fasterxml.jackson.databind.module, - com.fasterxml.jackson.annotation, - com.fasterxml.jackson.core.type, - com.fasterxml.jackson.core, - org.apache.commons.codec.binary, - com.google.common.base, - com.google.common.collect, - com.google.common.util.concurrent - - *;scope=compile|runtime;inline=false - *;scope=compile|runtime;artifactId=!shiro-core;inline=false - true - org.opendaylight.aaa.repackaged-shiro - - - - - - diff --git a/sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml deleted file mode 100644 index a8258dc8b..000000000 --- a/sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sdnr/wt/pom.xml b/sdnr/wt/pom.xml index 13a34cd47..04fb07291 100644 --- a/sdnr/wt/pom.xml +++ b/sdnr/wt/pom.xml @@ -47,7 +47,7 @@ mountpoint-registrar netconfnode-state-service mountpoint-state-provider - + oauth-provider featureaggregator -- cgit 1.2.3-korg