This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit 116c8c11a8f6414233d4d5de6b05114f79f3dab0 Author: Andrea Cosentino <anco...@gmail.com> AuthorDate: Fri Feb 9 11:48:42 2018 +0100 CAMEL-12237 - Camel-AWS: Create a KMS component --- components/camel-aws/pom.xml | 1 + .../camel-aws/src/main/docs/aws-kms-component.adoc | 130 ++++++++ .../camel/component/aws/kms/KMSComponent.java | 118 ++++++++ .../aws/kms/KMSComponentVerifierExtension.java | 87 ++++++ .../camel/component/aws/kms/KMSConfiguration.java | 137 +++++++++ .../camel/component/aws/kms/KMSConstants.java | 28 ++ .../camel/component/aws/kms/KMSEndpoint.java | 111 +++++++ .../camel/component/aws/kms/KMSOperations.java | 24 ++ .../camel/component/aws/kms/KMSProducer.java | 146 +++++++++ .../services/org/apache/camel/component/aws-kms | 18 ++ .../component/aws/kms/AmazonKMSClientMock.java | 336 +++++++++++++++++++++ .../aws/kms/KMSComponentConfigurationTest.java | 51 ++++ .../aws/kms/KMSComponentVerifierExtensionTest.java | 73 +++++ .../component/aws/kms/KMSProducerSpringTest.java | 91 ++++++ .../camel/component/aws/kms/KMSProducerTest.java | 116 +++++++ .../aws/kms/KMSComponentSpringTest-context.xml | 45 +++ .../springboot/KMSComponentAutoConfiguration.java | 128 ++++++++ .../kms/springboot/KMSComponentConfiguration.java | 179 +++++++++++ .../src/main/resources/META-INF/spring.factories | 4 +- 19 files changed, 1822 insertions(+), 1 deletion(-) diff --git a/components/camel-aws/pom.xml b/components/camel-aws/pom.xml index 379d309..a48a366 100644 --- a/components/camel-aws/pom.xml +++ b/components/camel-aws/pom.xml @@ -40,6 +40,7 @@ org.apache.camel.spi.ComponentResolver;component=aws-ec2, org.apache.camel.spi.ComponentResolver;component=aws-kinesis, org.apache.camel.spi.ComponentResolver;component=aws-kinesis-firehose, + org.apache.camel.spi.ComponentResolver;component=aws-kms, org.apache.camel.spi.ComponentResolver;component=aws-lambda, org.apache.camel.spi.ComponentResolver;component=aws-mq, org.apache.camel.spi.ComponentResolver;component=aws-s3, diff --git a/components/camel-aws/src/main/docs/aws-kms-component.adoc b/components/camel-aws/src/main/docs/aws-kms-component.adoc new file mode 100644 index 0000000..fa894ab --- /dev/null +++ b/components/camel-aws/src/main/docs/aws-kms-component.adoc @@ -0,0 +1,130 @@ +== AWS KMS Component +== AWS MQ Component + +*Available as of Camel version 2.21* + +The KMS component supports create, run, start, stop and terminate +https://aws.amazon.com/it/kms/[AWS KMS] instances. + +Prerequisites + +You must have a valid Amazon Web Services developer account, and be +signed up to use Amazon KMS. More information are available at +https://aws.amazon.com/it/mq/[Amazon KMS]. + +### URI Format + +[source,java] +------------------------- +aws-kms://label[?options] +------------------------- + +You can append query options to the URI in the following format, +?options=value&option2=value&... + +### URI Options + + +// component options: START +The AWS KMS component supports 5 options which are listed below. + + + +[width="100%",cols="2,5,^1,2",options="header"] +|=== +| Name | Description | Default | Type +| *configuration* (advanced) | The AWS MQ default configuration | | KMSConfiguration +| *accessKey* (producer) | Amazon AWS Access Key | | String +| *secretKey* (producer) | Amazon AWS Secret Key | | String +| *region* (producer) | The region in which MQ client needs to work | | String +| *resolveProperty Placeholders* (advanced) | Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. | true | boolean +|=== +// component options: END + + + + +// endpoint options: START +The AWS KMS endpoint is configured using URI syntax: + +---- +aws-kms:label +---- + +with the following path and query parameters: + +==== Path Parameters (1 parameters): + +[width="100%",cols="2,5,^1,2",options="header"] +|=== +| Name | Description | Default | Type +| *label* | *Required* Logical name | | String +|=== + +==== Query Parameters (8 parameters): + +[width="100%",cols="2,5,^1,2",options="header"] +|=== +| Name | Description | Default | Type +| *accessKey* (producer) | Amazon AWS Access Key | | String +| *kmsClient* (producer) | To use a existing configured AWS KMS as client | | AWSKMS +| *operation* (producer) | *Required* The operation to perform | | KMSOperations +| *proxyHost* (producer) | To define a proxy host when instantiating the KMS client | | String +| *proxyPort* (producer) | To define a proxy port when instantiating the KMS client | | Integer +| *region* (producer) | The region in which KMS client needs to work | | String +| *secretKey* (producer) | Amazon AWS Secret Key | | String +| *synchronous* (advanced) | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | false | boolean +|=== +// endpoint options: END + + + +Required EC2 component options + +You have to provide the amazonEc2Client in the +link:registry.html[Registry] or your accessKey and secretKey to access +the https://aws.amazon.com/it/ec2/[Amazon EC2] service. + +### Usage + +#### Message headers evaluated by the MQ producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Header |Type |Description + +|`CamelAwsKMSLimit` |`Integer` |The limit number of keys to return while performing a listKeys operation + +|`CamelAwsKMSOperation` |`String` |The operation we want to perform + +|`CamelAwsKMSDescription` |`String` |A key description to use while performing a createKey operation + +|`CamelAwsKMSKeyId` |`String` |The key Id +|======================================================================= + +Dependencies + +Maven users will need to add the following dependency to their pom.xml. + +*pom.xml* + +[source,xml] +--------------------------------------- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-aws</artifactId> + <version>${camel-version}</version> +</dependency> +--------------------------------------- + +where `${camel-version`} must be replaced by the actual version of Camel +(2.16 or higher). + +### See Also + +* link:configuring-camel.html[Configuring Camel] +* link:component.html[Component] +* link:endpoint.html[Endpoint] +* link:getting-started.html[Getting Started] + +* link:aws.html[AWS Component] diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSComponent.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSComponent.java new file mode 100644 index 0000000..513374b --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSComponent.java @@ -0,0 +1,118 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.spi.Metadata; +import org.apache.camel.util.ObjectHelper; + +/** + * For working with Amazon KMS. + */ +public class KMSComponent extends DefaultComponent { + + @Metadata + private String accessKey; + @Metadata + private String secretKey; + @Metadata + private String region; + @Metadata(label = "advanced") + private KMSConfiguration configuration; + + public KMSComponent() { + this(null); + } + + public KMSComponent(CamelContext context) { + super(context); + + this.configuration = new KMSConfiguration(); + registerExtension(new KMSComponentVerifierExtension()); + } + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + KMSConfiguration configuration = this.configuration.copy(); + setProperties(configuration, parameters); + + if (ObjectHelper.isEmpty(configuration.getAccessKey())) { + setAccessKey(accessKey); + } + if (ObjectHelper.isEmpty(configuration.getSecretKey())) { + setSecretKey(secretKey); + } + if (ObjectHelper.isEmpty(configuration.getRegion())) { + setRegion(region); + } + if (configuration.getKmsClient() == null && (configuration.getAccessKey() == null || configuration.getSecretKey() == null)) { + throw new IllegalArgumentException("Amazon kms client or accessKey and secretKey must be specified"); + } + + KMSEndpoint endpoint = new KMSEndpoint(uri, this, configuration); + return endpoint; + } + + public KMSConfiguration getConfiguration() { + return configuration; + } + + /** + * The AWS MQ default configuration + */ + public void setConfiguration(KMSConfiguration configuration) { + this.configuration = configuration; + } + + public String getAccessKey() { + return configuration.getAccessKey(); + } + + /** + * Amazon AWS Access Key + */ + public void setAccessKey(String accessKey) { + configuration.setAccessKey(accessKey); + } + + public String getSecretKey() { + return configuration.getSecretKey(); + } + + /** + * Amazon AWS Secret Key + */ + public void setSecretKey(String secretKey) { + configuration.setSecretKey(secretKey); + } + + public String getRegion() { + return configuration.getRegion(); + } + + /** + * The region in which MQ client needs to work + */ + public void setRegion(String region) { + configuration.setRegion(region); + } + +} diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSComponentVerifierExtension.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSComponentVerifierExtension.java new file mode 100644 index 0000000..c81548f --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSComponentVerifierExtension.java @@ -0,0 +1,87 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import java.util.Map; + +import com.amazonaws.SdkClientException; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.kms.AWSKMS; +import com.amazonaws.services.kms.AWSKMSClientBuilder; + +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; + +public class KMSComponentVerifierExtension extends DefaultComponentVerifierExtension { + + public KMSComponentVerifierExtension() { + this("aws-kms"); + } + + public KMSComponentVerifierExtension(String scheme) { + super(scheme); + } + + // ********************************* + // Parameters validation + // ********************************* + + @Override + protected Result verifyParameters(Map<String, Object> parameters) { + + ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS).error(ResultErrorHelper.requiresOption("accessKey", parameters)) + .error(ResultErrorHelper.requiresOption("secretKey", parameters)).error(ResultErrorHelper.requiresOption("region", parameters)); + + // Validate using the catalog + + super.verifyParametersAgainstCatalog(builder, parameters); + + return builder.build(); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Override + protected Result verifyConnectivity(Map<String, Object> parameters) { + ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY); + + try { + KMSConfiguration configuration = setProperties(new KMSConfiguration(), parameters); + AWSCredentials credentials = new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey()); + AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials); + AWSKMS client = AWSKMSClientBuilder.standard().withCredentials(credentialsProvider).withRegion(Regions.valueOf(configuration.getRegion())).build(); + client.listKeys(); + } catch (SdkClientException e) { + ResultErrorBuilder errorBuilder = ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.AUTHENTICATION, e.getMessage()) + .detail("aws_kms_exception_message", e.getMessage()).detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, e.getClass().getName()) + .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, e); + + builder.error(errorBuilder.build()); + } catch (Exception e) { + builder.error(ResultErrorBuilder.withException(e).build()); + } + return builder.build(); + } +} diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSConfiguration.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSConfiguration.java new file mode 100644 index 0000000..f5b7f86 --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSConfiguration.java @@ -0,0 +1,137 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import com.amazonaws.services.kms.AWSKMS; + +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriParams; +import org.apache.camel.spi.UriPath; + +@UriParams +public class KMSConfiguration implements Cloneable { + + @UriPath(description = "Logical name") + @Metadata(required = "true") + private String label; + @UriParam(label = "producer") + private AWSKMS kmsClient; + @UriParam(label = "producer", secret = true) + private String accessKey; + @UriParam(label = "producer", secret = true) + private String secretKey; + @UriParam(label = "producer") + @Metadata(required = "true") + private KMSOperations operation; + @UriParam(label = "producer") + private String proxyHost; + @UriParam(label = "producer") + private Integer proxyPort; + @UriParam + private String region; + + public AWSKMS getKmsClient() { + return kmsClient; + } + + /** + * To use a existing configured AWS KMS as client + */ + public void setKmsClient(AWSKMS kmsClient) { + this.kmsClient = kmsClient; + } + + public String getAccessKey() { + return accessKey; + } + + /** + * Amazon AWS Access Key + */ + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + /** + * Amazon AWS Secret Key + */ + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public KMSOperations getOperation() { + return operation; + } + + /** + * The operation to perform + */ + public void setOperation(KMSOperations operation) { + this.operation = operation; + } + + /** + * To define a proxy host when instantiating the KMS client + */ + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + /** + * To define a proxy port when instantiating the KMS client + */ + public Integer getProxyPort() { + return proxyPort; + } + + public void setProxyPort(Integer proxyPort) { + this.proxyPort = proxyPort; + } + + /** + * The region in which KMS client needs to work + */ + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + // ************************************************* + // + // ************************************************* + + public KMSConfiguration copy() { + try { + return (KMSConfiguration)super.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeCamelException(e); + } + } +} diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSConstants.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSConstants.java new file mode 100644 index 0000000..2900e8c --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSConstants.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +/** + * Constants used in Camel AWS MQ module + * + */ +public interface KMSConstants { + String OPERATION = "CamelAwsKMSOperation"; + String LIMIT = "CamelAwsKMSLimit"; + String DESCRIPTION = "CamelAwsKMSDescription"; + String KEY_ID = "CamelAwsKMSKeyId"; +} diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSEndpoint.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSEndpoint.java new file mode 100644 index 0000000..4d7cb69 --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSEndpoint.java @@ -0,0 +1,111 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import com.amazonaws.ClientConfiguration; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.kms.AWSKMS; +import com.amazonaws.services.kms.AWSKMSClientBuilder; + +import org.apache.camel.Component; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.impl.ScheduledPollEndpoint; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriParam; +import org.apache.camel.util.ObjectHelper; + +/** + * The aws-mq is used for managing Amazon KMS + */ +@UriEndpoint(firstVersion = "2.21.0", scheme = "aws-kms", title = "AWS KMS", syntax = "aws-kms:label", producerOnly = true, label = "cloud,management") +public class KMSEndpoint extends ScheduledPollEndpoint { + + private AWSKMS kmsClient; + + @UriParam + private KMSConfiguration configuration; + + public KMSEndpoint(String uri, Component component, KMSConfiguration configuration) { + super(uri, component); + this.configuration = configuration; + } + + public Consumer createConsumer(Processor processor) throws Exception { + throw new UnsupportedOperationException("You cannot receive messages from this endpoint"); + } + + public Producer createProducer() throws Exception { + return new KMSProducer(this); + } + + public boolean isSingleton() { + return true; + } + + @Override + public void doStart() throws Exception { + super.doStart(); + + kmsClient = configuration.getKmsClient() != null ? configuration.getKmsClient() : createKMSClient(); + } + + public KMSConfiguration getConfiguration() { + return configuration; + } + + public AWSKMS getKmsClient() { + return kmsClient; + } + + AWSKMS createKMSClient() { + AWSKMS client = null; + ClientConfiguration clientConfiguration = null; + AWSKMSClientBuilder clientBuilder = null; + boolean isClientConfigFound = false; + if (ObjectHelper.isNotEmpty(configuration.getProxyHost()) && ObjectHelper.isNotEmpty(configuration.getProxyPort())) { + clientConfiguration = new ClientConfiguration(); + clientConfiguration.setProxyHost(configuration.getProxyHost()); + clientConfiguration.setProxyPort(configuration.getProxyPort()); + isClientConfigFound = true; + } + if (configuration.getAccessKey() != null && configuration.getSecretKey() != null) { + AWSCredentials credentials = new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey()); + AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials); + if (isClientConfigFound) { + clientBuilder = AWSKMSClientBuilder.standard().withClientConfiguration(clientConfiguration).withCredentials(credentialsProvider); + } else { + clientBuilder = AWSKMSClientBuilder.standard().withCredentials(credentialsProvider); + } + } else { + if (isClientConfigFound) { + clientBuilder = AWSKMSClientBuilder.standard(); + } else { + clientBuilder = AWSKMSClientBuilder.standard().withClientConfiguration(clientConfiguration); + } + } + if (ObjectHelper.isNotEmpty(configuration.getRegion())) { + clientBuilder = clientBuilder.withRegion(configuration.getRegion()); + } + client = clientBuilder.build(); + return client; + } +} diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSOperations.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSOperations.java new file mode 100644 index 0000000..cdbef53 --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSOperations.java @@ -0,0 +1,24 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +public enum KMSOperations { + + listKeys, + createKey, + disableKey +} diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSProducer.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSProducer.java new file mode 100644 index 0000000..f845233 --- /dev/null +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/kms/KMSProducer.java @@ -0,0 +1,146 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import com.amazonaws.AmazonServiceException; +import com.amazonaws.services.kms.AWSKMS; +import com.amazonaws.services.kms.model.CreateKeyRequest; +import com.amazonaws.services.kms.model.CreateKeyResult; +import com.amazonaws.services.kms.model.DisableKeyRequest; +import com.amazonaws.services.kms.model.DisableKeyResult; +import com.amazonaws.services.kms.model.ListKeysRequest; +import com.amazonaws.services.kms.model.ListKeysResult; + +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.impl.DefaultProducer; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.URISupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.camel.component.aws.common.AwsExchangeUtil.getMessageForResponse; + +/** + * A Producer which sends messages to the Amazon KMS Service + * <a href="http://aws.amazon.com/kms/">AWS KMS</a> + */ +public class KMSProducer extends DefaultProducer { + + private static final Logger LOG = LoggerFactory.getLogger(KMSProducer.class); + + private transient String kmsProducerToString; + + public KMSProducer(Endpoint endpoint) { + super(endpoint); + } + + public void process(Exchange exchange) throws Exception { + switch (determineOperation(exchange)) { + case listKeys: + listKeys(getEndpoint().getKmsClient(), exchange); + break; + case createKey: + createKey(getEndpoint().getKmsClient(), exchange); + break; + case disableKey: + disableKey(getEndpoint().getKmsClient(), exchange); + break; + default: + throw new IllegalArgumentException("Unsupported operation"); + } + } + + private KMSOperations determineOperation(Exchange exchange) { + KMSOperations operation = exchange.getIn().getHeader(KMSConstants.OPERATION, KMSOperations.class); + if (operation == null) { + operation = getConfiguration().getOperation(); + } + return operation; + } + + protected KMSConfiguration getConfiguration() { + return getEndpoint().getConfiguration(); + } + + @Override + public String toString() { + if (kmsProducerToString == null) { + kmsProducerToString = "KMSProducer[" + URISupport.sanitizeUri(getEndpoint().getEndpointUri()) + "]"; + } + return kmsProducerToString; + } + + @Override + public KMSEndpoint getEndpoint() { + return (KMSEndpoint)super.getEndpoint(); + } + + private void listKeys(AWSKMS kmsClient, Exchange exchange) { + ListKeysRequest request = new ListKeysRequest(); + if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KMSConstants.LIMIT))) { + int limit = exchange.getIn().getHeader(KMSConstants.LIMIT, Integer.class); + request.withLimit(limit); + } + ListKeysResult result; + try { + result = kmsClient.listKeys(request); + } catch (AmazonServiceException ase) { + LOG.trace("List Keys command returned the error code {}", ase.getErrorCode()); + throw ase; + } + Message message = getMessageForResponse(exchange); + message.setBody(result); + } + + private void createKey(AWSKMS kmsClient, Exchange exchange) { + CreateKeyRequest request = new CreateKeyRequest(); + if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KMSConstants.DESCRIPTION))) { + String description = exchange.getIn().getHeader(KMSConstants.DESCRIPTION, String.class); + request.withDescription(description); + } + CreateKeyResult result; + try { + result = kmsClient.createKey(request); + } catch (AmazonServiceException ase) { + LOG.trace("Create Key command returned the error code {}", ase.getErrorCode()); + throw ase; + } + Message message = getMessageForResponse(exchange); + message.setBody(result); + } + + private void disableKey(AWSKMS kmsClient, Exchange exchange) { + DisableKeyRequest request = new DisableKeyRequest(); + if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KMSConstants.KEY_ID))) { + String keyId = exchange.getIn().getHeader(KMSConstants.KEY_ID, String.class); + request.withKeyId(keyId); + } else { + throw new IllegalArgumentException("Key Id must be specified"); + } + DisableKeyResult result; + try { + result = kmsClient.disableKey(request); + } catch (AmazonServiceException ase) { + LOG.trace("Disable Key command returned the error code {}", ase.getErrorCode()); + throw ase; + } + Message message = getMessageForResponse(exchange); + message.setBody(result); + } +} \ No newline at end of file diff --git a/components/camel-aws/src/main/resources/META-INF/services/org/apache/camel/component/aws-kms b/components/camel-aws/src/main/resources/META-INF/services/org/apache/camel/component/aws-kms new file mode 100644 index 0000000..3a89cd7 --- /dev/null +++ b/components/camel-aws/src/main/resources/META-INF/services/org/apache/camel/component/aws-kms @@ -0,0 +1,18 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You 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. +## --------------------------------------------------------------------------- + +class=org.apache.camel.component.aws.kms.KMSComponent diff --git a/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/AmazonKMSClientMock.java b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/AmazonKMSClientMock.java new file mode 100644 index 0000000..48b2bff --- /dev/null +++ b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/AmazonKMSClientMock.java @@ -0,0 +1,336 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import java.util.ArrayList; +import java.util.List; + +import com.amazonaws.AmazonWebServiceRequest; +import com.amazonaws.ResponseMetadata; +import com.amazonaws.regions.Region; +import com.amazonaws.services.kms.AWSKMS; +import com.amazonaws.services.kms.model.CancelKeyDeletionRequest; +import com.amazonaws.services.kms.model.CancelKeyDeletionResult; +import com.amazonaws.services.kms.model.CreateAliasRequest; +import com.amazonaws.services.kms.model.CreateAliasResult; +import com.amazonaws.services.kms.model.CreateGrantRequest; +import com.amazonaws.services.kms.model.CreateGrantResult; +import com.amazonaws.services.kms.model.CreateKeyRequest; +import com.amazonaws.services.kms.model.CreateKeyResult; +import com.amazonaws.services.kms.model.DecryptRequest; +import com.amazonaws.services.kms.model.DecryptResult; +import com.amazonaws.services.kms.model.DeleteAliasRequest; +import com.amazonaws.services.kms.model.DeleteAliasResult; +import com.amazonaws.services.kms.model.DeleteImportedKeyMaterialRequest; +import com.amazonaws.services.kms.model.DeleteImportedKeyMaterialResult; +import com.amazonaws.services.kms.model.DescribeKeyRequest; +import com.amazonaws.services.kms.model.DescribeKeyResult; +import com.amazonaws.services.kms.model.DisableKeyRequest; +import com.amazonaws.services.kms.model.DisableKeyResult; +import com.amazonaws.services.kms.model.DisableKeyRotationRequest; +import com.amazonaws.services.kms.model.DisableKeyRotationResult; +import com.amazonaws.services.kms.model.EnableKeyRequest; +import com.amazonaws.services.kms.model.EnableKeyResult; +import com.amazonaws.services.kms.model.EnableKeyRotationRequest; +import com.amazonaws.services.kms.model.EnableKeyRotationResult; +import com.amazonaws.services.kms.model.EncryptRequest; +import com.amazonaws.services.kms.model.EncryptResult; +import com.amazonaws.services.kms.model.GenerateDataKeyRequest; +import com.amazonaws.services.kms.model.GenerateDataKeyResult; +import com.amazonaws.services.kms.model.GenerateDataKeyWithoutPlaintextRequest; +import com.amazonaws.services.kms.model.GenerateDataKeyWithoutPlaintextResult; +import com.amazonaws.services.kms.model.GenerateRandomRequest; +import com.amazonaws.services.kms.model.GenerateRandomResult; +import com.amazonaws.services.kms.model.GetKeyPolicyRequest; +import com.amazonaws.services.kms.model.GetKeyPolicyResult; +import com.amazonaws.services.kms.model.GetKeyRotationStatusRequest; +import com.amazonaws.services.kms.model.GetKeyRotationStatusResult; +import com.amazonaws.services.kms.model.GetParametersForImportRequest; +import com.amazonaws.services.kms.model.GetParametersForImportResult; +import com.amazonaws.services.kms.model.ImportKeyMaterialRequest; +import com.amazonaws.services.kms.model.ImportKeyMaterialResult; +import com.amazonaws.services.kms.model.KeyListEntry; +import com.amazonaws.services.kms.model.KeyMetadata; +import com.amazonaws.services.kms.model.ListAliasesRequest; +import com.amazonaws.services.kms.model.ListAliasesResult; +import com.amazonaws.services.kms.model.ListGrantsRequest; +import com.amazonaws.services.kms.model.ListGrantsResult; +import com.amazonaws.services.kms.model.ListKeyPoliciesRequest; +import com.amazonaws.services.kms.model.ListKeyPoliciesResult; +import com.amazonaws.services.kms.model.ListKeysRequest; +import com.amazonaws.services.kms.model.ListKeysResult; +import com.amazonaws.services.kms.model.ListResourceTagsRequest; +import com.amazonaws.services.kms.model.ListResourceTagsResult; +import com.amazonaws.services.kms.model.ListRetirableGrantsRequest; +import com.amazonaws.services.kms.model.ListRetirableGrantsResult; +import com.amazonaws.services.kms.model.PutKeyPolicyRequest; +import com.amazonaws.services.kms.model.PutKeyPolicyResult; +import com.amazonaws.services.kms.model.ReEncryptRequest; +import com.amazonaws.services.kms.model.ReEncryptResult; +import com.amazonaws.services.kms.model.RetireGrantRequest; +import com.amazonaws.services.kms.model.RetireGrantResult; +import com.amazonaws.services.kms.model.RevokeGrantRequest; +import com.amazonaws.services.kms.model.RevokeGrantResult; +import com.amazonaws.services.kms.model.ScheduleKeyDeletionRequest; +import com.amazonaws.services.kms.model.ScheduleKeyDeletionResult; +import com.amazonaws.services.kms.model.TagResourceRequest; +import com.amazonaws.services.kms.model.TagResourceResult; +import com.amazonaws.services.kms.model.UntagResourceRequest; +import com.amazonaws.services.kms.model.UntagResourceResult; +import com.amazonaws.services.kms.model.UpdateAliasRequest; +import com.amazonaws.services.kms.model.UpdateAliasResult; +import com.amazonaws.services.kms.model.UpdateKeyDescriptionRequest; +import com.amazonaws.services.kms.model.UpdateKeyDescriptionResult; + + +public class AmazonKMSClientMock implements AWSKMS { + + public AmazonKMSClientMock() { + super(); + } + + @Override + public void setEndpoint(String endpoint) { + } + + @Override + public void setRegion(Region region) { + } + + @Override + public CancelKeyDeletionResult cancelKeyDeletion(CancelKeyDeletionRequest cancelKeyDeletionRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public CreateAliasResult createAlias(CreateAliasRequest createAliasRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public CreateGrantResult createGrant(CreateGrantRequest createGrantRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public CreateKeyResult createKey(CreateKeyRequest createKeyRequest) { + CreateKeyResult res = new CreateKeyResult(); + KeyMetadata metadata = new KeyMetadata(); + metadata.setKeyId("test"); + metadata.setEnabled(true); + res.setKeyMetadata(metadata); + return res; + } + + @Override + public CreateKeyResult createKey() { + throw new UnsupportedOperationException(); + } + + @Override + public DecryptResult decrypt(DecryptRequest decryptRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public DeleteAliasResult deleteAlias(DeleteAliasRequest deleteAliasRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public DeleteImportedKeyMaterialResult deleteImportedKeyMaterial(DeleteImportedKeyMaterialRequest deleteImportedKeyMaterialRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public DescribeKeyResult describeKey(DescribeKeyRequest describeKeyRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public DisableKeyResult disableKey(DisableKeyRequest disableKeyRequest) { + DisableKeyResult res = new DisableKeyResult(); + return res; + } + + @Override + public DisableKeyRotationResult disableKeyRotation(DisableKeyRotationRequest disableKeyRotationRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public EnableKeyResult enableKey(EnableKeyRequest enableKeyRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public EnableKeyRotationResult enableKeyRotation(EnableKeyRotationRequest enableKeyRotationRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public EncryptResult encrypt(EncryptRequest encryptRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public GenerateDataKeyResult generateDataKey(GenerateDataKeyRequest generateDataKeyRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public GenerateDataKeyWithoutPlaintextResult generateDataKeyWithoutPlaintext(GenerateDataKeyWithoutPlaintextRequest generateDataKeyWithoutPlaintextRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public GenerateRandomResult generateRandom(GenerateRandomRequest generateRandomRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public GenerateRandomResult generateRandom() { + throw new UnsupportedOperationException(); + } + + @Override + public GetKeyPolicyResult getKeyPolicy(GetKeyPolicyRequest getKeyPolicyRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public GetKeyRotationStatusResult getKeyRotationStatus(GetKeyRotationStatusRequest getKeyRotationStatusRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public GetParametersForImportResult getParametersForImport(GetParametersForImportRequest getParametersForImportRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ImportKeyMaterialResult importKeyMaterial(ImportKeyMaterialRequest importKeyMaterialRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ListAliasesResult listAliases(ListAliasesRequest listAliasesRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ListAliasesResult listAliases() { + throw new UnsupportedOperationException(); + } + + @Override + public ListGrantsResult listGrants(ListGrantsRequest listGrantsRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ListKeyPoliciesResult listKeyPolicies(ListKeyPoliciesRequest listKeyPoliciesRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ListKeysResult listKeys(ListKeysRequest listKeysRequest) { + ListKeysResult result = new ListKeysResult(); + List<KeyListEntry> keyList = new ArrayList<KeyListEntry>(); + KeyListEntry kle = new KeyListEntry(); + kle.withKeyId("keyId"); + keyList.add(kle); + result.setKeys(keyList); + return result; + } + + @Override + public ListKeysResult listKeys() { + throw new UnsupportedOperationException(); + } + + @Override + public ListResourceTagsResult listResourceTags(ListResourceTagsRequest listResourceTagsRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ListRetirableGrantsResult listRetirableGrants(ListRetirableGrantsRequest listRetirableGrantsRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public PutKeyPolicyResult putKeyPolicy(PutKeyPolicyRequest putKeyPolicyRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ReEncryptResult reEncrypt(ReEncryptRequest reEncryptRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public RetireGrantResult retireGrant(RetireGrantRequest retireGrantRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public RetireGrantResult retireGrant() { + throw new UnsupportedOperationException(); + } + + @Override + public RevokeGrantResult revokeGrant(RevokeGrantRequest revokeGrantRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public ScheduleKeyDeletionResult scheduleKeyDeletion(ScheduleKeyDeletionRequest scheduleKeyDeletionRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public TagResourceResult tagResource(TagResourceRequest tagResourceRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public UntagResourceResult untagResource(UntagResourceRequest untagResourceRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public UpdateAliasResult updateAlias(UpdateAliasRequest updateAliasRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public UpdateKeyDescriptionResult updateKeyDescription(UpdateKeyDescriptionRequest updateKeyDescriptionRequest) { + throw new UnsupportedOperationException(); + } + + @Override + public void shutdown() { + throw new UnsupportedOperationException(); + } + + @Override + public ResponseMetadata getCachedResponseMetadata(AmazonWebServiceRequest request) { + throw new UnsupportedOperationException(); + } + +} diff --git a/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSComponentConfigurationTest.java b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSComponentConfigurationTest.java new file mode 100644 index 0000000..96460c8 --- /dev/null +++ b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSComponentConfigurationTest.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import com.amazonaws.regions.Regions; + +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class KMSComponentConfigurationTest extends CamelTestSupport { + + + @Test + public void createEndpointWithComponentElements() throws Exception { + KMSComponent component = new KMSComponent(context); + component.setAccessKey("XXX"); + component.setSecretKey("YYY"); + KMSEndpoint endpoint = (KMSEndpoint)component.createEndpoint("aws-kms://label"); + + assertEquals("XXX", endpoint.getConfiguration().getAccessKey()); + assertEquals("YYY", endpoint.getConfiguration().getSecretKey()); + } + + @Test + public void createEndpointWithComponentAndEndpointElements() throws Exception { + KMSComponent component = new KMSComponent(context); + component.setAccessKey("XXX"); + component.setSecretKey("YYY"); + component.setRegion(Regions.US_WEST_1.toString()); + KMSEndpoint endpoint = (KMSEndpoint)component.createEndpoint("aws-mq://label?accessKey=xxxxxx&secretKey=yyyyy®ion=US_EAST_1"); + + assertEquals("xxxxxx", endpoint.getConfiguration().getAccessKey()); + assertEquals("yyyyy", endpoint.getConfiguration().getSecretKey()); + assertEquals("US_EAST_1", endpoint.getConfiguration().getRegion()); + } + +} diff --git a/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSComponentVerifierExtensionTest.java b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSComponentVerifierExtensionTest.java new file mode 100644 index 0000000..c8c1c2e --- /dev/null +++ b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSComponentVerifierExtensionTest.java @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.Component; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Assert; +import org.junit.Test; + +public class KMSComponentVerifierExtensionTest extends CamelTestSupport { + + // ************************************************* + // Tests (parameters) + // ************************************************* + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void testParameters() throws Exception { + Component component = context().getComponent("aws-kms"); + + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("secretKey", "l"); + parameters.put("accessKey", "k"); + parameters.put("region", "l"); + parameters.put("label", "test"); + parameters.put("operation", KMSOperations.listKeys); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivity() throws Exception { + Component component = context().getComponent("aws-kms"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("secretKey", "l"); + parameters.put("accessKey", "k"); + parameters.put("region", "US_EAST_1"); + parameters.put("label", "test"); + parameters.put("operation", KMSOperations.listKeys); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + } + +} diff --git a/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSProducerSpringTest.java b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSProducerSpringTest.java new file mode 100644 index 0000000..2dbb3f5 --- /dev/null +++ b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSProducerSpringTest.java @@ -0,0 +1,91 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import com.amazonaws.services.kms.model.CreateKeyResult; +import com.amazonaws.services.kms.model.ListKeysResult; + +import org.apache.camel.EndpointInject; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.spring.CamelSpringTestSupport; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class KMSProducerSpringTest extends CamelSpringTestSupport { + + @EndpointInject(uri = "mock:result") + private MockEndpoint mock; + + @Test + public void mqListBrokersTest() throws Exception { + + mock.expectedMessageCount(1); + Exchange exchange = template.request("direct:listKeys", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(KMSConstants.OPERATION, KMSOperations.listKeys); + } + }); + + assertMockEndpointsSatisfied(); + + ListKeysResult resultGet = (ListKeysResult) exchange.getIn().getBody(); + assertEquals(1, resultGet.getKeys().size()); + assertEquals("keyId", resultGet.getKeys().get(0).getKeyId()); + } + + @Test + public void kmsCreateKeyTest() throws Exception { + + mock.expectedMessageCount(1); + Exchange exchange = template.request("direct:createKey", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(KMSConstants.OPERATION, KMSOperations.createKey); + } + }); + + assertMockEndpointsSatisfied(); + + CreateKeyResult resultGet = (CreateKeyResult) exchange.getIn().getBody(); + assertEquals("test", resultGet.getKeyMetadata().getKeyId()); + assertEquals(true, resultGet.getKeyMetadata().isEnabled()); + } + + @Test + public void kmsDisableKeyTest() throws Exception { + + mock.expectedMessageCount(1); + template.request("direct:disableKey", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(KMSConstants.OPERATION, KMSOperations.disableKey); + exchange.getIn().setHeader(KMSConstants.KEY_ID, "test"); + } + }); + + assertMockEndpointsSatisfied(); + + } + + @Override + protected ClassPathXmlApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext("org/apache/camel/component/aws/kms/KMSComponentSpringTest-context.xml"); + } +} \ No newline at end of file diff --git a/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSProducerTest.java b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSProducerTest.java new file mode 100644 index 0000000..f478c2b --- /dev/null +++ b/components/camel-aws/src/test/java/org/apache/camel/component/aws/kms/KMSProducerTest.java @@ -0,0 +1,116 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms; + +import com.amazonaws.services.kms.model.CreateKeyResult; +import com.amazonaws.services.kms.model.ListKeysResult; + +import org.apache.camel.EndpointInject; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class KMSProducerTest extends CamelTestSupport { + + @EndpointInject(uri = "mock:result") + private MockEndpoint mock; + + @Test + public void kmsListKeysTest() throws Exception { + + mock.expectedMessageCount(1); + Exchange exchange = template.request("direct:listKeys", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(KMSConstants.OPERATION, KMSOperations.listKeys); + } + }); + + assertMockEndpointsSatisfied(); + + ListKeysResult resultGet = (ListKeysResult) exchange.getIn().getBody(); + assertEquals(1, resultGet.getKeys().size()); + assertEquals("keyId", resultGet.getKeys().get(0).getKeyId()); + } + + @Test + public void kmsCreateKeyTest() throws Exception { + + mock.expectedMessageCount(1); + Exchange exchange = template.request("direct:createKey", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(KMSConstants.OPERATION, KMSOperations.createKey); + } + }); + + assertMockEndpointsSatisfied(); + + CreateKeyResult resultGet = (CreateKeyResult) exchange.getIn().getBody(); + assertEquals("test", resultGet.getKeyMetadata().getKeyId()); + assertEquals(true, resultGet.getKeyMetadata().isEnabled()); + } + + @Test + public void kmsDisableKeyTest() throws Exception { + + mock.expectedMessageCount(1); + template.request("direct:disableKey", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(KMSConstants.OPERATION, KMSOperations.disableKey); + exchange.getIn().setHeader(KMSConstants.KEY_ID, "test"); + } + }); + + assertMockEndpointsSatisfied(); + + } + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry registry = super.createRegistry(); + + AmazonKMSClientMock clientMock = new AmazonKMSClientMock(); + + registry.bind("amazonKmsClient", clientMock); + + return registry; + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:listKeys") + .to("aws-kms://test?kmsClient=#amazonKmsClient&operation=listKeys") + .to("mock:result"); + from("direct:createKey") + .to("aws-kms://test?kmsClient=#amazonKmsClient&operation=createKey") + .to("mock:result"); + from("direct:disableKey") + .to("aws-kms://test?kmsClient=#amazonKmsClient&operation=disableKey") + .to("mock:result"); + } + }; + } +} \ No newline at end of file diff --git a/components/camel-aws/src/test/resources/org/apache/camel/component/aws/kms/KMSComponentSpringTest-context.xml b/components/camel-aws/src/test/resources/org/apache/camel/component/aws/kms/KMSComponentSpringTest-context.xml new file mode 100644 index 0000000..a901da2 --- /dev/null +++ b/components/camel-aws/src/test/resources/org/apache/camel/component/aws/kms/KMSComponentSpringTest-context.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:listKeys"/> + <to uri="aws-kms://Test?kmsClient=#amazonKmsClient&operation=listKeys"/> + <to uri="mock:result"/> + </route> + <route> + <from uri="direct:createKey"/> + <to uri="aws-kms://Test?kmsClient=#amazonKmsClient&operation=createKey"/> + <to uri="mock:result"/> + </route> + <route> + <from uri="direct:disableKey"/> + <to uri="aws-kms://Test?kmsClient=#amazonKmsClient&operation=disableKey"/> + <to uri="mock:result"/> + </route> + </camelContext> + + <bean id="amazonKmsClient" class="org.apache.camel.component.aws.kms.AmazonKMSClientMock"/> +</beans> \ No newline at end of file diff --git a/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/kms/springboot/KMSComponentAutoConfiguration.java b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/kms/springboot/KMSComponentAutoConfiguration.java new file mode 100644 index 0000000..a78283f --- /dev/null +++ b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/kms/springboot/KMSComponentAutoConfiguration.java @@ -0,0 +1,128 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms.springboot; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Generated; +import org.apache.camel.CamelContext; +import org.apache.camel.component.aws.kms.KMSComponent; +import org.apache.camel.spi.ComponentCustomizer; +import org.apache.camel.spi.HasId; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.apache.camel.spring.boot.ComponentConfigurationProperties; +import org.apache.camel.spring.boot.util.CamelPropertiesHelper; +import org.apache.camel.spring.boot.util.ConditionalOnCamelContextAndAutoConfigurationBeans; +import org.apache.camel.spring.boot.util.GroupCondition; +import org.apache.camel.spring.boot.util.HierarchicalPropertiesEvaluator; +import org.apache.camel.util.IntrospectionSupport; +import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; + +/** + * Generated by camel-package-maven-plugin - do not edit this file! + */ +@Generated("org.apache.camel.maven.packaging.SpringBootAutoConfigurationMojo") +@Configuration +@Conditional({ConditionalOnCamelContextAndAutoConfigurationBeans.class, + KMSComponentAutoConfiguration.GroupConditions.class}) +@AutoConfigureAfter(CamelAutoConfiguration.class) +@EnableConfigurationProperties({ComponentConfigurationProperties.class, + KMSComponentConfiguration.class}) +public class KMSComponentAutoConfiguration { + + private static final Logger LOGGER = LoggerFactory + .getLogger(KMSComponentAutoConfiguration.class); + @Autowired + private ApplicationContext applicationContext; + @Autowired + private CamelContext camelContext; + @Autowired + private KMSComponentConfiguration configuration; + @Autowired(required = false) + private List<ComponentCustomizer<KMSComponent>> customizers; + + static class GroupConditions extends GroupCondition { + public GroupConditions() { + super("camel.component", "camel.component.aws-kms"); + } + } + + @Lazy + @Bean(name = "aws-kms-component") + @ConditionalOnMissingBean(KMSComponent.class) + public KMSComponent configureKMSComponent() throws Exception { + KMSComponent component = new KMSComponent(); + component.setCamelContext(camelContext); + Map<String, Object> parameters = new HashMap<>(); + IntrospectionSupport.getProperties(configuration, parameters, null, + false); + for (Map.Entry<String, Object> entry : parameters.entrySet()) { + Object value = entry.getValue(); + Class<?> paramClass = value.getClass(); + if (paramClass.getName().endsWith("NestedConfiguration")) { + Class nestedClass = null; + try { + nestedClass = (Class) paramClass.getDeclaredField( + "CAMEL_NESTED_CLASS").get(null); + HashMap<String, Object> nestedParameters = new HashMap<>(); + IntrospectionSupport.getProperties(value, nestedParameters, + null, false); + Object nestedProperty = nestedClass.newInstance(); + CamelPropertiesHelper.setCamelProperties(camelContext, + nestedProperty, nestedParameters, false); + entry.setValue(nestedProperty); + } catch (NoSuchFieldException e) { + } + } + } + CamelPropertiesHelper.setCamelProperties(camelContext, component, + parameters, false); + if (ObjectHelper.isNotEmpty(customizers)) { + for (ComponentCustomizer<KMSComponent> customizer : customizers) { + boolean useCustomizer = (customizer instanceof HasId) + ? HierarchicalPropertiesEvaluator.evaluate( + applicationContext.getEnvironment(), + "camel.component.customizer", + "camel.component.aws-kms.customizer", + ((HasId) customizer).getId()) + : HierarchicalPropertiesEvaluator.evaluate( + applicationContext.getEnvironment(), + "camel.component.customizer", + "camel.component.aws-kms.customizer"); + if (useCustomizer) { + LOGGER.debug("Configure component {}, with customizer {}", + component, customizer); + customizer.customize(component); + } + } + } + return component; + } +} \ No newline at end of file diff --git a/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/kms/springboot/KMSComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/kms/springboot/KMSComponentConfiguration.java new file mode 100644 index 0000000..e573a7e --- /dev/null +++ b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/kms/springboot/KMSComponentConfiguration.java @@ -0,0 +1,179 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.aws.kms.springboot; + +import javax.annotation.Generated; +import com.amazonaws.services.kms.AWSKMS; +import org.apache.camel.component.aws.kms.KMSOperations; +import org.apache.camel.spring.boot.ComponentConfigurationPropertiesCommon; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * The aws-mq is used for managing Amazon KMS + * + * Generated by camel-package-maven-plugin - do not edit this file! + */ +@Generated("org.apache.camel.maven.packaging.SpringBootAutoConfigurationMojo") +@ConfigurationProperties(prefix = "camel.component.aws-kms") +public class KMSComponentConfiguration + extends + ComponentConfigurationPropertiesCommon { + + /** + * The AWS MQ default configuration + */ + private KMSConfigurationNestedConfiguration configuration; + /** + * Amazon AWS Access Key + */ + private String accessKey; + /** + * Amazon AWS Secret Key + */ + private String secretKey; + /** + * The region in which MQ client needs to work + */ + private String region; + /** + * Whether the component should resolve property placeholders on itself when + * starting. Only properties which are of String type can use property + * placeholders. + */ + private Boolean resolvePropertyPlaceholders = true; + + public KMSConfigurationNestedConfiguration getConfiguration() { + return configuration; + } + + public void setConfiguration( + KMSConfigurationNestedConfiguration configuration) { + this.configuration = configuration; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public Boolean getResolvePropertyPlaceholders() { + return resolvePropertyPlaceholders; + } + + public void setResolvePropertyPlaceholders( + Boolean resolvePropertyPlaceholders) { + this.resolvePropertyPlaceholders = resolvePropertyPlaceholders; + } + + public static class KMSConfigurationNestedConfiguration { + public static final Class CAMEL_NESTED_CLASS = org.apache.camel.component.aws.kms.KMSConfiguration.class; + /** + * To use a existing configured AWS KMS as client + */ + private AWSKMS kmsClient; + /** + * Amazon AWS Access Key + */ + private String accessKey; + /** + * Amazon AWS Secret Key + */ + private String secretKey; + /** + * The operation to perform + */ + private KMSOperations operation; + private String proxyHost; + private Integer proxyPort; + private String region; + + public AWSKMS getKmsClient() { + return kmsClient; + } + + public void setKmsClient(AWSKMS kmsClient) { + this.kmsClient = kmsClient; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public KMSOperations getOperation() { + return operation; + } + + public void setOperation(KMSOperations operation) { + this.operation = operation; + } + + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public Integer getProxyPort() { + return proxyPort; + } + + public void setProxyPort(Integer proxyPort) { + this.proxyPort = proxyPort; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + } +} \ No newline at end of file diff --git a/platforms/spring-boot/components-starter/camel-aws-starter/src/main/resources/META-INF/spring.factories b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/resources/META-INF/spring.factories index c90a18a..aaa12f1 100644 --- a/platforms/spring-boot/components-starter/camel-aws-starter/src/main/resources/META-INF/spring.factories +++ b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/resources/META-INF/spring.factories @@ -28,7 +28,9 @@ org.apache.camel.component.aws.cw.springboot.CwComponentAutoConfiguration,\ org.apache.camel.component.aws.ddb.springboot.DdbComponentAutoConfiguration,\ org.apache.camel.component.aws.firehose.springboot.KinesisFirehoseComponentAutoConfiguration,\ org.apache.camel.component.aws.lambda.springboot.LambdaComponentAutoConfiguration,\ -org.apache.camel.component.aws.mq.springboot.MQComponentAutoConfiguration +org.apache.camel.component.aws.mq.springboot.MQComponentAutoConfiguration,\ +org.apache.camel.component.aws.kms.springboot.KMSComponentAutoConfiguration + -- To stop receiving notification emails like this one, please contact acosent...@apache.org.