This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch CAMEL-20220 in repository https://gitbox.apache.org/repos/asf/camel.git
commit 302266b28e1adab7d5871b18c08571119a242089 Author: Andrea Cosentino <[email protected]> AuthorDate: Tue Dec 12 11:52:02 2023 +0100 CAMEL-20220 - Camel Azure Key Vault: Support Azure Identity in the component and secrets function Signed-off-by: Andrea Cosentino <[email protected]> --- .../camel/catalog/components/azure-key-vault.json | 13 ++++---- .../main/camel-main-configuration-metadata.json | 1 + .../key/vault/KeyVaultEndpointConfigurer.java | 6 ++++ .../key/vault/KeyVaultEndpointUriFactory.java | 3 +- .../component/azure/key/vault/azure-key-vault.json | 13 ++++---- .../component/azure/key/vault/CredentialType.java | 35 ++++++++++++++++++++++ .../azure/key/vault/KeyVaultConfiguration.java | 18 +++++++++++ .../azure/key/vault/KeyVaultEndpoint.java | 17 +++++++---- .../key/vault/KeyVaultPropertiesFunction.java | 25 ++++++++++++++-- .../camel/vault/AzureVaultConfiguration.java | 13 ++++++++ .../main/AzureVaultConfigurationConfigurer.java | 6 ++++ ...zureVaultConfigurationPropertiesConfigurer.java | 6 ++++ .../camel-main-configuration-metadata.json | 1 + core/camel-main/src/main/docs/main.adoc | 3 +- .../main/AzureVaultConfigurationProperties.java | 8 +++++ .../java/org/apache/camel/main/MainVaultTest.java | 2 ++ 16 files changed, 148 insertions(+), 22 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-key-vault.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-key-vault.json index f7cb32df0fa..6acab7018d6 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-key-vault.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-key-vault.json @@ -31,11 +31,12 @@ }, "properties": { "vaultName": { "index": 0, "kind": "path", "displayName": "Vault Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Vault Name to be used" }, - "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.azure.key.vault.KeyVaultOperation", "enum": [ "createSecret", "getSecret", "deleteSecret", "purgeDeletedSecret" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configu [...] - "secretClient": { "index": 2, "kind": "parameter", "displayName": "Secret Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "com.azure.security.keyvault.secrets.SecretClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Instance of Secret client" }, - "lazyStartProducer": { "index": 3, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] - "clientId": { "index": 4, "kind": "parameter", "displayName": "Client Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Id to be used" }, - "clientSecret": { "index": 5, "kind": "parameter", "displayName": "Client Secret", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Secret to be used" }, - "tenantId": { "index": 6, "kind": "parameter", "displayName": "Tenant Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Tenant Id to be used" } + "credentialType": { "index": 1, "kind": "parameter", "displayName": "Credential Type", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "org.apache.camel.component.azure.key.vault.CredentialType", "enum": [ "CLIENT_SECRET", "AZURE_IDENTITY" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CLIENT_SECRET", "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "co [...] + "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.azure.key.vault.KeyVaultOperation", "enum": [ "createSecret", "getSecret", "deleteSecret", "purgeDeletedSecret" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configu [...] + "secretClient": { "index": 3, "kind": "parameter", "displayName": "Secret Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "com.azure.security.keyvault.secrets.SecretClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Instance of Secret client" }, + "lazyStartProducer": { "index": 4, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] + "clientId": { "index": 5, "kind": "parameter", "displayName": "Client Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Id to be used" }, + "clientSecret": { "index": 6, "kind": "parameter", "displayName": "Client Secret", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Secret to be used" }, + "tenantId": { "index": 7, "kind": "parameter", "displayName": "Tenant Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Tenant Id to be used" } } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json index 72f4180cad8..5577ce62cb1 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json @@ -276,6 +276,7 @@ { "name": "camel.vault.aws.region", "description": "The AWS region", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.aws.secretKey", "description": "The AWS secret key", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.aws.secrets", "description": "Specify the secret names (or pattern) to check for updates. Multiple secrets can be separated by comma.", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.vault.azure.azureIdentityEnabled", "description": "Whether the Azure Identity Authentication should be used or not.", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.vault.azure.blobAccessKey", "description": "The Eventhubs Blob Access Key for CheckpointStore purpose", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.azure.blobAccountName", "description": "The Eventhubs Blob Account Name for CheckpointStore purpose", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.azure.blobContainerName", "description": "The Eventhubs Blob Container Name for CheckpointStore purpose", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, diff --git a/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointConfigurer.java b/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointConfigurer.java index a36c1210bd5..372ecd3a4fb 100644 --- a/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointConfigurer.java +++ b/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointConfigurer.java @@ -25,6 +25,8 @@ public class KeyVaultEndpointConfigurer extends PropertyConfigurerSupport implem case "clientId": target.getConfiguration().setClientId(property(camelContext, java.lang.String.class, value)); return true; case "clientsecret": case "clientSecret": target.getConfiguration().setClientSecret(property(camelContext, java.lang.String.class, value)); return true; + case "credentialtype": + case "credentialType": target.getConfiguration().setCredentialType(property(camelContext, org.apache.camel.component.azure.key.vault.CredentialType.class, value)); return true; case "lazystartproducer": case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; case "operation": target.getConfiguration().setOperation(property(camelContext, org.apache.camel.component.azure.key.vault.KeyVaultOperation.class, value)); return true; @@ -48,6 +50,8 @@ public class KeyVaultEndpointConfigurer extends PropertyConfigurerSupport implem case "clientId": return java.lang.String.class; case "clientsecret": case "clientSecret": return java.lang.String.class; + case "credentialtype": + case "credentialType": return org.apache.camel.component.azure.key.vault.CredentialType.class; case "lazystartproducer": case "lazyStartProducer": return boolean.class; case "operation": return org.apache.camel.component.azure.key.vault.KeyVaultOperation.class; @@ -67,6 +71,8 @@ public class KeyVaultEndpointConfigurer extends PropertyConfigurerSupport implem case "clientId": return target.getConfiguration().getClientId(); case "clientsecret": case "clientSecret": return target.getConfiguration().getClientSecret(); + case "credentialtype": + case "credentialType": return target.getConfiguration().getCredentialType(); case "lazystartproducer": case "lazyStartProducer": return target.isLazyStartProducer(); case "operation": return target.getConfiguration().getOperation(); diff --git a/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointUriFactory.java b/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointUriFactory.java index af6be600796..bc03fdbffa0 100644 --- a/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointUriFactory.java +++ b/components/camel-azure/camel-azure-key-vault/src/generated/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpointUriFactory.java @@ -21,9 +21,10 @@ public class KeyVaultEndpointUriFactory extends org.apache.camel.support.compone private static final Set<String> SECRET_PROPERTY_NAMES; private static final Set<String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(7); + Set<String> props = new HashSet<>(8); props.add("clientId"); props.add("clientSecret"); + props.add("credentialType"); props.add("lazyStartProducer"); props.add("operation"); props.add("secretClient"); diff --git a/components/camel-azure/camel-azure-key-vault/src/generated/resources/org/apache/camel/component/azure/key/vault/azure-key-vault.json b/components/camel-azure/camel-azure-key-vault/src/generated/resources/org/apache/camel/component/azure/key/vault/azure-key-vault.json index f7cb32df0fa..6acab7018d6 100644 --- a/components/camel-azure/camel-azure-key-vault/src/generated/resources/org/apache/camel/component/azure/key/vault/azure-key-vault.json +++ b/components/camel-azure/camel-azure-key-vault/src/generated/resources/org/apache/camel/component/azure/key/vault/azure-key-vault.json @@ -31,11 +31,12 @@ }, "properties": { "vaultName": { "index": 0, "kind": "path", "displayName": "Vault Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Vault Name to be used" }, - "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.azure.key.vault.KeyVaultOperation", "enum": [ "createSecret", "getSecret", "deleteSecret", "purgeDeletedSecret" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configu [...] - "secretClient": { "index": 2, "kind": "parameter", "displayName": "Secret Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "com.azure.security.keyvault.secrets.SecretClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Instance of Secret client" }, - "lazyStartProducer": { "index": 3, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] - "clientId": { "index": 4, "kind": "parameter", "displayName": "Client Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Id to be used" }, - "clientSecret": { "index": 5, "kind": "parameter", "displayName": "Client Secret", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Secret to be used" }, - "tenantId": { "index": 6, "kind": "parameter", "displayName": "Tenant Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Tenant Id to be used" } + "credentialType": { "index": 1, "kind": "parameter", "displayName": "Credential Type", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "org.apache.camel.component.azure.key.vault.CredentialType", "enum": [ "CLIENT_SECRET", "AZURE_IDENTITY" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CLIENT_SECRET", "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "co [...] + "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.azure.key.vault.KeyVaultOperation", "enum": [ "createSecret", "getSecret", "deleteSecret", "purgeDeletedSecret" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configu [...] + "secretClient": { "index": 3, "kind": "parameter", "displayName": "Secret Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "com.azure.security.keyvault.secrets.SecretClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Instance of Secret client" }, + "lazyStartProducer": { "index": 4, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] + "clientId": { "index": 5, "kind": "parameter", "displayName": "Client Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Id to be used" }, + "clientSecret": { "index": 6, "kind": "parameter", "displayName": "Client Secret", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Client Secret to be used" }, + "tenantId": { "index": 7, "kind": "parameter", "displayName": "Tenant Id", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.azure.key.vault.KeyVaultConfiguration", "configurationField": "configuration", "description": "Tenant Id to be used" } } } diff --git a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/CredentialType.java b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/CredentialType.java new file mode 100644 index 00000000000..8c8b294a98a --- /dev/null +++ b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/CredentialType.java @@ -0,0 +1,35 @@ +/* + * 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.azure.key.vault; + +public enum CredentialType { + /** + * Client Secret Credential + */ + CLIENT_SECRET, + /** + * Includes: + * <uL> + * <li>Service principal with secret</li> + * <li>Service principal with certificate</li> + * <li>username and password</li> + * </uL> + * + * @see com.azure.identity.DefaultAzureCredentialBuilder + */ + AZURE_IDENTITY +} diff --git a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultConfiguration.java b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultConfiguration.java index a92ef9e767f..2e3fb12b957 100644 --- a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultConfiguration.java +++ b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultConfiguration.java @@ -23,6 +23,9 @@ import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriParams; import org.apache.camel.spi.UriPath; +import static org.apache.camel.component.azure.key.vault.CredentialType.AZURE_IDENTITY; +import static org.apache.camel.component.azure.key.vault.CredentialType.CLIENT_SECRET; + @UriParams public class KeyVaultConfiguration implements Cloneable { @@ -39,6 +42,9 @@ public class KeyVaultConfiguration implements Cloneable { private String tenantId; @UriParam(label = "producer") private KeyVaultOperation operation = KeyVaultOperation.createSecret; + @UriParam(label = "common", enums = "CLIENT_SECRET,AZURE_IDENTITY", + defaultValue = "CLIENT_SECRET") + private CredentialType credentialType = CLIENT_SECRET; /** * Instance of Secret client @@ -106,6 +112,18 @@ public class KeyVaultConfiguration implements Cloneable { this.operation = operation; } + + public CredentialType getCredentialType() { + return credentialType; + } + + /** + * Determines the credential strategy to adopt + */ + public void setCredentialType(CredentialType credentialType) { + this.credentialType = credentialType; + } + // ************************************************* // // ************************************************* diff --git a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpoint.java b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpoint.java index 0840244dc4c..17bdcbca647 100644 --- a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpoint.java +++ b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultEndpoint.java @@ -16,8 +16,10 @@ */ package org.apache.camel.component.azure.key.vault; +import com.azure.core.credential.TokenCredential; import com.azure.identity.ClientSecretCredential; import com.azure.identity.ClientSecretCredentialBuilder; +import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.security.keyvault.secrets.SecretClient; import com.azure.security.keyvault.secrets.SecretClientBuilder; import org.apache.camel.Category; @@ -61,12 +63,17 @@ public class KeyVaultEndpoint extends DefaultEndpoint { // Build key vault URI String keyVaultUri = "https://" + getConfiguration().getVaultName() + ".vault.azure.net"; + TokenCredential credential = null; // Credential - ClientSecretCredential credential = new ClientSecretCredentialBuilder() - .tenantId(getConfiguration().getTenantId()) - .clientId(getConfiguration().getClientId()) - .clientSecret(getConfiguration().getClientSecret()) - .build(); + if (configuration.getCredentialType().equals(CredentialType.CLIENT_SECRET)) { + credential = new ClientSecretCredentialBuilder() + .tenantId(getConfiguration().getTenantId()) + .clientId(getConfiguration().getClientId()) + .clientSecret(getConfiguration().getClientSecret()) + .build(); + } else if (configuration.getCredentialType().equals(CredentialType.AZURE_IDENTITY)) { + credential = new DefaultAzureCredentialBuilder().build(); + } // Build Client localClient = new SecretClientBuilder() diff --git a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java index 35f71cd6ad1..ad758c560a2 100644 --- a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java +++ b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java @@ -19,9 +19,11 @@ package org.apache.camel.component.azure.key.vault; import java.util.HashSet; import java.util.Set; +import com.azure.core.credential.TokenCredential; import com.azure.core.exception.ResourceNotFoundException; import com.azure.identity.ClientSecretCredential; import com.azure.identity.ClientSecretCredentialBuilder; +import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.security.keyvault.secrets.SecretClient; import com.azure.security.keyvault.secrets.SecretClientBuilder; import com.azure.security.keyvault.secrets.models.KeyVaultSecret; @@ -46,6 +48,7 @@ import org.apache.camel.vault.AzureVaultConfiguration; * <li><tt>CAMEL_VAULT_AZURE_CLIENT_ID</tt></li> * <li><tt>CAMEL_VAULT_AZURE_CLIENT_SECRET</tt></li> * <li><tt>CAMEL_VAULT_AZURE_TENANT_ID</tt></li> + * <li><tt>CAMEL_VAULT_AZURE_IDENTITY_ENABLED</tt></li> * </ul> * <p/> * @@ -56,12 +59,13 @@ import org.apache.camel.vault.AzureVaultConfiguration; * <li><tt>camel.vault.azure.clientId</tt></li> * <li><tt>camel.vault.azure.clientSecret</tt></li> * <li><tt>camel.vault.azure.tenantId</tt></li> + * <li><tt>camel.vault.azure.azureIdentityEnabled</tt></li> * </ul> * <p/> * * This implementation is to return the secret value associated with a key. The properties related to this kind of * Properties Function are all prefixed with <tt>azure:</tt>. For example asking for <tt>azure:token</tt>, will return - * the secret value associated to the secret named token on AWS Secrets Manager. + * the secret value associated to the secret named token on Azure Key Vault. * * Another way of retrieving a secret value is using the following notation <tt>azure:database/username</tt>: in this * case the field username of the secret database will be returned. As a fallback, the user could provide a default @@ -78,6 +82,8 @@ public class KeyVaultPropertiesFunction extends ServiceSupport implements Proper private static final String CAMEL_VAULT_AZURE_CLIENT_ID = "CAMEL_VAULT_AZURE_CLIENT_ID"; private static final String CAMEL_VAULT_AZURE_CLIENT_SECRET = "CAMEL_VAULT_AZURE_CLIENT_SECRET"; private static final String CAMEL_VAULT_AZURE_TENANT_ID = "CAMEL_VAULT_AZURE_TENANT_ID"; + + private static final String CAMEL_VAULT_AZURE_IDENTITY_ENABLED = "CAMEL_VAULT_AZURE_IDENTITY_ENABLED"; private CamelContext camelContext; private SecretClient client; private final Set<String> secrets = new HashSet<>(); @@ -89,6 +95,7 @@ public class KeyVaultPropertiesFunction extends ServiceSupport implements Proper String clientId = System.getenv(CAMEL_VAULT_AZURE_CLIENT_ID); String clientSecret = System.getenv(CAMEL_VAULT_AZURE_CLIENT_SECRET); String tenantId = System.getenv(CAMEL_VAULT_AZURE_TENANT_ID); + boolean azureIdentityEnabled = Boolean.parseBoolean(System.getenv(CAMEL_VAULT_AZURE_IDENTITY_ENABLED)); if (ObjectHelper.isEmpty(vaultName) && ObjectHelper.isEmpty(clientId) && ObjectHelper.isEmpty(clientSecret) && ObjectHelper.isEmpty(tenantId)) { AzureVaultConfiguration azureVaultConfiguration = getCamelContext().getVaultConfiguration().azure(); @@ -97,10 +104,11 @@ public class KeyVaultPropertiesFunction extends ServiceSupport implements Proper clientId = azureVaultConfiguration.getClientId(); clientSecret = azureVaultConfiguration.getClientSecret(); tenantId = azureVaultConfiguration.getTenantId(); + azureIdentityEnabled = azureVaultConfiguration.isAzureIdentityEnabled(); } } if (ObjectHelper.isNotEmpty(vaultName) && ObjectHelper.isNotEmpty(clientId) && ObjectHelper.isNotEmpty(clientSecret) - && ObjectHelper.isNotEmpty(tenantId)) { + && ObjectHelper.isNotEmpty(tenantId) && !azureIdentityEnabled) { String keyVaultUri = "https://" + vaultName + ".vault.azure.net"; // Credential @@ -110,6 +118,17 @@ public class KeyVaultPropertiesFunction extends ServiceSupport implements Proper .clientSecret(clientSecret) .build(); + // Build Client + client = new SecretClientBuilder() + .vaultUrl(keyVaultUri) + .credential(credential) + .buildClient(); + } else if (ObjectHelper.isNotEmpty(vaultName) && azureIdentityEnabled) { + String keyVaultUri = "https://" + vaultName + ".vault.azure.net"; + + // Credential + TokenCredential credential = new DefaultAzureCredentialBuilder().build(); + // Build Client client = new SecretClientBuilder() .vaultUrl(keyVaultUri) @@ -117,7 +136,7 @@ public class KeyVaultPropertiesFunction extends ServiceSupport implements Proper .buildClient(); } else { throw new RuntimeCamelException( - "Using the Azure Key Vault Properties Function requires setting Azure credentials as application properties or environment variables"); + "Using the Azure Key Vault Properties Function requires setting Azure credentials as application properties or environment variables or enable the Azure Identity Authentication mechanism"); } } diff --git a/core/camel-api/src/main/java/org/apache/camel/vault/AzureVaultConfiguration.java b/core/camel-api/src/main/java/org/apache/camel/vault/AzureVaultConfiguration.java index 5e1804c661b..64e70878154 100644 --- a/core/camel-api/src/main/java/org/apache/camel/vault/AzureVaultConfiguration.java +++ b/core/camel-api/src/main/java/org/apache/camel/vault/AzureVaultConfiguration.java @@ -32,6 +32,8 @@ public class AzureVaultConfiguration extends VaultConfiguration { @Metadata(secret = true) private String tenantId; @Metadata + private boolean azureIdentityEnabled; + @Metadata private boolean refreshEnabled; @Metadata(defaultValue = "30000") private long refreshPeriod = 30000; @@ -90,6 +92,17 @@ public class AzureVaultConfiguration extends VaultConfiguration { this.tenantId = tenantId; } + public boolean isAzureIdentityEnabled() { + return azureIdentityEnabled; + } + + /** + * Whether the Azure Identity Authentication should be used or not. + */ + public void setAzureIdentityEnabled(boolean azureIdentityEnabled) { + this.azureIdentityEnabled = azureIdentityEnabled; + } + public boolean isRefreshEnabled() { return refreshEnabled; } diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationConfigurer.java index 9560719e584..ea4798b7450 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationConfigurer.java @@ -23,6 +23,8 @@ public class AzureVaultConfigurationConfigurer extends org.apache.camel.support. switch (ignoreCase ? name.toLowerCase() : name) { case "awsvaultconfiguration": case "AwsVaultConfiguration": target.setAwsVaultConfiguration(property(camelContext, org.apache.camel.vault.AwsVaultConfiguration.class, value)); return true; + case "azureidentityenabled": + case "AzureIdentityEnabled": target.setAzureIdentityEnabled(property(camelContext, boolean.class, value)); return true; case "azurevaultconfiguration": case "AzureVaultConfiguration": target.setAzureVaultConfiguration(property(camelContext, org.apache.camel.vault.AzureVaultConfiguration.class, value)); return true; case "blobaccesskey": @@ -60,6 +62,8 @@ public class AzureVaultConfigurationConfigurer extends org.apache.camel.support. switch (ignoreCase ? name.toLowerCase() : name) { case "awsvaultconfiguration": case "AwsVaultConfiguration": return org.apache.camel.vault.AwsVaultConfiguration.class; + case "azureidentityenabled": + case "AzureIdentityEnabled": return boolean.class; case "azurevaultconfiguration": case "AzureVaultConfiguration": return org.apache.camel.vault.AzureVaultConfiguration.class; case "blobaccesskey": @@ -98,6 +102,8 @@ public class AzureVaultConfigurationConfigurer extends org.apache.camel.support. switch (ignoreCase ? name.toLowerCase() : name) { case "awsvaultconfiguration": case "AwsVaultConfiguration": return target.getAwsVaultConfiguration(); + case "azureidentityenabled": + case "AzureIdentityEnabled": return target.isAzureIdentityEnabled(); case "azurevaultconfiguration": case "AzureVaultConfiguration": return target.getAzureVaultConfiguration(); case "blobaccesskey": diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationPropertiesConfigurer.java index cafee650316..65616f5136c 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationPropertiesConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/AzureVaultConfigurationPropertiesConfigurer.java @@ -23,6 +23,8 @@ public class AzureVaultConfigurationPropertiesConfigurer extends org.apache.came switch (ignoreCase ? name.toLowerCase() : name) { case "awsvaultconfiguration": case "AwsVaultConfiguration": target.setAwsVaultConfiguration(property(camelContext, org.apache.camel.vault.AwsVaultConfiguration.class, value)); return true; + case "azureidentityenabled": + case "AzureIdentityEnabled": target.setAzureIdentityEnabled(property(camelContext, boolean.class, value)); return true; case "azurevaultconfiguration": case "AzureVaultConfiguration": target.setAzureVaultConfiguration(property(camelContext, org.apache.camel.vault.AzureVaultConfiguration.class, value)); return true; case "blobaccesskey": @@ -60,6 +62,8 @@ public class AzureVaultConfigurationPropertiesConfigurer extends org.apache.came switch (ignoreCase ? name.toLowerCase() : name) { case "awsvaultconfiguration": case "AwsVaultConfiguration": return org.apache.camel.vault.AwsVaultConfiguration.class; + case "azureidentityenabled": + case "AzureIdentityEnabled": return boolean.class; case "azurevaultconfiguration": case "AzureVaultConfiguration": return org.apache.camel.vault.AzureVaultConfiguration.class; case "blobaccesskey": @@ -98,6 +102,8 @@ public class AzureVaultConfigurationPropertiesConfigurer extends org.apache.came switch (ignoreCase ? name.toLowerCase() : name) { case "awsvaultconfiguration": case "AwsVaultConfiguration": return target.getAwsVaultConfiguration(); + case "azureidentityenabled": + case "AzureIdentityEnabled": return target.isAzureIdentityEnabled(); case "azurevaultconfiguration": case "AzureVaultConfiguration": return target.getAzureVaultConfiguration(); case "blobaccesskey": diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 72f4180cad8..5577ce62cb1 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -276,6 +276,7 @@ { "name": "camel.vault.aws.region", "description": "The AWS region", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.aws.secretKey", "description": "The AWS secret key", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.aws.secrets", "description": "Specify the secret names (or pattern) to check for updates. Multiple secrets can be separated by comma.", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.vault.azure.azureIdentityEnabled", "description": "Whether the Azure Identity Authentication should be used or not.", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.vault.azure.blobAccessKey", "description": "The Eventhubs Blob Access Key for CheckpointStore purpose", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.azure.blobAccountName", "description": "The Eventhubs Blob Account Name for CheckpointStore purpose", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.vault.azure.blobContainerName", "description": "The Eventhubs Blob Container Name for CheckpointStore purpose", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration", "type": "string", "javaType": "java.lang.String" }, diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index cf27329b981..b4bbd92d60a 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -316,11 +316,12 @@ The camel.vault.gcp supports 7 options, which are listed below. === Camel Azure Key Vault configurations -The camel.vault.azure supports 11 options, which are listed below. +The camel.vault.azure supports 12 options, which are listed below. [width="100%",cols="2,5,^1,2",options="header"] |=== | Name | Description | Default | Type +| *camel.vault.azure.azure{zwsp}IdentityEnabled* | Whether the Azure Identity Authentication should be used or not. | false | boolean | *camel.vault.azure.blobAccess{zwsp}Key* | The Eventhubs Blob Access Key for CheckpointStore purpose | | String | *camel.vault.azure.blobAccount{zwsp}Name* | The Eventhubs Blob Account Name for CheckpointStore purpose | | String | *camel.vault.azure.blob{zwsp}ContainerName* | The Eventhubs Blob Container Name for CheckpointStore purpose | | String diff --git a/core/camel-main/src/main/java/org/apache/camel/main/AzureVaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/AzureVaultConfigurationProperties.java index 57f786cb978..4a15b5168b2 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/AzureVaultConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/AzureVaultConfigurationProperties.java @@ -81,6 +81,14 @@ public class AzureVaultConfigurationProperties extends AzureVaultConfiguration i return this; } + /** + * Whether the Azure Identity Authentication should be used or not. + */ + public AzureVaultConfigurationProperties withAzureIdentityEnabled(boolean azureIdentityEnabled) { + setAzureIdentityEnabled(azureIdentityEnabled); + return this; + } + /** * Whether to automatically reload Camel upon secrets being updated in Azure. */ diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainVaultTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainVaultTest.java index ca7ca42b3d8..18fcbe55a8e 100644 --- a/core/camel-main/src/test/java/org/apache/camel/main/MainVaultTest.java +++ b/core/camel-main/src/test/java/org/apache/camel/main/MainVaultTest.java @@ -201,6 +201,7 @@ public class MainVaultTest { Assertions.assertEquals("id1", cfg.getClientId()); Assertions.assertEquals("secret1", cfg.getClientSecret()); Assertions.assertEquals("tenant1", cfg.getTenantId()); + Assertions.assertEquals(false, cfg.isAzureIdentityEnabled()); main.stop(); } @@ -226,6 +227,7 @@ public class MainVaultTest { Assertions.assertEquals("id1", cfg.getClientId()); Assertions.assertEquals("secret1", cfg.getClientSecret()); Assertions.assertEquals("tenant1", cfg.getTenantId()); + Assertions.assertEquals(false, cfg.isAzureIdentityEnabled()); main.stop(); }
