Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#1078] split request signing factories into different factories for …
…http push and amqp Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
- Loading branch information
Showing
28 changed files
with
531 additions
and
189 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
...ce/src/main/java/org/eclipse/ditto/connectivity/service/config/WithStringMapDecoding.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
|
||
package org.eclipse.ditto.connectivity.service.config; | ||
|
||
import java.text.MessageFormat; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
import org.eclipse.ditto.internal.utils.config.DittoConfigError; | ||
import org.eclipse.ditto.internal.utils.config.ScopedConfig; | ||
|
||
import com.typesafe.config.Config; | ||
import com.typesafe.config.ConfigException; | ||
|
||
/** | ||
* Interface providing functionality to decode a config entry to a {@code Map<String, String>}. | ||
*/ | ||
public interface WithStringMapDecoding { | ||
|
||
/** | ||
* Decode the value at {@code path} in {@code config} to a {@link Map}. | ||
* | ||
* @param config the config. | ||
* @param path the path at which the Map should be located. | ||
* @return the {@link Map} containing the values. | ||
* @throws DittoConfigError if the value at {@code path} was missing or no Map from string to string. | ||
*/ | ||
default Map<String, String> asStringMap(final ScopedConfig config, final String path) { | ||
try { | ||
final Config stringMapConfig = config.getConfig(path); | ||
final Map<String, String> map = stringMapConfig.root().entrySet().stream() | ||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> (String) entry.getValue().unwrapped())); | ||
return Collections.unmodifiableMap(map); | ||
} catch (final ClassCastException | ConfigException e) { | ||
final String errorMessage = | ||
MessageFormat.format("Key <{0}> in config <{1}> must contain a map from string to string", | ||
path, config.getConfigPath()); | ||
throw new DittoConfigError(errorMessage); | ||
} | ||
} | ||
|
||
} |
44 changes: 44 additions & 0 deletions
44
...ain/java/org/eclipse/ditto/connectivity/service/messaging/amqp/AmqpConnectionSigning.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.ditto.connectivity.service.messaging.amqp; | ||
|
||
import java.time.Instant; | ||
import java.util.Optional; | ||
|
||
import org.eclipse.ditto.connectivity.model.UserPasswordCredentials; | ||
import org.eclipse.ditto.connectivity.service.messaging.signing.Signing; | ||
|
||
/** | ||
* Functional interface for preparing signing information for AMQP connection. | ||
*/ | ||
@FunctionalInterface | ||
public interface AmqpConnectionSigning extends Signing { | ||
|
||
/** | ||
* Creates signed credentials for a connection if applicable. | ||
* | ||
* @return an {@link Optional} containing the signed credentials if applicable, otherwise an empty {@link Optional}. | ||
*/ | ||
default Optional<UserPasswordCredentials> createSignedCredentials() { | ||
return createSignedCredentials(Instant.now()); | ||
} | ||
|
||
/** | ||
* Creates signed credentials for a connection if applicable. | ||
* | ||
* @param timestamp Timestamp to include in the signature. | ||
* @return an {@link Optional} containing the signed credentials if applicable, otherwise an empty {@link Optional}. | ||
*/ | ||
Optional<UserPasswordCredentials> createSignedCredentials(Instant timestamp); | ||
|
||
} |
118 changes: 118 additions & 0 deletions
118
...org/eclipse/ditto/connectivity/service/messaging/amqp/AmqpConnectionSigningExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.ditto.connectivity.service.messaging.amqp; | ||
|
||
import java.util.Collections; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
import org.eclipse.ditto.connectivity.model.ClientCertificateCredentials; | ||
import org.eclipse.ditto.connectivity.model.CredentialsVisitor; | ||
import org.eclipse.ditto.connectivity.model.HmacCredentials; | ||
import org.eclipse.ditto.connectivity.model.MessageSendingFailedException; | ||
import org.eclipse.ditto.connectivity.model.SshPublicKeyCredentials; | ||
import org.eclipse.ditto.connectivity.model.UserPasswordCredentials; | ||
import org.eclipse.ditto.connectivity.service.config.Amqp10Config; | ||
import org.eclipse.ditto.connectivity.service.config.DittoConnectivityConfig; | ||
import org.eclipse.ditto.connectivity.service.messaging.signing.NoOpSigning; | ||
import org.eclipse.ditto.internal.utils.config.DefaultScopedConfig; | ||
|
||
import com.typesafe.config.Config; | ||
|
||
import akka.actor.AbstractExtensionId; | ||
import akka.actor.ActorSystem; | ||
import akka.actor.ExtendedActorSystem; | ||
import akka.actor.Extension; | ||
import scala.collection.immutable.List$; | ||
import scala.reflect.ClassTag; | ||
|
||
/** | ||
* Actor system extension to load the configured connection signing algorithms. | ||
*/ | ||
public final class AmqpConnectionSigningExtension implements Extension, CredentialsVisitor<AmqpConnectionSigning> { | ||
|
||
private static final Id ID = new Id(); | ||
|
||
private final Map<String, AmqpConnectionSigningFactory> registry; | ||
|
||
private AmqpConnectionSigningExtension(final Map<String, AmqpConnectionSigningFactory> registry) { | ||
this.registry = registry; | ||
} | ||
|
||
/** | ||
* Lookup this actor system extension. | ||
* | ||
* @param system the actor system. | ||
* @return this extension. | ||
*/ | ||
public static AmqpConnectionSigningExtension get(final ActorSystem system) { | ||
return ID.get(system); | ||
} | ||
|
||
@Override | ||
public AmqpConnectionSigning clientCertificate(final ClientCertificateCredentials credentials) { | ||
return NoOpSigning.INSTANCE; | ||
} | ||
|
||
@Override | ||
public AmqpConnectionSigning usernamePassword(final UserPasswordCredentials credentials) { | ||
return NoOpSigning.INSTANCE; | ||
} | ||
|
||
@Override | ||
public AmqpConnectionSigning sshPublicKeyAuthentication(final SshPublicKeyCredentials credentials) { | ||
return NoOpSigning.INSTANCE; | ||
} | ||
|
||
@Override | ||
public AmqpConnectionSigning hmac(final HmacCredentials credentials) { | ||
final AmqpConnectionSigningFactory factory = registry.get(credentials.getAlgorithm()); | ||
if (factory != null) { | ||
return factory.createAmqpConnectionSigning(credentials); | ||
} else { | ||
throw MessageSendingFailedException.newBuilder() | ||
.message("Failed to sign AMQP 1.0 connection.") | ||
.description(String.format("The configured algorithm '%s' does not exist. Fix this by adding an" + | ||
" implementation for it in the '%s' section of the amqp config.", | ||
credentials.getAlgorithm(), Amqp10Config.Amqp10ConfigValue.HMAC_ALGORITHMS.getConfigPath())) | ||
.build(); | ||
} | ||
} | ||
|
||
/** | ||
* The extension ID. | ||
*/ | ||
public static final class Id extends AbstractExtensionId<AmqpConnectionSigningExtension> { | ||
|
||
private static AmqpConnectionSigningFactory instantiate(final ExtendedActorSystem system, final String className) { | ||
final ClassTag<AmqpConnectionSigningFactory> tag = | ||
scala.reflect.ClassTag$.MODULE$.apply(AmqpConnectionSigningFactory.class); | ||
return system.dynamicAccess().createInstanceFor(className, List$.MODULE$.empty(), tag).get(); | ||
} | ||
|
||
@Override | ||
public AmqpConnectionSigningExtension createExtension(final ExtendedActorSystem system) { | ||
final Config config = system.settings().config(); | ||
final Map<String, String> hmacAlgorithms = | ||
DittoConnectivityConfig.of(DefaultScopedConfig.dittoScoped(config)) | ||
.getConnectionConfig() | ||
.getAmqp10Config() | ||
.getHmacAlgorithms(); | ||
final Map<String, AmqpConnectionSigningFactory> factoryMap = hmacAlgorithms.entrySet() | ||
.stream() | ||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> instantiate(system, entry.getValue()))); | ||
return new AmqpConnectionSigningExtension(Collections.unmodifiableMap(factoryMap)); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.