mirror of
https://github.com/jlengrand/helidon.git
synced 2026-03-10 00:11:20 +00:00
Support for overriding configuration of security providers using simple properties. (#2511)
Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
This commit is contained in:
@@ -138,6 +138,21 @@ security:
|
||||
roles: ["user"]
|
||||
----
|
||||
|
||||
==== Overriding configuration
|
||||
When a configuration needs to be overridden, we may have problems with the list
|
||||
type of the `providers` configuration. To simplify overrides using properties,
|
||||
you can explicitly setup a type of provider using a `type` key.
|
||||
|
||||
Example:
|
||||
[source,properties]
|
||||
----
|
||||
security.providers.1.type=header-atn
|
||||
security.providers.1.header-atn.authenticate=false
|
||||
----
|
||||
|
||||
Would explicitly override the second provider (`http-basic-auth` in example above) with
|
||||
`header-atn` provider. Note that the `type` and the key of the provider must match.
|
||||
|
||||
=== Hybrid pattern (Builder & Configuration)
|
||||
|
||||
[source,java]
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.util.stream.Collectors;
|
||||
import io.helidon.common.configurable.ThreadPoolSupplier;
|
||||
import io.helidon.common.serviceloader.HelidonServiceLoader;
|
||||
import io.helidon.config.Config;
|
||||
import io.helidon.config.ConfigValue;
|
||||
import io.helidon.security.internal.SecurityAuditEvent;
|
||||
import io.helidon.security.spi.AuditProvider;
|
||||
import io.helidon.security.spi.AuthenticationProvider;
|
||||
@@ -80,6 +81,7 @@ public class Security {
|
||||
|
||||
private static final Set<String> RESERVED_PROVIDER_KEYS = Set.of(
|
||||
"name",
|
||||
"type",
|
||||
"class",
|
||||
"is-authentication-provider",
|
||||
"is-authorization-provider",
|
||||
@@ -951,7 +953,9 @@ public class Security {
|
||||
}
|
||||
|
||||
private void providerFromConfig(Map<String, SecurityProviderService> configKeyToService,
|
||||
Map<String, SecurityProviderService> classNameToService, String knownKeys, Config pConf) {
|
||||
Map<String, SecurityProviderService> classNameToService,
|
||||
String knownKeys,
|
||||
Config pConf) {
|
||||
AtomicReference<SecurityProviderService> service = new AtomicReference<>();
|
||||
AtomicReference<Config> providerSpecific = new AtomicReference<>();
|
||||
|
||||
@@ -1053,24 +1057,38 @@ public class Security {
|
||||
Config pConf,
|
||||
AtomicReference<SecurityProviderService> service,
|
||||
AtomicReference<Config> providerSpecific) {
|
||||
// everything else is based on provider specific configuration
|
||||
pConf.asNodeList().get().stream().filter(this::notReservedProviderKey).forEach(providerSpecificConf -> {
|
||||
if (!providerSpecific.compareAndSet(null, providerSpecificConf)) {
|
||||
throw new SecurityException("More than one provider configurations found, each provider can only"
|
||||
+ " have one provider specific config. Conflict: "
|
||||
+ providerSpecific.get().key()
|
||||
+ " and " + providerSpecificConf.key());
|
||||
}
|
||||
|
||||
String keyName = providerSpecificConf.name();
|
||||
if (configKeyToService.containsKey(keyName)) {
|
||||
service.set(configKeyToService.get(keyName));
|
||||
} else {
|
||||
throw new SecurityException("Configuration key " + providerSpecificConf.key()
|
||||
+ " is not a valid provider configuration. Supported keys: "
|
||||
+ knownKeys);
|
||||
}
|
||||
});
|
||||
ConfigValue<String> type = pConf.get("type").asString();
|
||||
if (type.isPresent()) {
|
||||
// explicit type, ignore search below
|
||||
findProviderService(service, configKeyToService, type.get(), knownKeys);
|
||||
providerSpecific.set(pConf.get(type.get()));
|
||||
} else {
|
||||
// everything else is based on provider specific configuration
|
||||
pConf.asNodeList().get().stream().filter(this::notReservedProviderKey).forEach(providerSpecificConf -> {
|
||||
if (!providerSpecific.compareAndSet(null, providerSpecificConf)) {
|
||||
throw new SecurityException("More than one provider configurations found, each provider can only"
|
||||
+ " have one provider specific config. Conflict: "
|
||||
+ providerSpecific.get().key()
|
||||
+ " and " + providerSpecificConf.key());
|
||||
}
|
||||
|
||||
findProviderService(service, configKeyToService, providerSpecificConf.name(), knownKeys);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void findProviderService(AtomicReference<SecurityProviderService> service,
|
||||
Map<String, SecurityProviderService> configKeyToService,
|
||||
String name,
|
||||
String knownKeys) {
|
||||
if (configKeyToService.containsKey(name)) {
|
||||
service.set(configKeyToService.get(name));
|
||||
} else {
|
||||
throw new SecurityException("Configuration key " + name
|
||||
+ " is not a valid provider configuration. Supported keys: "
|
||||
+ knownKeys);
|
||||
}
|
||||
}
|
||||
|
||||
private String loadProviderServices(Map<String, SecurityProviderService> configKeyToService,
|
||||
|
||||
67
tests/integration/security/gh2455/pom.xml
Normal file
67
tests/integration/security/gh2455/pom.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
~
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>helidon-tests-integration-security</artifactId>
|
||||
<groupId>io.helidon.tests.integration</groupId>
|
||||
<version>2.1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>helidon-tests-integration-security-gh2455</artifactId>
|
||||
<name>Helidon Tests Integration Security GH-2455</name>
|
||||
|
||||
<description>
|
||||
Integration test for issue https://github.com/oracle/helidon/issues/2455
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.helidon.security</groupId>
|
||||
<artifactId>helidon-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-http-auth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-header</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-abac</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.config</groupId>
|
||||
<artifactId>helidon-config-yaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
security:
|
||||
providers:
|
||||
- abac:
|
||||
- http-basic-auth:
|
||||
realm: "helidon"
|
||||
users:
|
||||
- login: "tomas"
|
||||
password: "password"
|
||||
roles: ["admin"]
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package io.helidon.tests.integration.security.gh2455;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.helidon.config.Config;
|
||||
import io.helidon.config.ConfigSources;
|
||||
import io.helidon.security.Security;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class TestProviderOverrides {
|
||||
@Test
|
||||
void testOverride() {
|
||||
Map<String, String> map = Map.of(
|
||||
"security.providers.1.type", "header-atn",
|
||||
"security.providers.1.header-atn.authenticate", "false"
|
||||
);
|
||||
Config config = Config.builder()
|
||||
.addSource(ConfigSources.create(map))
|
||||
.addSource(ConfigSources.classpath("application.yaml"))
|
||||
.disableEnvironmentVariablesSource()
|
||||
.disableSystemPropertiesSource()
|
||||
.build();
|
||||
|
||||
Security security = Security.create(config.get("security"));
|
||||
}
|
||||
}
|
||||
@@ -37,5 +37,6 @@
|
||||
<modules>
|
||||
<module>gh1487</module>
|
||||
<module>gh2297</module>
|
||||
<module>gh2455</module>
|
||||
</modules>
|
||||
</project>
|
||||
Reference in New Issue
Block a user