aboutsummaryrefslogtreecommitdiffstats
path: root/aai-resources/src/main
diff options
context:
space:
mode:
authorFiete Ostkamp <Fiete.Ostkamp@telekom.de>2025-01-06 11:38:34 +0100
committerFiete Ostkamp <fiete.ostkamp@telekom.de>2025-01-13 20:41:40 +0000
commit1733043036bbf8659db9856eaac583e70f44ed4a (patch)
tree057a884a61ba32e3bc4b4da1762c6ae6d459de28 /aai-resources/src/main
parentdd4a7968d539a958b2ddccb77d00fcb68eb177b7 (diff)
Make aai-resources agnostic of the embedded server (remove jetty-specific code)HEADoslomaster
- small adjustments to authentication - make users configurable via aai.basic-auth.users[] in application.properties - remove Keycloak integration [0] [0] for the following reasons: - integration test (MultiTenancyTest) already not working - dependency is ancient (uses 11, 26 is available as of writing) - keycloak autoconfiguration is in conflict with spring security - keycloak-specific starters have been deprecated and users are advised to use the out-of-the-box spring OIDC integration [1] - there is no (and likely never will be a) starter that is compatible with spring-boot 3 [1] https://www.keycloak.org/2023/03/adapter-deprecation-update Issue-ID: AAI-4100 Change-Id: I8440f44106f9ba2cbd4addfa88efb63329365977 Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
Diffstat (limited to 'aai-resources/src/main')
-rw-r--r--aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java5
-rw-r--r--aai-resources/src/main/java/org/onap/aai/ResourcesApp.java6
-rw-r--r--aai-resources/src/main/java/org/onap/aai/config/AuthProperties.java (renamed from aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java)33
-rw-r--r--aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java26
-rw-r--r--aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java159
-rw-r--r--aai-resources/src/main/java/org/onap/aai/interceptors/pre/AuthInterceptor.java87
-rw-r--r--aai-resources/src/main/java/org/onap/aai/interceptors/pre/NamespaceInterceptor.java3
-rw-r--r--aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java83
-rw-r--r--aai-resources/src/main/java/org/onap/aai/rest/ResourcesController.java35
-rw-r--r--aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java79
-rw-r--r--aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java113
-rw-r--r--aai-resources/src/main/resources/application-keycloak.properties14
-rw-r--r--aai-resources/src/main/resources/application.properties32
-rw-r--r--aai-resources/src/main/resources/etc/appprops/aaiconfig.properties5
14 files changed, 156 insertions, 524 deletions
diff --git a/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java b/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java
index 9331f2f5..68ed2fb6 100644
--- a/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java
+++ b/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java
@@ -41,7 +41,6 @@ import org.onap.aai.introspection.LoaderFactory;
import org.onap.aai.introspection.ModelType;
import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
import org.onap.aai.logging.ErrorLogHelper;
-import org.onap.aai.restclient.PropertyPasswordConfiguration;
import org.onap.aai.serialization.db.EdgeSerializer;
import org.onap.aai.serialization.engines.TransactionalGraphEngine;
import org.onap.aai.setup.SchemaVersions;
@@ -76,8 +75,6 @@ public class IncreaseNodesTool {
throws AAIUnknownObjectException, UnsupportedEncodingException, AAIException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
- PropertyPasswordConfiguration initializer = new PropertyPasswordConfiguration();
- initializer.initialize(context);
try {
context.scan("org.onap.aai.config", "org.onap.aai.setup");
context.refresh();
@@ -129,7 +126,7 @@ public class IncreaseNodesTool {
* /cloud-infrastructure/pservers/pserver/
* /network/pnfs/pnf/
* /cloud-infrastructure/pservers/pserver/random-056fd6c4-7313-4fa0-b854-0d9983bdb0ab/p-interfaces/p-interface/
- *
+ *
* @param
* @param
* @param cArgs
diff --git a/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java b/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java
index 51f5609f..7e1bd3a9 100644
--- a/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java
+++ b/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java
@@ -30,7 +30,6 @@ import org.onap.aai.dbmap.AAIGraph;
import org.onap.aai.exceptions.AAIException;
import org.onap.aai.logging.ErrorLogHelper;
import org.onap.aai.nodes.NodeIngestor;
-import org.onap.aai.restclient.PropertyPasswordConfiguration;
import org.onap.aai.util.AAIConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,9 +41,11 @@ import org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoCo
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
+@EnableConfigurationProperties
@SpringBootApplication(
exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, CassandraDataAutoConfiguration.class, CassandraAutoConfiguration.class})
@@ -105,7 +106,6 @@ public class ResourcesApp {
SpringApplication app = new SpringApplication(ResourcesApp.class);
app.setLogStartupInfo(false);
app.setRegisterShutdownHook(true);
- app.addInitializers(new PropertyPasswordConfiguration());
env = app.run(args).getEnvironment();
} catch (Exception ex) {
AAIException aai = null;
@@ -132,8 +132,6 @@ public class ResourcesApp {
logger.info("Resources MicroService Started");
logger.debug("Resources MicroService Started");
- System.out.println("Resources Microservice Started");
-
}
public static void setDefaultProps() {
diff --git a/aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java b/aai-resources/src/main/java/org/onap/aai/config/AuthProperties.java
index 833fd563..1ecffb6f 100644
--- a/aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java
+++ b/aai-resources/src/main/java/org/onap/aai/config/AuthProperties.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2025 Deutsche Telekom. 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.
@@ -20,15 +20,28 @@
package org.onap.aai.config;
-import org.eclipse.jetty.util.security.Password;
+import java.util.List;
-public class JettyPasswordDecoder implements PasswordDecoder {
+import javax.validation.constraints.NotEmpty;
- @Override
- public String decode(String input) {
- if (input.startsWith("OBF:")) {
- return Password.deobfuscate(input);
- }
- return Password.deobfuscate("OBF:" + input);
- }
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Data;
+
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "aai.basic-auth")
+public class AuthProperties {
+
+ boolean enabled = true;
+
+ @NotEmpty
+ List<User> users;
+
+ @Data
+ public static class User {
+ private String username;
+ private String password;
+ }
}
diff --git a/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java b/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java
deleted file mode 100644
index 8ad75d9d..00000000
--- a/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T 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.aai.config;
-
-public interface PasswordDecoder {
-
- String decode(String input);
-}
diff --git a/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java b/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java
deleted file mode 100644
index f205804f..00000000
--- a/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T 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.aai.config;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.commons.io.IOUtils;
-import org.springframework.context.ApplicationContextInitializer;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.core.env.ConfigurableEnvironment;
-import org.springframework.core.env.EnumerablePropertySource;
-import org.springframework.core.env.MapPropertySource;
-import org.springframework.core.env.PropertySource;
-
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class PropertyPasswordConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> {
-
- private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)");
- private PasswordDecoder passwordDecoder = new JettyPasswordDecoder();
-
- @Override
- public void initialize(ConfigurableApplicationContext applicationContext) {
- ConfigurableEnvironment environment = applicationContext.getEnvironment();
- String certPath = environment.getProperty("server.certs.location");
- File passwordFile = null;
- File passphrasesFile = null;
- InputStream passwordStream = null;
- InputStream passphrasesStream = null;
- Map<String, Object> sslProps = new LinkedHashMap<>();
-
- // Override the passwords from application.properties if we find AAF certman files
- if (certPath != null) {
- try {
- passwordFile = new File(certPath + ".password");
- passwordStream = new FileInputStream(passwordFile);
-
- if (passwordStream != null) {
- String keystorePassword = null;
-
- keystorePassword = IOUtils.toString(passwordStream, Charset.defaultCharset());
- if (keystorePassword != null) {
- keystorePassword = keystorePassword.trim();
- }
- sslProps.put("server.ssl.key-store-password", keystorePassword);
- sslProps.put("schema.service.ssl.key-store-password", keystorePassword);
- } else {
- log.info("Not using AAF Certman password file");
- }
- } catch (IOException e) {
- log.warn("Not using AAF Certman password file, e=" + e.getMessage());
- } finally {
- if (passwordStream != null) {
- try {
- passwordStream.close();
- } catch (Exception e) {
- }
- }
- }
- try {
- passphrasesFile = new File(certPath + ".passphrases");
- passphrasesStream = new FileInputStream(passphrasesFile);
-
- if (passphrasesStream != null) {
- String truststorePassword = null;
- Properties passphrasesProps = new Properties();
- passphrasesProps.load(passphrasesStream);
- truststorePassword = passphrasesProps.getProperty("cadi_truststore_password");
- if (truststorePassword != null) {
- truststorePassword = truststorePassword.trim();
- }
- sslProps.put("server.ssl.trust-store-password", truststorePassword);
- sslProps.put("schema.service.ssl.trust-store-password", truststorePassword);
- } else {
- log.info("Not using AAF Certman passphrases file");
- }
- } catch (IOException e) {
- log.warn("Not using AAF Certman passphrases file, e=" + e.getMessage());
- } finally {
- if (passphrasesStream != null) {
- try {
- passphrasesStream.close();
- } catch (Exception e) {
- }
- }
- }
- }
- for (PropertySource<?> propertySource : environment.getPropertySources()) {
- Map<String, Object> propertyOverrides = new LinkedHashMap<>();
- decodePasswords(propertySource, propertyOverrides);
- if (!propertyOverrides.isEmpty()) {
- PropertySource<?> decodedProperties =
- new MapPropertySource("decoded " + propertySource.getName(), propertyOverrides);
- environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties);
- }
-
- }
- if (!sslProps.isEmpty()) {
- log.info("Using AAF Certman files");
- PropertySource<?> additionalProperties = new MapPropertySource("additionalProperties", sslProps);
- environment.getPropertySources().addFirst(additionalProperties);
- }
- }
-
- private void decodePasswords(PropertySource<?> source, Map<String, Object> propertyOverrides) {
- if (source instanceof EnumerablePropertySource) {
- EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source;
- for (String key : enumerablePropertySource.getPropertyNames()) {
- Object rawValue = source.getProperty(key);
- if (rawValue instanceof String) {
- String decodedValue = decodePasswordsInString((String) rawValue);
- propertyOverrides.put(key, decodedValue);
- }
- }
- }
- }
-
- private String decodePasswordsInString(String input) {
- if (input == null)
- return null;
- StringBuffer output = new StringBuffer();
- Matcher matcher = decodePasswordPattern.matcher(input);
- while (matcher.find()) {
- String replacement = passwordDecoder.decode(matcher.group(1));
- matcher.appendReplacement(output, replacement);
- }
- matcher.appendTail(output);
- return output.toString();
- }
-
-}
diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AuthInterceptor.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AuthInterceptor.java
new file mode 100644
index 00000000..e590d9f6
--- /dev/null
+++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AuthInterceptor.java
@@ -0,0 +1,87 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2025 Deutsche Telekom. 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.aai.interceptors.pre;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onap.aai.ResourcesProfiles;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.service.AuthorizationService;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+import lombok.RequiredArgsConstructor;
+
+@Component
+@PreMatching
+@RequiredArgsConstructor
+@Profile(ResourcesProfiles.ONE_WAY_SSL) // this mainly serves the purpose of making the tests work
+@Priority(AAIRequestFilterPriority.AUTHORIZATION)
+public class AuthInterceptor extends AAIContainerFilter implements ContainerRequestFilter {
+
+ private static final Pattern PATTERN_ECHO = Pattern.compile("^.*/util/echo$");
+ private static final Pattern PATTERN_ACTUATOR = Pattern.compile("^.*/actuator/.*$");
+ private static final AAIException AAI_EXCEPTION = new AAIException("AAI_3300");
+ private final AuthorizationService authorizationService;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ String path = requestContext.getUriInfo().getRequestUri().getPath();
+ if (PATTERN_ECHO.matcher(path).matches() || PATTERN_ACTUATOR.matcher(path).matches()) {
+ return;
+ }
+
+ String basicAuth = requestContext.getHeaders().getFirst("Authorization");
+ if (basicAuth == null || !basicAuth.startsWith("Basic ")) {
+ Response errorResponse = errorResponse("AAI_3300", requestContext.getAcceptableMediaTypes());
+ requestContext.abortWith(errorResponse);
+ return;
+ }
+
+ if (!authorizationService.isAuthorized(basicAuth)) {
+ Response errorResponse = errorResponse("AAI_3300", requestContext.getAcceptableMediaTypes());
+ requestContext.abortWith(errorResponse);
+ return;
+ }
+ }
+
+ private Response errorResponse(String errorCode, List<MediaType> acceptHeaderValues) {
+
+ return Response
+ .status(AAI_EXCEPTION.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, AAI_EXCEPTION, new ArrayList<>()))
+ .build();
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/NamespaceInterceptor.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/NamespaceInterceptor.java
index c97e475a..7889a2c9 100644
--- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/NamespaceInterceptor.java
+++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/NamespaceInterceptor.java
@@ -41,7 +41,6 @@ import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
-import org.onap.aai.IncreaseNodesTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -67,7 +66,7 @@ import org.xml.sax.InputSource;
@ConditionalOnProperty(value = "aai.remove-xmlns.enabled", havingValue = "true", matchIfMissing = true)
public class NamespaceInterceptor implements ReaderInterceptor {
- private static final Logger log = LoggerFactory.getLogger(IncreaseNodesTool.class);
+ private static final Logger log = LoggerFactory.getLogger(NamespaceInterceptor.class);
private static final String xslStr = String.join("\n",
"<xsl:transform xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">",
"<xsl:output version=\"1.0\" encoding=\"UTF-8\" indent=\"no\"/>",
diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java
deleted file mode 100644
index b5321052..00000000
--- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T 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.aai.interceptors.pre;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import javax.annotation.Priority;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.container.PreMatching;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.onap.aai.ResourcesProfiles;
-import org.onap.aai.exceptions.AAIException;
-import org.onap.aai.interceptors.AAIContainerFilter;
-import org.onap.aai.logging.ErrorLogHelper;
-import org.onap.aai.service.AuthorizationService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
-
-@Profile(ResourcesProfiles.ONE_WAY_SSL)
-@PreMatching
-@Priority(AAIRequestFilterPriority.AUTHORIZATION)
-public class OneWaySslAuthorization extends AAIContainerFilter implements ContainerRequestFilter {
-
- @Autowired
- private AuthorizationService authorizationService;
-
- @Override
- public void filter(ContainerRequestContext containerRequestContext) throws IOException {
-
- if (containerRequestContext.getUriInfo().getRequestUri().getPath().matches("^.*/util/echo$")) {
- return;
- }
-
- String basicAuth = containerRequestContext.getHeaderString("Authorization");
- List<MediaType> acceptHeaderValues = containerRequestContext.getAcceptableMediaTypes();
-
- if (basicAuth == null || !basicAuth.startsWith("Basic ")) {
- Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues);
- containerRequestContext.abortWith(responseOptional.get());
- return;
- }
-
- basicAuth = basicAuth.replaceAll("Basic ", "");
-
- if (!authorizationService.checkIfUserAuthorized(basicAuth)) {
- Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues);
- containerRequestContext.abortWith(responseOptional.get());
- return;
- }
-
- }
-
- private Optional<Response> errorResponse(String errorCode, List<MediaType> acceptHeaderValues) {
- AAIException aaie = new AAIException(errorCode);
- return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode())
- .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())).build());
-
- }
-}
diff --git a/aai-resources/src/main/java/org/onap/aai/rest/ResourcesController.java b/aai-resources/src/main/java/org/onap/aai/rest/ResourcesController.java
index 12839d48..1f66697e 100644
--- a/aai-resources/src/main/java/org/onap/aai/rest/ResourcesController.java
+++ b/aai-resources/src/main/java/org/onap/aai/rest/ResourcesController.java
@@ -34,8 +34,6 @@ import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang3.ObjectUtils;
-import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
-import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.onap.aai.concurrent.AaiCallable;
import org.onap.aai.introspection.Introspector;
import org.onap.aai.introspection.sideeffect.OwnerCheck;
@@ -65,7 +63,7 @@ public class ResourcesController extends RESTAPI {
@Context HttpHeaders headers,
@Context UriInfo info,
@Context HttpServletRequest req) {
- Set<String> roles = getRoles(req.getUserPrincipal(), req.getMethod());
+ Set<String> roles = Collections.emptySet();
MediaType mediaType = headers.getMediaType();
return resourcesService.handleWrites(mediaType, HttpMethod.PUT, content, versionParam, uri, headers, info, roles);
}
@@ -96,7 +94,7 @@ public class ResourcesController extends RESTAPI {
@Context HttpHeaders headers,
@Context UriInfo info,
@Context HttpServletRequest req) {
- Set<String> roles = getRoles(req.getUserPrincipal(), req.getMethod());
+ Set<String> roles = Collections.emptySet();
MediaType mediaType = MediaType.APPLICATION_JSON_TYPE;
return resourcesService.handleWrites(mediaType, HttpMethod.MERGE_PATCH, content, versionParam, uri, headers, info, roles);
@@ -134,7 +132,7 @@ public class ResourcesController extends RESTAPI {
@Context HttpHeaders headers,
@Context UriInfo info,
@Context HttpServletRequest req) {
- Set<String> roles = getRoles(req.getUserPrincipal(), req.getMethod());
+ Set<String> roles = Collections.emptySet();
Pageable pageable = includeTotalCount == false
? new Pageable(resultIndex -1, resultSize)
: new Pageable(resultIndex -1, resultSize).includeTotalCount();
@@ -159,7 +157,7 @@ public class ResourcesController extends RESTAPI {
@Context UriInfo info,
@QueryParam("resource-version") String resourceVersion,
@Context HttpServletRequest req) {
- Set<String> roles = getRoles(req.getUserPrincipal(), req.getMethod());
+ Set<String> roles = Collections.emptySet();
return resourcesService.delete(versionParam, uri, headers, info, req, roles);
}
@@ -210,29 +208,4 @@ public class ResourcesController extends RESTAPI {
protected boolean isEmptyObject(Introspector obj) {
return "{}".equals(obj.marshal(false));
}
-
- private Set<String> getRoles(Principal userPrincipal, String method) {
- KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) userPrincipal;
- if (ObjectUtils.isEmpty(token)) {
- return Collections.emptySet();
- }
- SimpleKeycloakAccount account = (SimpleKeycloakAccount) token.getDetails();
- if (ObjectUtils.isEmpty(account)) {
- return Collections.emptySet();
- }
- // When the request is not a GET, we need to exclude ReadOnly access roles
- if (isNotGetRequest(method)) {
- return getExcludedReadOnlyAccessRoles(account);
- }
- return account.getRoles();
- }
-
- private Set<String> getExcludedReadOnlyAccessRoles(SimpleKeycloakAccount account) {
- return account.getRoles().stream().filter(role -> !role.endsWith(OwnerCheck.READ_ONLY_SUFFIX))
- .collect(Collectors.toSet());
- }
-
- private boolean isNotGetRequest(String method) {
- return !Action.GET.name().equalsIgnoreCase(method);
- }
}
diff --git a/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java b/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java
deleted file mode 100644
index c63a70a0..00000000
--- a/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright (C) 2019 Nordix Foundation.
- * Modifications Copyright (C) 2019 AT&T Intellectual Property.
- * Modifications Copyright (C) 2020 Bell Canada.
- * ================================================================================
- * 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.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.aai.rest.security;
-
-import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
-import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
-import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
-import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Import;
-import org.springframework.context.annotation.Profile;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.builders.WebSecurity;
-import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
-import org.springframework.security.core.session.SessionRegistryImpl;
-import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
-import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
-import org.springframework.security.web.session.HttpSessionEventPublisher;
-
-@Profile("keycloak")
-@KeycloakConfiguration
-@Import({KeycloakSpringBootConfigResolver.class})
-public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
-
- @Autowired
- public void configureGlobal(AuthenticationManagerBuilder auth) {
- KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
- keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
- auth.authenticationProvider(keycloakAuthenticationProvider);
- }
-
- @Bean
- public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
- return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher());
- }
-
- @Bean
- @Override
- protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
- return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- super.configure(http);
- http.authorizeRequests().antMatchers("/**").permitAll().and().csrf().disable();
- }
-
- @Override
- public void configure(WebSecurity web) {
- web.ignoring().regexMatchers("^.*/util/echo$");
- }
-
-}
diff --git a/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java b/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java
index 0c219a75..7b420b9d 100644
--- a/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java
+++ b/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2025 Deutsche Telekom. 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.
@@ -20,92 +20,45 @@
package org.onap.aai.service;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.Base64;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Stream;
+import java.util.Set;
+import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
-
-import org.eclipse.jetty.util.security.Password;
-import org.onap.aai.ResourcesProfiles;
-import org.onap.aai.util.AAIConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.annotation.Profile;
+import org.onap.aai.config.AuthProperties;
import org.springframework.stereotype.Service;
-@Profile(ResourcesProfiles.ONE_WAY_SSL)
+/**
+ * Should be removed once Spring Security-based auth works
+ */
@Service
public class AuthorizationService {
- private static final Logger logger = LoggerFactory.getLogger(AuthorizationService.class);
-
- private final Map<String, String> authorizedUsers = new HashMap<>();
-
- private static final Base64.Encoder ENCODER = Base64.getEncoder();
-
- @PostConstruct
- public void init() {
-
- String basicAuthFile = getBasicAuthFilePath();
-
- try (Stream<String> stream = Files.lines(Path.of(basicAuthFile))) {
- stream.filter(line -> !line.startsWith("#")).forEach(str -> {
- byte[] bytes = null;
-
- String usernamePassword = null;
- String accessType = null;
-
- try {
- String[] userAccessType = str.split(",");
-
- if (userAccessType == null || userAccessType.length != 2) {
- throw new RuntimeException(
- "Please check the realm.properties file as it is not conforming to the basic auth");
- }
-
- usernamePassword = userAccessType[0];
- accessType = userAccessType[1];
-
- String[] usernamePasswordArray = usernamePassword.split(":");
-
- if (usernamePasswordArray == null || usernamePasswordArray.length != 3) {
- throw new RuntimeException("This username / pwd is not a valid entry in realm.properties");
- }
-
- String username = usernamePasswordArray[0];
- String password = null;
-
- if (str.contains("OBF:")) {
- password = usernamePasswordArray[1] + ":" + usernamePasswordArray[2];
- password = Password.deobfuscate(password);
- }
-
- bytes = ENCODER.encode((username + ":" + password).getBytes("UTF-8"));
-
- authorizedUsers.put(new String(bytes), accessType);
-
- } catch (UnsupportedEncodingException e) {
- logger.error("Unable to support the encoding of the file" + basicAuthFile);
- }
-
- authorizedUsers.put(new String(ENCODER.encode(bytes)), accessType);
- });
- } catch (IOException e) {
- logger.error("IO Exception occurred during the reading of realm.properties", e);
- }
- }
+ // Saved in this format for best performance
+ private final Set<String> authorizedHeaders;
+
+ public AuthorizationService(AuthProperties authProperties) {
+ authorizedHeaders = getAuthorizedHeaders(authProperties);
+ }
+
+ public boolean isAuthorized(String authHeaderValue) {
+ return authorizedHeaders.contains(authHeaderValue);
+ }
+
+ /**
+ * Returns valid Bearer auth headers for all users.
+ * @param authProperties
+ * @param encoder
+ * @return
+ */
+ private Set<String> getAuthorizedHeaders(AuthProperties authProperties) {
+ Base64.Encoder encoder = Base64.getEncoder();
+ return authProperties.getUsers().stream()
+ .map(user -> user.getUsername() + ":" + user.getPassword())
+ .map(usernamePasswordPair -> encoder.encode(usernamePasswordPair.getBytes()))
+ .map(String::new)
+ .map(encodedPair -> "Basic " + encodedPair)
+ .collect(Collectors.toSet());
+ }
- public boolean checkIfUserAuthorized(String authorization) {
- return authorizedUsers.containsKey(authorization) && "admin".equals(authorizedUsers.get(authorization));
- }
- public String getBasicAuthFilePath() {
- return AAIConstants.AAI_HOME_ETC_AUTH + AAIConstants.AAI_FILESEP + "realm.properties";
- }
}
diff --git a/aai-resources/src/main/resources/application-keycloak.properties b/aai-resources/src/main/resources/application-keycloak.properties
deleted file mode 100644
index d398256f..00000000
--- a/aai-resources/src/main/resources/application-keycloak.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-
-spring.autoconfigure.exclude=\
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
-
-multi.tenancy.enabled=true
-keycloak.auth-server-url=http://localhost:8180/auth
-keycloak.realm=aai-resources
-keycloak.resource=aai-resources-app
-keycloak.public-client=true
-keycloak.principal-attribute=preferred_username
-
-keycloak.ssl-required=external
-keycloak.bearer-only=true \ No newline at end of file
diff --git a/aai-resources/src/main/resources/application.properties b/aai-resources/src/main/resources/application.properties
index f0ef368a..c0c805fc 100644
--- a/aai-resources/src/main/resources/application.properties
+++ b/aai-resources/src/main/resources/application.properties
@@ -20,7 +20,6 @@ server.servlet.context-path=/
spring.autoconfigure.exclude=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
- org.keycloak.adapters.springboot.KeycloakAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
@@ -37,21 +36,8 @@ server.tomcat.max-idle-time=60000
# If you get an application startup failure that the port is already taken
# If thats not it, please check if the key-store file path makes sense
server.local.startpath=src/main/resources
-server.basic.auth.location=${server.local.startpath}/etc/auth/realm.properties
-server.certs.location=${server.local.startpath}/etc/auth/
-#server.keystore.name=keystore.jks
-server.keystore.name=aai_keystore
-server.truststore.name=aai_keystore
-server.port=8447
-server.ssl.enabled=false
-server.ssl.enabled-protocols=TLSv1.1,TLSv1.2
-server.ssl.key-store=${server.certs.location}${server.keystore.name}
-server.ssl.key-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
-server.ssl.trust-store=${server.certs.location}${server.truststore.name}
-server.ssl.trust-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
-server.ssl.client-auth=want
-server.ssl.key-store-type=JKS
+server.port=8447
null.db.serialization.enabled=true
@@ -103,10 +89,6 @@ schema.service.nodes.endpoint=nodes?version=
schema.service.edges.endpoint=edgerules?version=
schema.service.versions.endpoint=versions
-schema.service.ssl.key-store=${server.certs.location}${server.keystore.name}
-schema.service.ssl.trust-store=${server.certs.location}${server.truststore.name}
-schema.service.ssl.key-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
-schema.service.ssl.trust-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
schema.service.versions.override=false
#To Expose the Prometheus scraping endpoint
@@ -134,14 +116,6 @@ delta.events.enabled=false
validation.service.client=one-way-ssl
# Base url for the validation service
validation.service.base.url=https://localhost:9501/services/validation-service
-# Client certificate to use to make the request to validation
-validation.service.ssl.key-store=${server.local.startpath}/etc/auth/aai-client-cert.p12
-# Truststore to use to make the request to validation
-validation.service.ssl.trust-store=${server.local.startpath}/etc/auth/tomcat_keystore
-# Client certificate password for the validation
-validation.service.ssl.key-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
-# Truststore password for the validation
-validation.service.ssl.trust-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
# Amount of time that the client should wait in milliseconds before request failing
validation.service.timeout-in-milliseconds=3000
# List of aai node types that should be send to the validation microservice
@@ -163,3 +137,7 @@ aai.actuator.echo.enabled=false
aai.notifications.enabled=false
aai.graph.properties.path=${server.local.startpath}/etc/appprops/janusgraph-realtime.properties
+
+aai.basic-auth.enabled=true
+aai.basic-auth.users[0].username=AAI
+aai.basic-auth.users[0].password=AAI
diff --git a/aai-resources/src/main/resources/etc/appprops/aaiconfig.properties b/aai-resources/src/main/resources/etc/appprops/aaiconfig.properties
index ecbbcb1c..cd197341 100644
--- a/aai-resources/src/main/resources/etc/appprops/aaiconfig.properties
+++ b/aai-resources/src/main/resources/etc/appprops/aaiconfig.properties
@@ -48,11 +48,6 @@ aai.server.url.base=https://localhost:8443/aai/
aai.server.url=https://localhost:8443/aai/v20/
aai.global.callback.url=https://localhost:8443/aai/
-aai.truststore.filename=aai_keystore
-aai.truststore.passwd.x=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
-aai.keystore.filename=aai-client-cert.p12
-aai.keystore.passwd.x=
-
aai.notification.current.version=v20
aai.notificationEvent.default.status=UNPROCESSED
aai.notificationEvent.default.eventType=AAI-EVENT