From a56e964604c86a33e9b4b855c9ac99d0099026b9 Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Wed, 21 Aug 2024 08:51:03 -0700 Subject: [PATCH] App Config Sample with Entra ID (#753) * sameple with entra id * updating main readme and pom * Update pom.xml --------- Co-authored-by: Muyao Feng <92105726+Netyyyy@users.noreply.github.com> --- README.md | 1 + .../README.md | 96 +++++++++++++++++++ .../pom.xml | 41 ++++++++ .../example/AppConfigClientCustomizer.java | 21 ++++ .../main/java/example/AppConfiguration.java | 14 +++ .../src/main/java/example/Application.java | 14 +++ .../main/java/example/HelloController.java | 25 +++++ .../main/java/example/MessageProperties.java | 25 +++++ .../main/resources/META-INF/spring.factories | 3 + .../src/main/resources/bootstrap.properties | 5 + pom.xml | 2 + 11 files changed, 247 insertions(+) create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/README.md create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/pom.xml create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfigClientCustomizer.java create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfiguration.java create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/Application.java create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/HelloController.java create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/MessageProperties.java create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/META-INF/spring.factories create mode 100644 appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/bootstrap.properties diff --git a/README.md b/README.md index de1e5fc06..15ede2c95 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ | [spring-cloud-azure-feature-management-sample](appconfiguration/spring-cloud-azure-feature-management/spring-cloud-azure-feature-management-sample) | ✅ | ✅ | | [spring-cloud-azure-feature-management-web-sample](appconfiguration/spring-cloud-azure-feature-management-web) | ✅ | ✅ | | [spring-cloud-azure-starter-appconfiguration-config-sample](appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-sample) | ✅ | ✅ | +| [spring-cloud-azure-starter-appconfiguration-config-entraid-sample](appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample) | ✅ | ✅ | | [appconfiguration-client](appconfiguration/spring-cloud-azure-starter-appconfiguration/appconfiguration-client) | ✅ | ✅ | ### Azure Cache diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/README.md b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/README.md new file mode 100644 index 000000000..867e20fe8 --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/README.md @@ -0,0 +1,96 @@ +--- +page_type: sample +languages: +- java +products: +- azure-app-configuration +name: Refreshing Configuration Properties From App Configuration in Spring Boot Application using Entra ID +description: This sample demonstrates how to refresh configuration properties from App Configuration in Spring Boot application using Entra ID. +--- + +# Refreshing Configuration Properties From App Configuration in Spring Boot Application + +## Prerequisite + +* A [Java Development Kit (JDK)](https://docs.microsoft.com/java/azure/jdk/?view=azure-java-stable), version 8. +* [Apache Maven](http://maven.apache.org/), version 3.0 or later. + +## How to run + +### Setup your App Configuration Store + +1. To create your Azure App Configuration store, you can use: + + ```azurecli + az appconfig create --resource-group --name --sku Standard + ``` + +1. Create the test key in your new store: + + ```azurecli + az appconfig kv set --key /application/config.message --value testKey --name --yes + ``` + +1. Create monitor trigger. + + ```azurecli + az appconfig kv set --key sentinel --value 1 --name --yes + ``` + +This value should match the `spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].key` value in `bootstrap.properties`. + +### Setup your environment + +1. Set an environment variable named **APP_CONFIGURATION_ENDPOINT**, and set it to the endpoint to your App Configuration store. At the command line, run the following command and restart the command prompt to allow the change to take effect: + + ```cmd + setx APP_CONFIGURATION_ENDPOINT "endpoint-of-your-app-configuration-store" + ``` + + If you use Windows PowerShell, run the following command: + + ```azurepowershell + $Env:APP_CONFIGURATION_ENDPOINT = "endpoint-of-your-app-configuration-store" + ``` + + If you use macOS or Linux, run the following command: + + ```cmd + export APP_CONFIGURATION_ENDPOINT='endpoint-of-your-app-configuration-store' + ``` + +### Run the application + +1. Build the application + + ```console + mvn clean package + ``` + +1. Run the application + + ```console + mvn spring-boot:run + ``` + +1. Go to `localhost:8080` which will display the value `testKey`. + +1. Update key to new value. + + ```azurecli + az appconfig kv set --key /application/config.message --value updatedTestKey --name --yes + ``` + +1. Update monitor trigger, to trigger refresh. + + ```azurecli + az appconfig kv set --key sentinel --value 2 --name --yes + ``` + +1. Refresh page, this will trigger the refresh update. + +1. After a couple seconds refresh again, this time the new value `updatedTestKey` will show. + +## Deploy to Azure Spring Apps + +Now that you have the Spring Boot application running locally, it's time to move it to production. [Azure Spring Apps](https://learn.microsoft.com/azure/spring-apps/overview) makes it easy to deploy Spring Boot applications to Azure without any code changes. The service manages the infrastructure of Spring applications so developers can focus on their code. Azure Spring Apps provides lifecycle management using comprehensive monitoring and diagnostics, configuration management, service discovery, CI/CD integration, blue-green deployments, and more. To deploy your application to Azure Spring Apps, see [Deploy your first application to Azure Spring Apps](https://learn.microsoft.com/azure/spring-apps/quickstart?tabs=Azure-CLI). diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/pom.xml b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/pom.xml new file mode 100644 index 000000000..4fb734cbc --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/pom.xml @@ -0,0 +1,41 @@ + + + + com.azure.spring + azure-spring-boot-samples + 1.0.0 + ../../../pom.xml + + + 4.0.0 + + spring-cloud-azure-starter-appconfiguration-config-entraid-sample + 1.0.0 + jar + Azure App Configuration Refresh Sample with Entra ID + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + com.azure.spring + spring-cloud-azure-starter-appconfiguration-config + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfigClientCustomizer.java b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfigClientCustomizer.java new file mode 100644 index 000000000..94da0cd26 --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfigClientCustomizer.java @@ -0,0 +1,21 @@ +package example; + +import com.azure.data.appconfiguration.ConfigurationClientBuilder; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.azure.security.keyvault.secrets.SecretClientBuilder; +import com.azure.spring.cloud.appconfiguration.config.ConfigurationClientCustomizer; +import com.azure.spring.cloud.appconfiguration.config.SecretClientCustomizer; + +public class AppConfigClientCustomizer implements ConfigurationClientCustomizer, SecretClientCustomizer { + + @Override + public void customize(ConfigurationClientBuilder builder, String endpoint) { + builder.credential(new DefaultAzureCredentialBuilder().build()); + } + + @Override + public void customize(SecretClientBuilder builder, String endpoint) { + builder.credential(new DefaultAzureCredentialBuilder().build()); + } + +} diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfiguration.java b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfiguration.java new file mode 100644 index 000000000..bba686530 --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/AppConfiguration.java @@ -0,0 +1,14 @@ +package example; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfiguration { + + @Bean + public AppConfigClientCustomizer clientCustomizers() { + return new AppConfigClientCustomizer(); + } + +} diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/Application.java b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/Application.java new file mode 100644 index 000000000..903b5b353 --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/Application.java @@ -0,0 +1,14 @@ +package example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +@SpringBootApplication +@EnableConfigurationProperties +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/HelloController.java b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/HelloController.java new file mode 100644 index 000000000..99f289d6e --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/HelloController.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package example; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.core.JsonProcessingException; + +@RestController +public class HelloController { + + @Autowired + private MessageProperties properties; + + @GetMapping("") + public String getMessage() throws JsonProcessingException { + return properties.getMessage(); + } + +} diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/MessageProperties.java b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/MessageProperties.java new file mode 100644 index 000000000..06ff859c1 --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/java/example/MessageProperties.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package example; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "config") +public class MessageProperties { + + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/META-INF/spring.factories b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..ddfeebd2a --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.cloud.bootstrap.BootstrapConfiguration=\ +example.AppConfiguration + diff --git a/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/bootstrap.properties b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/bootstrap.properties new file mode 100644 index 000000000..f34424dc2 --- /dev/null +++ b/appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample/src/main/resources/bootstrap.properties @@ -0,0 +1,5 @@ +spring.cloud.azure.appconfiguration.stores[0].endpoint=${CONFIG_STORE_ENDPOINT} + +spring.cloud.azure.appconfiguration.stores[0].monitoring.enabled=true +spring.cloud.azure.appconfiguration.stores[0].monitoring.refresh-interval=5s +spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].key=sentinel diff --git a/pom.xml b/pom.xml index 180eb8e9f..e7bb8cf1f 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,7 @@ appconfiguration/spring-cloud-azure-feature-management-web/spring2samples/spring-cloud-azure-targeting-filter-web-sample appconfiguration/spring-cloud-azure-feature-management/spring-cloud-azure-feature-management-sample appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-sample + appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample appconfiguration/spring-cloud-azure-starter-appconfiguration/appconfiguration-client cache/spring2-sample/spring-cloud-azure-starter/spring-cloud-azure-sample-cache cache/spring2-sample/spring-cloud-azure-starter/spring-cloud-azure-sample-cache-passwordless @@ -160,6 +161,7 @@ appconfiguration/spring-cloud-azure-feature-management-web/spring3samples/spring-cloud-azure-targeting-filter-web-sample appconfiguration/spring-cloud-azure-feature-management/spring-cloud-azure-feature-management-sample appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-sample + appconfiguration/spring-cloud-azure-starter-appconfiguration-config/spring-cloud-azure-starter-appconfiguration-config-entraid-sample appconfiguration/spring-cloud-azure-starter-appconfiguration/appconfiguration-client cache/spring3-sample/spring-cloud-azure-redis-sample cache/spring3-sample/spring-cloud-azure-redis-sample-passwordless