Skip to content

Commit 08034ba

Browse files
committed
update custom domain in migrate to aca
1 parent c3310d0 commit 08034ba

File tree

1 file changed

+102
-120
lines changed

1 file changed

+102
-120
lines changed

articles/spring-apps/migration/migrate-to-azure-container-apps-custom-domain.md

Lines changed: 102 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -117,140 +117,122 @@ For more information, see the [Peer-to-peer encryption](../../container-apps/net
117117

118118
## Traffic to external services
119119

120-
### Reference a certificate from Key Vault and mount certificates in a volume
120+
When you define a certificate, you create a reference to a certifiacte stored in Azure Key Vault. You can enable TLS and mTLS for traffic to external services by loading the certificate from Azure Key Vault with `spring-cloud-azure-starter-keyvault-jca`.
121121

122-
When you define a certificate, you create a reference to a certificate stored in Azure Key Vault. Azure Container Apps automatically retrieves the certificate value from Key Vault and makes it available as a secret in your container app.
122+
To use this feature, your java project must be Spring Boot 3.1+ and adding the following dependency to your `pom.xml`:
123123

124-
To reference a certificate from Key Vault, you must first enable managed identity in your container app and grant the identity access to the Key Vault secrets.
125-
126-
To enable managed identity in your container app, see [Managed identities in Azure Container Apps](../../container-apps/managed-identity.md).
127-
128-
To grant access to a Key Vault certificate, add the role assignment `Key Vault Secrets User` in Key Vault for the managed identity you created. For more information, see [Best Practices for individual keys, secrets, and certificates role assignments](/azure/key-vault/general/rbac-guide#best-practices-for-individual-keys-secrets-and-certificates-role-assignments).
129-
130-
When you create a container app, certificates are defined using the `--secrets` parameter and using the following guidelines:
131-
132-
- The parameter accepts a space-delimited set of name/value pairs.
133-
- Each pair is delimited by an equals sign (`=`).
134-
- To specify a Key Vault reference, use the format `<certificate-name>=keyvaultref:<key-vault-secret-identifier-of-certificate>,identityref:<managed-identity-ID>`. For example, `my-cert=keyvaultref:https://mykeyvault.vault.azure.net/secrets/mycert,identityref:/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/my-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-identity`.
135-
136-
The following command provides an example:
137-
138-
```azurecli
139-
az containerapp create \
140-
--resource-group "my-resource-group" \
141-
--name "my-app" \
142-
--environment "my-environment-name" \
143-
--image <image_name> \
144-
--user-assigned "<user-assigned-identity-ID>" \
145-
--secrets "my-cert=keyvaultref:<key-vault-secret-identifier-of-certificate>,identityref:<user-assigned-identity-ID>"
146-
--secret-volume-mount "/mnt/cert"
124+
```xml
125+
<dependency>
126+
<groupId>com.azure.spring</groupId>
127+
<artifactId>spring-cloud-azure-starter-keyvault-jca</artifactId>
128+
<version>5.21.0</version>
129+
</dependency>
147130
```
148131

149-
Here, a certificate is declared in the `--secrets` parameter. Replace `<key-vault-secret-identifier-of-certificate>` with the Secret Identifier URI of your certificate in Key Vault. Replace `<user-assigned-identity-ID>` with the resource ID of the user assigned identity. For a system assigned identity, use `system` instead of the resource ID. The certificate mounted in a volume is named `my-cert` of type Secret. The volume is mounted at the path **/mnt/cert**. The application can then read the secrets as files in the volume mount.
150-
151-
For an existing container app, you can use following commands to reference a secret from Key Vault and mount it to a volume:
152-
153-
```azurecli
154-
az containerapp secret set \
155-
--resource-group "my-resource-group" \
156-
--name "my-app" \
157-
--secrets "my-cert=keyvaultref:<key-vault-secret-identifier-of-certificate>,identityref:<user-assigned-identity-ID>"
158-
159-
az containerapp update \
160-
--resource-group "my-resource-group" \
161-
--name "my-app" \
162-
--secret-volume-mount "/mnt/cert"
132+
### Load certificate into truststore from Key Vault with SSL bundle
133+
134+
1. Generate or import certificates in Azure Key Vault. For more information, see [Create and import certificates in Azure Key Vault](/azure/key-vault/certificates/certificate-scenarios#creating-and-importing-certificates).
135+
1. Enable managed identity in your container app. To enable managed identity in your container app, see [Managed identities in Azure Container Apps](../../container-apps/managed-identity.md).
136+
1. Grant the `Key Vault Certificate User` role to the managed identity in your Key Vault. For more information, see [Best Practices for individual keys, secrets, and certificates role assignments](/azure/key-vault/general/rbac-guide#best-practices-for-individual-keys-secrets-and-certificates-role-assignments).
137+
1. Configure `application.yml`:
138+
139+
```yml
140+
spring:
141+
ssl:
142+
bundle:
143+
keyvault:
144+
tlsClientBundle:
145+
truststore:
146+
keyvault-ref: keyvault1
147+
cloud:
148+
azure:
149+
keyvault:
150+
jca:
151+
vaults:
152+
keyvault1:
153+
endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
154+
profile:
155+
tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID} # Required for user-assigned managed identity
156+
credential:
157+
client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID} # Required for user-assigned managed identity
158+
managed-identity-enabled: true
163159
```
164160

165-
### Load a certificate from code
166-
167-
Your loaded certificates are available in your defined mounted path - for example, **/mnt/cert/my-cert**. Use the following Java code to load a certificate in an application in Azure Container Apps.
168-
169-
Because the certificate is mounted as a secret, its content is encoded in Base64, so you might need to decode it before use.
161+
1. Update your `RestTemplate` or `WebClient` bean configuration to apply the Key Vault SSL bundle:
170162

171163
```java
172-
try {
173-
byte[] encodedBytes = Files.readAllBytes(Paths.get("/mnt/cert/my-cert"));
174-
PKCS12PfxPdu pfx = new PKCS12PfxPdu(Base64.getDecoder().decode(encodedBytes));
175-
List<Certificate> certificates = new ArrayList<>();
176-
for (ContentInfo contentInfo : pfx.getContentInfos()) {
177-
if (contentInfo.getContentType().equals(PKCSObjectIdentifiers.encryptedData)) {
178-
PKCS12SafeBagFactory safeBagFactory = new PKCS12SafeBagFactory(contentInfo,
179-
new JcePKCSPBEInputDecryptorProviderBuilder().build("\0".toCharArray()));
180-
PKCS12SafeBag[] safeBags = safeBagFactory.getSafeBags();
181-
for (PKCS12SafeBag safeBag : safeBags) {
182-
Object bagValue = safeBag.getBagValue();
183-
if (bagValue instanceof X509CertificateHolder) {
184-
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
185-
InputStream in = new ByteArrayInputStream(((X509CertificateHolder) bagValue).getEncoded());
186-
certificates.add(certFactory.generateCertificate(in));
187-
}
188-
}
189-
}
190-
}
191-
192-
// use the loaded certificate in 'certificates'
193-
} catch (PKCSException | CertificateException | IOException e) {
194-
// handle exception
164+
// For RestTemplate
165+
@Bean
166+
RestTemplate restTemplateWithTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
167+
return restTemplateBuilder.sslBundle(sslBundles.getBundle("tlsClientBundle")).build();
195168
}
196-
```
197-
198-
In this sample code, you need to import [org.bouncycastle.bcpkix-lts8on](https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-lts8on) to your project to parse the certificate data.
199-
200-
### Load a certificate into the trust store
201-
202-
Use the following steps to load a certificate:
203-
204-
1. Set up a storage account - for example, `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.Storage/storageAccounts/mystorageaccount`.
205169
206-
1. Download and upload the JCA library. Get the latest version of the JCA library from the Maven repository [azure-security-keyvault-jca](https://mvnrepository.com/artifact/com.azure/azure-security-keyvault-jca) and upload the JAR file to a file share in the storage account - for example, **/jca/lib/azure-security-keyvault-jca.jar**.
207-
208-
1. Use the following steps to modify and upload a Java security configuration:
209-
210-
1. Make a copy of the **java.security** file in your JDK. For Java version 8 or earlier, you can find the **java.security** file at **$JAVA_HOME/jre/lib/security/java.security**. For Java version 11 or later, you can find the **java.security** file at **$JAVA_HOME/conf/security**.
211-
212-
1. Locate `security.provider.<#>=` property in the file and add the following line:
213-
214-
```text
215-
security.provider.<#>=com.azure.security.keyvault.jca.KeyVaultJcaProvider
216-
```
217-
218-
In this line, the number sign placeholder `<#>` represents one increment above the last number in the list - for example, `security.provider.14`.
219-
220-
1. Upload the modified **java.security** file to a file share in the storage account - for example, **/jca/security/java.security**.
221-
222-
1. Upload the certificates that need to be loaded into the trust store to the file share in the storage account - for example, **/jca/truststore/**.
223-
224-
1. Add the volume mount. To add a volume mount for the JCA library and certificates in the container app, see [Tutorial: Create an Azure Files volume mount in Azure Container Apps](../../container-apps/storage-mounts-azure-files.md). You can mount it, for example, as **/mnt/jca/**.
225-
226-
1. Update your image with JCA-related parameters. Modify your Dockerfile as shown in the following example:
227-
228-
```dockerfile
229-
# filename: JAR.dockerfile
230-
231-
FROM mcr.microsoft.com/openjdk/jdk:17-mariner
232-
233-
ARG JAR_FILENAME
170+
// For WebClient
171+
@Bean
172+
WebClient webClientWithTLS(WebClientSsl ssl) {
173+
return WebClient.builder().apply(ssl.fromBundle("tlsClientBundle")).build();
174+
}
175+
```
234176

235-
COPY $JAR_FILENAME /opt/app/app.jar
236-
ENTRYPOINT ["java", "-Dsecurity.overridePropertiesFile=true", "-Djava.security.properties=/mnt/jca/security/java.security", \
237-
"--module-path", "/mnt/jca/lib", "--add-modules=com.azure.security.keyvault.jca", "-Djavax.net.ssl.trustStoreType=AzureKeyVault", \
238-
"-Dazure.cert-path.custom=/mnt/jca/truststore/", "-jar", "/opt/app/app.jar"]
239-
```
177+
### Enable mTLS communication
178+
179+
Set up mTLS for two-way authentication between client and server.
180+
181+
1. Generate or import both client and server certificates to Azure Key Vault. For more information, see [Create and import certificates in Azure Key Vault](/azure/key-vault/certificates/certificate-scenarios#creating-and-importing-certificates).
182+
1. Enable managed identity for your container app. To enable managed identity in your container app, see [Managed identities in Azure Container Apps](../../container-apps/managed-identity.md).
183+
1. Grant `Key Vault Certificate User` role to the managed identity for both Key Vaults. For more information, see [Best Practices for individual keys, secrets, and certificates role assignments](/azure/key-vault/general/rbac-guide#best-practices-for-individual-keys-secrets-and-certificates-role-assignments).
184+
1. Configure `application.yml` for mTLS:
185+
186+
```yml
187+
spring:
188+
ssl:
189+
bundle:
190+
keyvault:
191+
mtlsClientBundle:
192+
key:
193+
alias: client
194+
for-client-auth: true
195+
keystore:
196+
keyvault-ref: keyvault2
197+
truststore:
198+
keyvault-ref: keyvault1
199+
cloud:
200+
azure:
201+
keyvault:
202+
jca:
203+
vaults:
204+
keyvault1:
205+
endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
206+
profile:
207+
tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID} # Required for user-assigned managed identity
208+
credential:
209+
client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID} # Required for user-assigned managed identity
210+
managed-identity-enabled: true
211+
keyvault2:
212+
endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_02}
213+
profile:
214+
tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID} # Required for user-assigned managed identity
215+
credential:
216+
client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID} # Required for user-assigned managed identity
217+
managed-identity-enabled: true
218+
```
240219

241-
1. Rebuild the image with the following command and then upload it to the container registry:
220+
1. Update your `RestTemplate` or `WebClient` bean configuration to apply the Key Vault SSL bundle:
242221

243-
```azurecli
244-
docker build -t <image-name>:<image-tag> \
245-
-f JAR.dockerfile \
246-
--build-arg JAR_FILENAME=<path-to-jar> \
247-
.
248-
```
249-
250-
1. Create or update your container app. For more information, see [Quickstart: Deploy your first container app using the Azure portal](../../container-apps/quickstart-portal.md).
222+
```java
223+
// For RestTemplate
224+
@Bean
225+
RestTemplate restTemplateWithMTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
226+
return restTemplateBuilder.sslBundle(sslBundles.getBundle("mtlsClientBundle")).build();
227+
}
251228
252-
For more information on using the JCA Provider for Azure Key Vault in your Java application, see [JCA Provider Example](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/keyvault/azure-security-keyvault-jca#examples).
229+
// For WebClient
230+
@Bean
231+
WebClient webClientWithMTLS(WebClientSsl ssl) {
232+
return WebClient.builder().apply(ssl.fromBundle("mtlsClientBundle")).build();
233+
}
234+
```
253235

254-
This method maintains consistency with the behavior of Azure Spring Apps. You can also use other ways to load certificates into the trust store.
236+
For more information on using the `spring-cloud-azure-starter-keyvault-jca` in your Spring Boot application, see [Introducing Spring Cloud Azure Starter Key Vault JCA: Streamlined TLS and mTLS for Spring Boot](https://devblogs.microsoft.com/azure-sdk/introducing-spring-cloud-azure-starter-key-vault-jca-streamlined-tls-and-mtls-for-spring-boot/).
255237

256238
By following these steps, you can successfully migrate your custom domain with TLS/SSL from Azure Spring Apps to Azure Container Apps, maintaining secure and efficient communication across all traffic types.

0 commit comments

Comments
 (0)