diff --git a/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/README.md b/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/README.md
index a2a1acb5..23bdd0a2 100644
--- a/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/README.md
+++ b/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/README.md
@@ -70,6 +70,7 @@ Open `application.properties` file and add below properties to specify your Azur
azure.keyvault.uri=put-your-azure-keyvault-uri-here
azure.keyvault.client-id=put-your-azure-client-id-here
azure.keyvault.client-key=put-your-azure-client-key-here
+azure.keyvault.tenant-id=put-your-azure-tenant-id-here
# Uncomment following property if you want to specify the secrets to load from Key Vault
# azure.keyvault.secret.keys=yourSecretPropertyName1,yourSecretPropertyName2
diff --git a/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/src/main/resources/application.properties b/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/src/main/resources/application.properties
index 05c88a63..550e4e8e 100644
--- a/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/src/main/resources/application.properties
+++ b/azure-spring-boot-samples/azure-keyvault-secrets-spring-boot-sample/src/main/resources/application.properties
@@ -1,3 +1,4 @@
azure.keyvault.client-id=put-your-azure-client-id-here
azure.keyvault.client-key=put-your-azure-client-key-here
azure.keyvault.uri=put-your-azure-keyvault-uri-here
+azure.keyvault.tenant-id=
diff --git a/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/README.md b/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/README.md
index 4b0ff647..de0f6905 100644
--- a/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/README.md
+++ b/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/README.md
@@ -15,7 +15,7 @@ If you are using Maven, add the following dependency.
com.microsoft.azure
azure-keyvault-secrets-spring-boot-starter
- 0.2.3
+ 2.2.1
```
@@ -26,6 +26,7 @@ azure.keyvault.enabled=true
azure.keyvault.uri=put-your-azure-keyvault-uri-here
azure.keyvault.client-id=put-your-azure-client-id-here
azure.keyvault.client-key=put-your-azure-client-key-here
+azure.keyvault.tenant-id=put-your-azure-tenant-id-here
azure.keyvault.token-acquire-timeout-seconds=60
azure.keyvault.refresh-interval=1800000
azure.keyvault.secret.keys=key1,key2,key3
diff --git a/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/pom.xml b/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/pom.xml
index 09a4168e..08d0921c 100644
--- a/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/pom.xml
+++ b/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/pom.xml
@@ -34,16 +34,6 @@
com.microsoft.azure
azure-spring-boot
-
- com.microsoft.azure
- azure-keyvault
-
-
- com.microsoft.azure
- azure-client-runtime
-
-
-
com.microsoft.azure
azure-client-authentication
diff --git a/azure-spring-boot-tests/azure-spring-boot-test-application/pom.xml b/azure-spring-boot-tests/azure-spring-boot-test-application/pom.xml
index c0f73aad..b391121f 100644
--- a/azure-spring-boot-tests/azure-spring-boot-test-application/pom.xml
+++ b/azure-spring-boot-tests/azure-spring-boot-test-application/pom.xml
@@ -20,6 +20,7 @@
${project.basedir}/../..
UTF-8
UTF-8
+ 1.2.61
@@ -38,6 +39,12 @@
com.microsoft.azure
azure-keyvault-secrets-spring-boot-starter
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
diff --git a/azure-spring-boot-tests/azure-spring-boot-test-application/src/main/java/com/microsoft/azure/test/Application.java b/azure-spring-boot-tests/azure-spring-boot-test-application/src/main/java/com/microsoft/azure/test/Application.java
index 4d65547a..96305453 100644
--- a/azure-spring-boot-tests/azure-spring-boot-test-application/src/main/java/com/microsoft/azure/test/Application.java
+++ b/azure-spring-boot-tests/azure-spring-boot-test-application/src/main/java/com/microsoft/azure/test/Application.java
@@ -4,23 +4,41 @@
* license information.
*/
package com.microsoft.azure.test;
+
+import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.PropertySource;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+@Slf4j
@SpringBootApplication
@RestController
public class Application implements CommandLineRunner {
+ @Autowired
+ private ConfigurableEnvironment environment;
+
+
@Value("${azure.cosmosdb.key:local}")
private String cosmosDBkey;
private static ObjectMapper mapper = new ObjectMapper();
+
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@@ -40,6 +58,36 @@ public class Application implements CommandLineRunner {
return cosmosDBkey;
}
+ @GetMapping("env/{key}")
+ public String env(@PathVariable String key) {
+ final String property = environment.getProperty(key);
+ return property;
+ }
+
+ @GetMapping("list")
+ public String list() {
+ final List list = new ArrayList();
+ final MutablePropertySources propertySources = this.environment.getPropertySources();
+ final Iterator> iterator = propertySources.iterator();
+ while (iterator.hasNext()) {
+ final PropertySource> next = iterator.next();
+ list.add(next.getName());
+ }
+ return JSON.toJSONString(list);
+ }
+
+ @GetMapping("getSpecificProperty/{ps}/{key}")
+ public String getSpecificProperty(@PathVariable String ps, @PathVariable String key) {
+ final MutablePropertySources propertySources = this.environment.getPropertySources();
+ final PropertySource> propertySource = propertySources.get(ps);
+ if (propertySource != null) {
+ final Object property = propertySource.getProperty(key);
+ return property == null ? null : property.toString();
+ } else {
+ return null;
+ }
+ }
+
public void run(String... varl) throws Exception {
System.out.println("property your-property-name value is: " + cosmosDBkey);
}
diff --git a/azure-spring-boot-tests/azure-spring-boot-test-core/src/main/java/com/microsoft/azure/test/AppRunner.java b/azure-spring-boot-tests/azure-spring-boot-test-core/src/main/java/com/microsoft/azure/test/AppRunner.java
index ee81eb69..fa746e55 100644
--- a/azure-spring-boot-tests/azure-spring-boot-test-core/src/main/java/com/microsoft/azure/test/AppRunner.java
+++ b/azure-spring-boot-tests/azure-spring-boot-test-core/src/main/java/com/microsoft/azure/test/AppRunner.java
@@ -42,6 +42,18 @@ public class AppRunner implements AutoCloseable {
app = builder.build().run();
}
}
+
+ public ConfigurableApplicationContext start(String dummy) {
+ if (app == null) {
+ final SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
+ builder.properties("spring.jmx.enabled=false");
+ builder.properties(String.format("server.port=%d", availableTcpPort()));
+ builder.properties(props());
+
+ app = builder.build().run();
+ }
+ return app;
+ }
private int availableTcpPort() {
return SocketUtils.findAvailableTcpPort();
diff --git a/azure-spring-boot-tests/azure-spring-boot-test-keyvault/src/test/java/com/microsoft/azure/test/keyvault/KeyVaultIT.java b/azure-spring-boot-tests/azure-spring-boot-test-keyvault/src/test/java/com/microsoft/azure/test/keyvault/KeyVaultIT.java
index d7fa0290..a259948e 100755
--- a/azure-spring-boot-tests/azure-spring-boot-test-keyvault/src/test/java/com/microsoft/azure/test/keyvault/KeyVaultIT.java
+++ b/azure-spring-boot-tests/azure-spring-boot-test-keyvault/src/test/java/com/microsoft/azure/test/keyvault/KeyVaultIT.java
@@ -22,6 +22,10 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
@@ -85,8 +89,16 @@ public class KeyVaultIT {
app.property("azure.keyvault.uri", vault.vaultUri());
app.property("azure.keyvault.client-id", access.clientId());
app.property("azure.keyvault.client-key", access.clientSecret());
-
- app.start();
+ app.property("azure.keyvault.tenant-id", access.tenant());
+
+ final ConfigurableApplicationContext dummy = app.start("dummy");
+ final ConfigurableEnvironment environment = dummy.getEnvironment();
+ final MutablePropertySources propertySources = environment.getPropertySources();
+ for (final PropertySource> propertySource : propertySources) {
+ System.out.println("name = " + propertySource.getName() + "\nsource = " + propertySource
+ .getSource().getClass() + "\n");
+ }
+
assertEquals(KEY_VAULT_VALUE, app.getProperty("key"));
app.close();
log.info("--------------------->test over");
@@ -100,6 +112,7 @@ public class KeyVaultIT {
app.property("azure.keyvault.uri", vault.vaultUri());
app.property("azure.keyvault.client-id", access.clientId());
app.property("azure.keyvault.client-key", access.clientSecret());
+ app.property("azure.keyvault.tenant-id", access.tenant());
app.property("azure.keyvault.secret.keys", "key");
app.start();
@@ -133,6 +146,7 @@ public class KeyVaultIT {
appService.zipDeploy(zipFile);
log.info(String.format("Successfully deployed the artifact to https://%s",
appService.defaultHostName()));
+ break;
} catch (Exception e) {
log.debug(
String.format("Exception occurred when deploying the zip package: %s, " +
@@ -141,7 +155,9 @@ public class KeyVaultIT {
}
// Restart App Service
+ log.info("restarting app service...");
appService.restart();
+ log.info("restarting app service finished...");
final String resourceUrl = "https://" + appService.name() + ".azurewebsites.net" + "/get";
// warm up
@@ -179,7 +195,13 @@ public class KeyVaultIT {
// run java application
final List commands = new ArrayList<>();
commands.add(String.format("cd /home/%s", VM_USER_NAME));
- commands.add(String.format("nohup java -jar -Dazure.keyvault.uri=%s %s &", vault.vaultUri(),
+ commands.add(
+ String.
+ format("nohup java -jar -Xdebug " +
+ "-Xrunjdwp:server=y,transport=dt_socket,address=4000,suspend=n " +
+ "-Dazure.keyvault.uri=%s %s &" +
+ " >/log.txt 2>&1"
+ , vault.vaultUri(),
TEST_KEY_VAULT_JAR_FILE_NAME));
vmTool.runCommandOnVM(vm, commands);
@@ -191,6 +213,7 @@ public class KeyVaultIT {
assertEquals(response.getStatusCode(), HttpStatus.OK);
assertEquals(response.getBody(), KEY_VAULT_VALUE);
+ log.info("key vault value is: {}", response.getBody());
log.info("--------------------->test virtual machine with MSI over");
}
diff --git a/azure-spring-boot-tests/pom.xml b/azure-spring-boot-tests/pom.xml
index 67186362..8886ecb3 100644
--- a/azure-spring-boot-tests/pom.xml
+++ b/azure-spring-boot-tests/pom.xml
@@ -36,6 +36,7 @@
2.1.1
0.1.53
1.6
+ 3.3
@@ -92,9 +93,8 @@
commons-net
commons-net
- 3.3
+ ${commons.net.version}
-
@@ -168,8 +168,12 @@
maven-failsafe-plugin
- ${project.rootdir}/azure-spring-boot-tests/azure-spring-boot-test-application/target/app.jar
- ${project.rootdir}/azure-spring-boot-tests/azure-spring-boot-test-application/target/app.zip
+
+ ${project.rootdir}/azure-spring-boot-tests/azure-spring-boot-test-application/target/app.jar
+
+
+ ${project.rootdir}/azure-spring-boot-tests/azure-spring-boot-test-application/target/app.zip
+
diff --git a/azure-spring-boot/pom.xml b/azure-spring-boot/pom.xml
index 720e6f03..6d906f8f 100644
--- a/azure-spring-boot/pom.xml
+++ b/azure-spring-boot/pom.xml
@@ -151,16 +151,17 @@
azure-storage-blob
true
+
- com.microsoft.azure
- azure-keyvault
- true
-
-
- com.microsoft.azure
- azure-client-runtime
-
-
+ com.azure
+ azure-security-keyvault-secrets
+ 4.1.0
+
+
+
+ com.azure
+ azure-identity
+ 1.0.2
com.microsoft.azure
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultCredential.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultCredential.java
deleted file mode 100644
index 5d8dbb5f..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultCredential.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring;
-
-import com.microsoft.aad.adal4j.AuthenticationResult;
-import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;
-import com.microsoft.azure.utils.AADAuthUtil;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-
-public class AzureKeyVaultCredential extends KeyVaultCredentials {
- private static final long DEFAULT_TOKEN_ACQUIRE_TIMEOUT_IN_SECONDS = 60L;
- private String clientId;
- private String clientKey;
- private long timeoutInSeconds;
-
- private AADAuthUtil aadAuthUtil;
- private String token = "";
- private AtomicLong lastAcquireTokenTime = new AtomicLong();
- private AtomicLong expireIn = new AtomicLong();
- private static final long EXPIRE_BUFFER_TIME = 10 * 1000; //buffer time 10s
-
- public AzureKeyVaultCredential(String clientId, String clientKey, long timeoutInSeconds, AADAuthUtil aadAuthUtil) {
- this.clientId = clientId;
- this.clientKey = clientKey;
- this.timeoutInSeconds = timeoutInSeconds;
- this.aadAuthUtil = aadAuthUtil;
- }
-
- public AzureKeyVaultCredential(String clientId, String clientKey, long timeoutInSeconds) {
- this(clientId, clientKey, timeoutInSeconds, new AADAuthUtil());
- }
-
- public AzureKeyVaultCredential(String clientId, String clientKey) {
- this(clientId, clientKey, DEFAULT_TOKEN_ACQUIRE_TIMEOUT_IN_SECONDS);
- }
-
- @Override
- public String doAuthenticate(String authorization, String resource, String scope) {
- if (StringUtils.isEmpty(token) || needRefresh()) {
- refreshToken(authorization, resource);
- }
- return token;
- }
-
- private synchronized void refreshToken(String authorization, String resource) {
- if (!needRefresh()) { //double check
- return;
- }
-
- try {
- final AuthenticationResult result = aadAuthUtil.getToken(authorization,
- resource,
- clientId,
- clientKey,
- timeoutInSeconds);
- token = result.getAccessToken();
- expireIn.set(result.getExpiresAfter());
- lastAcquireTokenTime.set(System.currentTimeMillis());
- } catch (Exception ex) {
- throw new IllegalStateException("Failed to do authentication.", ex);
- }
- }
-
- private boolean needRefresh() {
- return ((System.currentTimeMillis() - lastAcquireTokenTime.get() + EXPIRE_BUFFER_TIME) / 1000) >=
- expireIn.get();
- }
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultMSICredential.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultMSICredential.java
deleted file mode 100644
index 907466e9..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultMSICredential.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring;
-
-import com.microsoft.azure.AzureEnvironment;
-import com.microsoft.azure.credentials.AzureTokenCredentials;
-import com.microsoft.azure.credentials.MSICredentials;
-import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;
-
-import java.io.IOException;
-
-public class AzureKeyVaultMSICredential extends KeyVaultCredentials {
- private final AzureTokenCredentials tokenCredentials;
-
- public AzureKeyVaultMSICredential(AzureTokenCredentials tokenCredentials) {
- this.tokenCredentials = tokenCredentials;
- }
-
- public AzureKeyVaultMSICredential(AzureEnvironment environment) {
- this.tokenCredentials = new MSICredentials(environment);
- }
-
- public AzureKeyVaultMSICredential(AzureEnvironment environment, String clientId) {
- this.tokenCredentials = new MSICredentials(environment).withClientId(clientId);
- }
-
- @Override
- public String doAuthenticate(String authorization, String resource, String scope) {
- try {
- return tokenCredentials.getToken(resource);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to do authentication.", e);
- }
- }
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/Constants.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/Constants.java
index 6890caad..ee86f3c2 100644
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/Constants.java
+++ b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/Constants.java
@@ -12,6 +12,7 @@ public class Constants {
public static final String AZURE_KEYVAULT_USER_AGENT = "spring-boot-starter/" + PropertyLoader.getProjectVersion();
public static final String AZURE_KEYVAULT_CLIENT_ID = "azure.keyvault.client-id";
public static final String AZURE_KEYVAULT_CLIENT_KEY = "azure.keyvault.client-key";
+ public static final String AZURE_KEYVAULT_TENANT_ID = "azure.keyvault.tenant-id";
public static final String AZURE_KEYVAULT_CERTIFICATE_PATH = "azure.keyvault.certificate.path";
public static final String AZURE_KEYVAULT_CERTIFICATE_PASSWORD = "azure.keyvault.certificate.password";
public static final String AZURE_KEYVAULT_ENABLED = "azure.keyvault.enabled";
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultCertificateCredential.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultCertificateCredential.java
deleted file mode 100644
index 39afa081..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultCertificateCredential.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring;
-
-import com.microsoft.aad.adal4j.AsymmetricKeyCredential;
-import com.microsoft.aad.adal4j.AuthenticationContext;
-import com.microsoft.aad.adal4j.AuthenticationResult;
-import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;
-import com.microsoft.azure.keyvault.spring.certificate.KeyCert;
-import com.microsoft.azure.keyvault.spring.certificate.KeyCertReader;
-import com.microsoft.azure.keyvault.spring.certificate.KeyCertReaderFactory;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.core.io.Resource;
-import org.springframework.util.Assert;
-
-import java.net.MalformedURLException;
-import java.security.PrivateKey;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-@Slf4j
-public class KeyVaultCertificateCredential extends KeyVaultCredentials {
- private static final long DEFAULT_TOKEN_ACQUIRE_TIMEOUT_IN_SECONDS = 60L;
- private final String clientId;
- private final Resource certResource;
- private final String certPassword;
- private final long timeoutInSeconds;
-
- public KeyVaultCertificateCredential(String clientId, Resource certResource, String certPassword,
- long timeoutInSeconds) {
- Assert.isTrue(certResource.exists(), String.format("Certificate file %s should exist.",
- certResource.getFilename()));
-
- this.clientId = clientId;
- this.certResource = certResource;
- this.certPassword = certPassword;
- this.timeoutInSeconds = timeoutInSeconds <= 0 ? DEFAULT_TOKEN_ACQUIRE_TIMEOUT_IN_SECONDS : timeoutInSeconds;
- }
-
- public KeyVaultCertificateCredential(String clientId, Resource certResource, String certPassword) {
- this(clientId, certResource, certPassword, DEFAULT_TOKEN_ACQUIRE_TIMEOUT_IN_SECONDS);
- }
-
- @Override
- public String doAuthenticate(String authorization, String resource, String scope) {
- final String certFileName = certResource.getFilename();
- final KeyCertReader certReader = KeyCertReaderFactory.getReader(certFileName);
-
- final KeyCert keyCert = certReader.read(certResource, certPassword);
-
- try {
- final AuthenticationContext context = new AuthenticationContext(authorization, false,
- Executors.newSingleThreadExecutor());
-
- final AsymmetricKeyCredential asymmetricKeyCredential = AsymmetricKeyCredential.create(clientId,
- keyCert.getKey(), keyCert.getCertificate());
-
- final AuthenticationResult authResult = context.acquireToken(resource, asymmetricKeyCredential, null)
- .get(timeoutInSeconds, TimeUnit.SECONDS);
-
- return authResult.getAccessToken();
- } catch (MalformedURLException | InterruptedException | ExecutionException | TimeoutException e) {
- final String errMsg = String.format("Failed to authenticate with Key Vault using certificate %s",
- certFileName);
- log.error(errMsg, e);
- throw new IllegalStateException(errMsg, e);
- }
- }
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessor.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessor.java
index 6b455aa7..92630863 100644
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessor.java
+++ b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessor.java
@@ -6,6 +6,7 @@
package com.microsoft.azure.keyvault.spring;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.env.EnvironmentPostProcessor;
@@ -13,13 +14,13 @@ import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ClassUtils;
+@Slf4j
public class KeyVaultEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
public static final int DEFAULT_ORDER = ConfigFileApplicationListener.DEFAULT_ORDER + 1;
private int order = DEFAULT_ORDER;
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
-
if (isKeyVaultEnabled(environment)) {
final KeyVaultEnvironmentPostProcessorHelper helper =
new KeyVaultEnvironmentPostProcessorHelper(environment);
@@ -37,7 +38,7 @@ public class KeyVaultEnvironmentPostProcessor implements EnvironmentPostProcesso
}
private boolean isKeyVaultClientAvailable() {
- return ClassUtils.isPresent("com.microsoft.azure.keyvault.KeyVaultClient",
+ return ClassUtils.isPresent("com.azure.security.keyvault.secrets.SecretClient",
KeyVaultEnvironmentPostProcessor.class.getClassLoader());
}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorHelper.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorHelper.java
index 49518f16..939074a9 100644
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorHelper.java
+++ b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorHelper.java
@@ -6,24 +6,21 @@
package com.microsoft.azure.keyvault.spring;
-import com.microsoft.azure.AzureEnvironment;
-import com.microsoft.azure.AzureResponseBuilder;
-import com.microsoft.azure.credentials.AppServiceMSICredentials;
-import com.microsoft.azure.keyvault.KeyVaultClient;
-import com.microsoft.azure.serializer.AzureJacksonAdapter;
-import com.microsoft.azure.spring.support.UserAgent;
+import com.azure.core.credential.TokenCredential;
+import com.azure.identity.ClientCertificateCredentialBuilder;
+import com.azure.identity.ClientSecretCredential;
+import com.azure.identity.ClientSecretCredentialBuilder;
+import com.azure.identity.ManagedIdentityCredentialBuilder;
+import com.azure.security.keyvault.secrets.SecretClient;
+import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.microsoft.azure.telemetry.TelemetrySender;
-import com.microsoft.rest.RestClient;
-import com.microsoft.rest.credentials.ServiceClientCredentials;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
-import org.springframework.core.io.DefaultResourceLoader;
-import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
@@ -32,14 +29,13 @@ import java.util.Optional;
import static com.microsoft.azure.telemetry.TelemetryData.SERVICE_NAME;
import static com.microsoft.azure.telemetry.TelemetryData.getClassPackageSimpleName;
+@Slf4j
class KeyVaultEnvironmentPostProcessorHelper {
- private static final Logger LOG = LoggerFactory.getLogger(KeyVaultEnvironmentPostProcessorHelper.class);
private final ConfigurableEnvironment environment;
public KeyVaultEnvironmentPostProcessorHelper(final ConfigurableEnvironment environment) {
this.environment = environment;
-
// As @PostConstructor not available when post processor, call it explicitly.
sendTelemetry();
}
@@ -50,21 +46,15 @@ class KeyVaultEnvironmentPostProcessorHelper {
this.environment.getProperty(Constants.AZURE_KEYVAULT_REFRESH_INTERVAL))
.map(Long::valueOf).orElse(Constants.DEFAULT_REFRESH_INTERVAL_MS);
final String secretKeys = this.environment.getProperty(Constants.AZURE_KEYVAULT_SECRET_KEYS);
- final ServiceClientCredentials credentials = getCredentials();
-
- final RestClient restClient = new RestClient.Builder().withBaseUrl(vaultUri)
- .withCredentials(credentials)
- .withSerializerAdapter(new AzureJacksonAdapter())
- .withResponseBuilderFactory(new AzureResponseBuilder.Factory())
- .withUserAgent(UserAgent.getUserAgent(Constants.AZURE_KEYVAULT_USER_AGENT,
- allowTelemetry(this.environment)))
- .build();
-
- final KeyVaultClient kvClient = new KeyVaultClient(restClient);
+ final TokenCredential tokenCredential = getCredentials();
+ final SecretClient secretClient = new SecretClientBuilder()
+ .vaultUrl(vaultUri)
+ .credential(tokenCredential)
+ .buildClient();
try {
final MutablePropertySources sources = this.environment.getPropertySources();
- final KeyVaultOperation kvOperation = new KeyVaultOperation(kvClient,
+ final KeyVaultOperation kvOperation = new KeyVaultOperation(secretClient,
vaultUri,
refreshInterval,
secretKeys);
@@ -81,62 +71,58 @@ class KeyVaultEnvironmentPostProcessorHelper {
}
}
- ServiceClientCredentials getCredentials() {
- if (this.environment.containsProperty("MSI_ENDPOINT")
- && this.environment.containsProperty("MSI_SECRET")) {
- LOG.debug("Will use MSI credentials for app services");
- final String msiEndpoint = getProperty(this.environment, "MSI_ENDPOINT");
- final String msiSecret = getProperty(this.environment, "MSI_SECRET");
- final AppServiceMSICredentials msiCredentials = new AppServiceMSICredentials(AzureEnvironment.AZURE,
- msiEndpoint, msiSecret);
-
- if (this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_ID)) {
- LOG.debug("Will use MSI credentials for app services with user assigned identity");
- final String clientId = getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_ID);
- msiCredentials.withClientId(clientId);
- }
-
- return msiCredentials;
- }
-
- final long timeAcquiringTimeoutInSeconds = this.environment.getProperty(
- Constants.AZURE_TOKEN_ACQUIRE_TIMEOUT_IN_SECONDS, Long.class, Constants.TOKEN_ACQUIRE_TIMEOUT_SECS);
+ public TokenCredential getCredentials() {
+ //use service principle to authenticate
if (this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_ID)
- && this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_KEY)) {
- LOG.debug("Will use custom credentials");
+ && this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_KEY)
+ && this.environment.containsProperty(Constants.AZURE_KEYVAULT_TENANT_ID)) {
+ log.debug("Will use custom credentials");
final String clientId = getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_ID);
final String clientKey = getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_KEY);
- return new AzureKeyVaultCredential(clientId, clientKey, timeAcquiringTimeoutInSeconds);
+ final String tenantId = getProperty(this.environment, Constants.AZURE_KEYVAULT_TENANT_ID);
+ final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
+ .clientId(clientId)
+ .clientSecret(clientKey)
+ .tenantId(tenantId)
+ .build();
+ return clientSecretCredential;
}
-
- if (this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_ID) &&
- this.environment.containsProperty(Constants.AZURE_KEYVAULT_CERTIFICATE_PATH)) {
- final String clientId = getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_ID);
+ //use certificate to authenticate
+ if (this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_ID)
+ && this.environment.containsProperty(Constants.AZURE_KEYVAULT_CERTIFICATE_PATH)
+ && this.environment.containsProperty(Constants.AZURE_KEYVAULT_TENANT_ID)) {
// Password can be empty
final String certPwd = this.environment.getProperty(Constants.AZURE_KEYVAULT_CERTIFICATE_PASSWORD);
final String certPath = getProperty(this.environment, Constants.AZURE_KEYVAULT_CERTIFICATE_PATH);
- LOG.info("Read certificate from {}...", certPath);
- final Resource certResource = new DefaultResourceLoader().getResource(certPath);
-
- return new KeyVaultCertificateCredential(clientId, certResource, certPwd, timeAcquiringTimeoutInSeconds);
+ if (StringUtils.isEmpty(certPwd)) {
+ return new ClientCertificateCredentialBuilder()
+ .tenantId(getProperty(this.environment, Constants.AZURE_KEYVAULT_TENANT_ID))
+ .clientId(getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_ID))
+ .pemCertificate(certPath)
+ .build();
+ } else {
+ return new ClientCertificateCredentialBuilder()
+ .tenantId(getProperty(this.environment, Constants.AZURE_KEYVAULT_TENANT_ID))
+ .clientId(getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_ID))
+ .pfxCertificate(certPath, certPwd)
+ .build();
+ }
}
+ //use MSI to authenticate
if (this.environment.containsProperty(Constants.AZURE_KEYVAULT_CLIENT_ID)) {
- LOG.debug("Will use MSI credentials for VMs with specified clientId");
+ log.debug("Will use MSI credentials with specified clientId");
final String clientId = getProperty(this.environment, Constants.AZURE_KEYVAULT_CLIENT_ID);
- return new AzureKeyVaultMSICredential(AzureEnvironment.AZURE, clientId);
+ return new ManagedIdentityCredentialBuilder().clientId(clientId).build();
}
-
- LOG.debug("Will use MSI credentials for VM");
- return new AzureKeyVaultMSICredential(AzureEnvironment.AZURE);
+ log.debug("Will use MSI credentials");
+ return new ManagedIdentityCredentialBuilder().build();
}
private String getProperty(final ConfigurableEnvironment env, final String propertyName) {
Assert.notNull(env, "env must not be null!");
Assert.notNull(propertyName, "propertyName must not be null!");
-
final String property = env.getProperty(propertyName);
-
if (property == null || property.isEmpty()) {
throw new IllegalArgumentException("property " + propertyName + " must not be null");
}
@@ -145,7 +131,6 @@ class KeyVaultEnvironmentPostProcessorHelper {
private boolean allowTelemetry(final ConfigurableEnvironment env) {
Assert.notNull(env, "env must not be null!");
-
return env.getProperty(Constants.AZURE_KEYVAULT_ALLOW_TELEMETRY, Boolean.class, true);
}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultOperation.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultOperation.java
index 2a028e25..fa09f0b4 100644
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultOperation.java
+++ b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/KeyVaultOperation.java
@@ -6,10 +6,10 @@
package com.microsoft.azure.keyvault.spring;
-import com.microsoft.azure.PagedList;
-import com.microsoft.azure.keyvault.KeyVaultClient;
-import com.microsoft.azure.keyvault.models.SecretBundle;
-import com.microsoft.azure.keyvault.models.SecretItem;
+import com.azure.core.http.rest.PagedIterable;
+import com.azure.security.keyvault.secrets.SecretClient;
+import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
+import com.azure.security.keyvault.secrets.models.SecretProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
@@ -27,7 +27,7 @@ public class KeyVaultOperation {
private final String[] secretKeys;
private final Object refreshLock = new Object();
- private final KeyVaultClient keyVaultClient;
+ private final SecretClient keyVaultClient;
private final String vaultUri;
private ArrayList propertyNames = new ArrayList<>();
@@ -36,7 +36,7 @@ public class KeyVaultOperation {
private final AtomicLong lastUpdateTime = new AtomicLong();
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
- public KeyVaultOperation(final KeyVaultClient keyVaultClient,
+ public KeyVaultOperation(final SecretClient keyVaultClient,
String vaultUri,
final long refreshInterval,
final String secretKeysConfig) {
@@ -111,8 +111,8 @@ public class KeyVaultOperation {
refreshPropertyNames();
}
if (this.propertyNames.contains(secretName)) {
- final SecretBundle secretBundle = this.keyVaultClient.getSecret(this.vaultUri, secretName);
- return secretBundle == null ? null : secretBundle.value();
+ final KeyVaultSecret secret = this.keyVaultClient.getSecret(secretName);
+ return secret == null ? null : secret.getValue();
} else {
return null;
}
@@ -135,11 +135,9 @@ public class KeyVaultOperation {
if (this.secretKeys == null || secretKeys.length == 0) {
this.propertyNames.clear();
- final PagedList secrets = this.keyVaultClient.listSecrets(this.vaultUri);
- secrets.loadAll();
-
- secrets.forEach(s -> {
- final String secretName = s.id().replace(vaultUri + "/secrets/", "");
+ final PagedIterable secretProperties = keyVaultClient.listPropertiesOfSecrets();
+ secretProperties.forEach(s -> {
+ final String secretName = s.getName().replace(vaultUri + "/secrets/", "");
addSecretIfNotExist(secretName);
});
@@ -157,12 +155,9 @@ public class KeyVaultOperation {
private void addSecretIfNotExist(final String secretName) {
final String secretNameLowerCase = secretName.toLowerCase(Locale.US);
-
if (!propertyNames.contains(secretNameLowerCase)) {
propertyNames.add(secretNameLowerCase);
}
-
-
final String secretNameSeparatedByDot = secretNameLowerCase.replaceAll("-", ".");
if (!propertyNames.contains(secretNameSeparatedByDot)) {
propertyNames.add(secretNameSeparatedByDot);
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCert.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCert.java
deleted file mode 100644
index d478189b..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCert.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring.certificate;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-@Getter
-@AllArgsConstructor
-public class KeyCert {
- private final X509Certificate certificate;
- private final PrivateKey key;
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCertReader.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCertReader.java
deleted file mode 100644
index fcd723a3..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCertReader.java
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring.certificate;
-
-import org.springframework.core.io.Resource;
-
-public interface KeyCertReader {
- KeyCert read(Resource resource, String password);
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCertReaderFactory.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCertReaderFactory.java
deleted file mode 100644
index 0b361616..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/KeyCertReaderFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring.certificate;
-
-import org.apache.commons.io.FilenameUtils;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * Factory to create different certificate reader based on extension.
- */
-public class KeyCertReaderFactory {
- private static final ConcurrentMap readerMap = new ConcurrentHashMap<>();
- private static final String NOT_SUPPORTED_CERT = "Certificate type %s not supported.";
- private static final String PFX_EXTENSION = "pfx";
-
- public static KeyCertReader getReader(String certFile) {
- final String extension = FilenameUtils.getExtension(certFile);
-
- switch (extension) {
- case PFX_EXTENSION:
- return readerMap.computeIfAbsent(PFX_EXTENSION, k -> new PfxCertReader());
- default:
- throw new IllegalStateException(String.format(NOT_SUPPORTED_CERT, extension));
- }
- }
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/PfxCertReader.java b/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/PfxCertReader.java
deleted file mode 100644
index fe4e351d..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/keyvault/spring/certificate/PfxCertReader.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring.certificate;
-
-import org.springframework.core.io.Resource;
-
-import java.io.*;
-import java.security.*;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Enumeration;
-
-public class PfxCertReader implements KeyCertReader {
- private String CERT_NOT_FOUND = "Cert file %s not found.";
- private String CERT_READ_FAILURE = "Failed to read cert file %s.";
- private KeyStore store;
-
- @Override
- public KeyCert read(Resource resource, String password) {
- try (InputStream inputStream = resource.getInputStream()) {
- getOrInitPKCS12Store();
-
- final char[] passwordArray = password == null ? new char[]{} : password.toCharArray();
- store.load(inputStream, passwordArray);
-
- final Enumeration aliases = store.aliases();
- while (aliases.hasMoreElements()) {
- final String alias = aliases.nextElement();
-
- if (store.getCertificate(alias).getType().equals("X.509") && store.isKeyEntry(alias)) {
- final X509Certificate certificate = (X509Certificate) store.getCertificate(alias);
- final PrivateKey key = (PrivateKey) store.getKey(alias, passwordArray);
-
- return new KeyCert(certificate, key);
- }
- }
-
- throw new IllegalStateException(String.format(CERT_READ_FAILURE, resource.getFilename()));
- } catch (FileNotFoundException e) {
- throw new IllegalStateException(String.format(CERT_NOT_FOUND, resource.getFilename()), e);
- } catch (IOException | KeyStoreException | NoSuchProviderException | NoSuchAlgorithmException |
- UnrecoverableKeyException | CertificateException e) {
- throw new IllegalStateException(String.format(CERT_READ_FAILURE, resource.getFilename()), e);
- }
- }
-
- private void getOrInitPKCS12Store() throws KeyStoreException, NoSuchProviderException {
- if (this.store == null) {
- this.store = KeyStore.getInstance("pkcs12", "SunJSSE");
- }
- }
-}
diff --git a/azure-spring-boot/src/main/java/com/microsoft/azure/utils/AADAuthUtil.java b/azure-spring-boot/src/main/java/com/microsoft/azure/utils/AADAuthUtil.java
deleted file mode 100644
index 9bb206c5..00000000
--- a/azure-spring-boot/src/main/java/com/microsoft/azure/utils/AADAuthUtil.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.utils;
-
-import com.microsoft.aad.adal4j.AuthenticationContext;
-import com.microsoft.aad.adal4j.AuthenticationResult;
-import com.microsoft.aad.adal4j.ClientCredential;
-
-import java.net.MalformedURLException;
-import java.util.concurrent.*;
-
-public class AADAuthUtil {
- public AuthenticationResult getToken(String authorization,
- String resource,
- String clientId,
- String clientKey,
- long tokenAcquireTimeout) {
- AuthenticationContext context = null;
- AuthenticationResult result = null;
- final ExecutorService executorService = Executors.newSingleThreadExecutor();
- try {
- context = new AuthenticationContext(authorization, false, executorService);
- final ClientCredential credential = new ClientCredential(clientId, clientKey);
-
- final Future future = context.acquireToken(resource, credential, null);
- result = future.get(tokenAcquireTimeout, TimeUnit.SECONDS);
- } catch (MalformedURLException | TimeoutException | InterruptedException | ExecutionException ex) {
- throw new IllegalStateException("Failed to do authentication.", ex);
- } finally {
- executorService.shutdown();
- }
- return result;
- }
-}
diff --git a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultCredentialUnitTest.java b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultCredentialUnitTest.java
deleted file mode 100644
index 77796221..00000000
--- a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/AzureKeyVaultCredentialUnitTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring;
-
-import com.microsoft.aad.adal4j.AuthenticationResult;
-import com.microsoft.azure.utils.AADAuthUtil;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class AzureKeyVaultCredentialUnitTest {
-
- @Test(expected = RuntimeException.class)
- public void testDoAuthenticationRejctIfInvalidCredential() {
- final AzureKeyVaultCredential keyVaultCredential = new AzureKeyVaultCredential("fakeClientId",
- "fakeClientKey",
- Constants.TOKEN_ACQUIRE_TIMEOUT_SECS);
- keyVaultCredential.doAuthenticate("https://fakeauthorizationurl.com", "keyvault", "scope");
- }
-
- @Test
- public void testDoAuthenticationPass() throws Exception {
- final MockAADAuthUtil mockAADAuthUtil = new MockAADAuthUtil("token1", 11L);
- final AzureKeyVaultCredential keyVaultCredential = new AzureKeyVaultCredential("fakeClientId",
- "fakeClientKey",
- Constants.TOKEN_ACQUIRE_TIMEOUT_SECS,
- mockAADAuthUtil);
- final String token = keyVaultCredential.doAuthenticate("https://fakeauthorizationurl.com", "keyvault", "scope");
- //assert token from cache
- mockAADAuthUtil.updateToken("token2");
- assertThat(keyVaultCredential.doAuthenticate("https://fakeauthorizationurl.com",
- "keyvault",
- "scope")).isEqualTo(token);
- //assert token refresh
- Thread.sleep(1000L);
- assertThat(keyVaultCredential.doAuthenticate("https://fakeauthorizationurl.com",
- "keyvault",
- "scope")).isNotEqualTo(token);
- }
-
- class MockAADAuthUtil extends AADAuthUtil {
- private AuthenticationResult result;
-
- public void updateToken(String token) {
- result = new AuthenticationResult("mockType",
- token,
- "mockRefreshToken",
- result.getExpiresAfter(),
- "mockIdToken",
- null,
- true);
- }
-
- public MockAADAuthUtil(String token, long expiresIn) {
- this.result = new AuthenticationResult("mockType",
- token,
- "mockRefreshToken",
- expiresIn,
- "mockIdToken",
- null,
- true);
- }
-
- @Override
- public AuthenticationResult getToken(String authorization,
- String resource,
- String clientId,
- String clientKey,
- long tokenAcquireTimeout) {
- return result;
- }
- }
-}
diff --git a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyCertReaderFactoryTest.java b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyCertReaderFactoryTest.java
deleted file mode 100644
index c6832940..00000000
--- a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyCertReaderFactoryTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring;
-
-import com.microsoft.azure.keyvault.spring.certificate.KeyCertReader;
-import com.microsoft.azure.keyvault.spring.certificate.KeyCertReaderFactory;
-import com.microsoft.azure.keyvault.spring.certificate.PfxCertReader;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class KeyCertReaderFactoryTest {
- private static final String FAKE_PFX_CERT = "fake-pfx-cert.pfx";
-
- @Test
- public void testPfxCertificateReader() {
- final KeyCertReader certReader = KeyCertReaderFactory.getReader(FAKE_PFX_CERT);
- assertThat(certReader).isInstanceOf(PfxCertReader.class);
- }
-}
diff --git a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyCertReaderTest.java b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyCertReaderTest.java
deleted file mode 100644
index 7b61ee2c..00000000
--- a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyCertReaderTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for
- * license information.
- */
-package com.microsoft.azure.keyvault.spring;
-
-import com.microsoft.azure.keyvault.spring.certificate.KeyCert;
-import com.microsoft.azure.keyvault.spring.certificate.PfxCertReader;
-import org.junit.Test;
-import org.springframework.core.io.DefaultResourceLoader;
-import org.springframework.core.io.Resource;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class KeyCertReaderTest {
- private static final String TEST_PFX_FILE = "testkeyvault.pfx";
- private static final String TEST_SUBJECT = "CN=testkeyvault";
- private static final String TEST_PFX_PASSWORD = "123456";
-
- private static final String TEST_NO_PASSWORD_PFX_FILE = "nopwdcert.pfx";
- private static final String TEST_NO_PASSWORD_SUBJECT = "CN=nopwdcert";
- private static final String TEST_NO_PASSWORD = null;
-
- @Test
- public void testPfxCertReaderCanRead() {
- validatePfxCertRead(TEST_PFX_FILE, TEST_PFX_PASSWORD, TEST_SUBJECT);
- }
-
- @Test
- public void testPfxCertNoPasswordReaderCanRead() {
- validatePfxCertRead(TEST_NO_PASSWORD_PFX_FILE, TEST_NO_PASSWORD, TEST_NO_PASSWORD_SUBJECT);
- }
-
- private void validatePfxCertRead(String file, String password, String expectedSubject) {
- final Resource resource = new DefaultResourceLoader().getResource(file);
- final PfxCertReader reader = new PfxCertReader();
- final KeyCert pfxCert = reader.read(resource, password);
-
- assertThat(pfxCert).isNotNull();
- assertThat(pfxCert.getCertificate()).isNotNull();
- assertThat(pfxCert.getCertificate().getSubjectX500Principal().getName()).isEqualTo(expectedSubject);
- assertThat(pfxCert.getKey()).isNotNull();
- }
-}
diff --git a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorTest.java b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorTest.java
index 80096047..58acf35b 100644
--- a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorTest.java
+++ b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultEnvironmentPostProcessorTest.java
@@ -6,9 +6,10 @@
package com.microsoft.azure.keyvault.spring;
-import com.microsoft.azure.credentials.AppServiceMSICredentials;
-import com.microsoft.azure.credentials.MSICredentials;
-import com.microsoft.rest.credentials.ServiceClientCredentials;
+import com.azure.core.credential.TokenCredential;
+import com.azure.identity.ClientCertificateCredential;
+import com.azure.identity.ClientSecretCredential;
+import com.azure.identity.ManagedIdentityCredential;
import org.hamcrest.core.IsInstanceOf;
import org.junit.Before;
import org.junit.Test;
@@ -25,8 +26,8 @@ import org.springframework.mock.env.MockEnvironment;
import java.util.HashMap;
import java.util.Map;
-import static com.microsoft.azure.keyvault.spring.Constants.AZURE_KEYVAULT_CLIENT_ID;
import static com.microsoft.azure.keyvault.spring.Constants.AZURE_KEYVAULT_CERTIFICATE_PATH;
+import static com.microsoft.azure.keyvault.spring.Constants.AZURE_KEYVAULT_CLIENT_ID;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -43,6 +44,33 @@ public class KeyVaultEnvironmentPostProcessorTest {
propertySources = environment.getPropertySources();
}
+ @Test
+ public void testGetCredentialsWhenUsingClientAndKey() {
+ testProperties.put("azure.keyvault.client-id", "aaaa-bbbb-cccc-dddd");
+ testProperties.put("azure.keyvault.client-key", "mySecret");
+ testProperties.put("azure.keyvault.tenant-id", "myid");
+ propertySources.addLast(new MapPropertySource("Test_Properties", testProperties));
+
+ keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
+
+ final TokenCredential credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
+
+ assertThat(credentials, IsInstanceOf.instanceOf(ClientSecretCredential.class));
+ }
+
+ @Test
+ public void testGetCredentialsWhenPFXCertConfigured() {
+ testProperties.put(AZURE_KEYVAULT_CLIENT_ID, "aaaa-bbbb-cccc-dddd");
+ testProperties.put("azure.keyvault.tenant-id", "myid");
+ testProperties.put(AZURE_KEYVAULT_CERTIFICATE_PATH, "fake-pfx-cert.pfx");
+
+ propertySources.addLast(new MapPropertySource("Test_Properties", testProperties));
+ keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
+
+ final TokenCredential credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
+ assertThat(credentials, IsInstanceOf.instanceOf(ClientCertificateCredential.class));
+ }
+
@Test
public void testGetCredentialsWhenMSIEnabledInAppService() {
testProperties.put("MSI_ENDPOINT", "fakeendpoint");
@@ -51,23 +79,12 @@ public class KeyVaultEnvironmentPostProcessorTest {
keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
- final ServiceClientCredentials credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
+ final TokenCredential credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
- assertThat(credentials, IsInstanceOf.instanceOf(AppServiceMSICredentials.class));
+ assertThat(credentials, IsInstanceOf.instanceOf(ManagedIdentityCredential.class));
}
- @Test
- public void testGetCredentialsWhenUsingClientAndKey() {
- testProperties.put("azure.keyvault.client-id", "aaaa-bbbb-cccc-dddd");
- testProperties.put("azure.keyvault.client-key", "mySecret");
- propertySources.addLast(new MapPropertySource("Test_Properties", testProperties));
- keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
-
- final ServiceClientCredentials credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
-
- assertThat(credentials, IsInstanceOf.instanceOf(AzureKeyVaultCredential.class));
- }
@Test
public void testGetCredentialsWhenMSIEnabledInVMWithClientId() {
@@ -76,30 +93,18 @@ public class KeyVaultEnvironmentPostProcessorTest {
keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
- final ServiceClientCredentials credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
+ final TokenCredential credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
- assertThat(credentials, IsInstanceOf.instanceOf(AzureKeyVaultMSICredential.class));
+ assertThat(credentials, IsInstanceOf.instanceOf(ManagedIdentityCredential.class));
}
@Test
public void testGetCredentialsWhenMSIEnabledInVMWithoutClientId() {
keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
- final ServiceClientCredentials credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
+ final TokenCredential credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
- assertThat(credentials, IsInstanceOf.instanceOf(AzureKeyVaultMSICredential.class));
- }
-
- @Test
- public void testGetCredentialsWhenPFXCertConfigured() {
- testProperties.put(AZURE_KEYVAULT_CLIENT_ID, "aaaa-bbbb-cccc-dddd");
- testProperties.put(AZURE_KEYVAULT_CERTIFICATE_PATH, "fake-pfx-cert.pfx");
-
- propertySources.addLast(new MapPropertySource("Test_Properties", testProperties));
- keyVaultEnvironmentPostProcessorHelper = new KeyVaultEnvironmentPostProcessorHelper(environment);
-
- final ServiceClientCredentials credentials = keyVaultEnvironmentPostProcessorHelper.getCredentials();
- assertThat(credentials, IsInstanceOf.instanceOf(KeyVaultCertificateCredential.class));
+ assertThat(credentials, IsInstanceOf.instanceOf(ManagedIdentityCredential.class));
}
@Test
diff --git a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultOperationUnitTest.java b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultOperationUnitTest.java
index fa6e23a6..e81e3911 100644
--- a/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultOperationUnitTest.java
+++ b/azure-spring-boot/src/test/java/com/microsoft/azure/keyvault/spring/KeyVaultOperationUnitTest.java
@@ -5,20 +5,19 @@
*/
package com.microsoft.azure.keyvault.spring;
-import com.microsoft.azure.Page;
-import com.microsoft.azure.PagedList;
-import com.microsoft.azure.keyvault.KeyVaultClient;
-import com.microsoft.azure.keyvault.models.SecretBundle;
-import com.microsoft.azure.keyvault.models.SecretItem;
-import com.microsoft.rest.RestException;
+import com.azure.core.http.rest.PagedFlux;
+import com.azure.core.http.rest.PagedIterable;
+import com.azure.security.keyvault.secrets.SecretClient;
+import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
+import com.azure.security.keyvault.secrets.models.SecretProperties;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
+import java.util.function.Consumer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
@@ -32,7 +31,7 @@ public class KeyVaultOperationUnitTest {
private static final String secretKey1 = "key1";
- private static final String fakeVaultUri = "https://fake.vault.com";
+ private static final String fakeVaultUri = "https:fake.vault.com";
private static final String TEST_SPRING_RELAXED_BINDING_NAME_0 = "acme.my-project.person.first-name";
@@ -52,27 +51,15 @@ public class KeyVaultOperationUnitTest {
);
@Mock
- private KeyVaultClient keyVaultClient;
+ private SecretClient keyVaultClient;
private KeyVaultOperation keyVaultOperation;
public void setupSecretBundle(String id, String value, String secretKeysConfig) {
- final PagedList mockResult = new PagedList() {
- @Override
- public Page nextPage(String s) throws RestException {
- return new MockPage();
- }
- };
-
- final SecretItem secretItem = new SecretItem();
- secretItem.withId(id);
- mockResult.add(secretItem);
-
- final SecretBundle secretBundle = new SecretBundle();
-
- secretBundle.withId(id).withValue(value);
-
- when(keyVaultClient.listSecrets(anyString())).thenReturn(mockResult);
- when(keyVaultClient.getSecret(anyString(), anyString())).thenReturn(secretBundle);
+ //provision for list
+ when(keyVaultClient.listPropertiesOfSecrets()).thenReturn(new MockPage(new PagedFlux<>(() -> null), id));
+ //provison for get
+ final KeyVaultSecret secretBundle = new KeyVaultSecret(id, value);
+ when(keyVaultClient.getSecret(anyString())).thenReturn(secretBundle);
keyVaultOperation = new KeyVaultOperation(keyVaultClient,
fakeVaultUri,
Constants.TOKEN_ACQUIRE_TIMEOUT_SECS,
@@ -135,20 +122,39 @@ public class KeyVaultOperationUnitTest {
);
}
+ class MockPage extends PagedIterable {
+ private String name;
- class MockPage implements Page {
+ public MockPage(PagedFlux pagedFlux, String name) {
+ super(pagedFlux);
+ this.name = name;
+ }
- final SecretItem mockSecretItem = new SecretItem();
-
- @Override
- public String nextPageLink() {
- return null;
+ /**
+ * Creates instance given {@link PagedFlux}.
+ *
+ * @param pagedFlux to use as iterable
+ */
+ public MockPage(PagedFlux pagedFlux) {
+ super(pagedFlux);
}
@Override
- public List items() {
- mockSecretItem.withId("testPropertyName1");
- return Collections.singletonList(mockSecretItem);
+ public void forEach(Consumer super SecretProperties> action) {
+ action.accept(new MockSecretProperties(name));
+ }
+ }
+
+ class MockSecretProperties extends SecretProperties {
+ private String name;
+
+ public MockSecretProperties(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
}
}
}