Skip to content

Commit 412ad64

Browse files
authored
Merge pull request #301414 from haochenghuang/haochuang/migration-jca
[ASA] Update loading certificates from key vault in custom domain part of migration docs
2 parents f892f57 + 8f08c15 commit 412ad64

File tree

1 file changed

+100
-118
lines changed

1 file changed

+100
-118
lines changed

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

Lines changed: 100 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ If you need to secure your custom domain in Azure Container Apps, you can use a
4646

4747
If you have a private certificate stored locally, you can upload it. For more information, see [Custom domain names and bring your own certificates in Azure Container Apps](../../container-apps/custom-domains-certificates.md).
4848

49-
If your certificate is from Azure Key Vault, see [Import certificates from Azure Key Vault to Azure Container Apps](../../container-apps/key-vault-certificates-manage.md) for more information.
49+
If your certificate is from Azure Key Vault, you can import certificates to Azure Container Apps directly. For more information, see [Import certificates from Azure Key Vault to Azure Container Apps](../../container-apps/key-vault-certificates-manage.md).
5050

5151
If you want to continue using the original certificate and domain name from Azure Spring Apps, you can upload the certificate to container apps or Azure Key Vault. Also, you can update the A record or CNAME in your DNS provider to redirect the original domain name to the container app IP or URL.
5252

@@ -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+
This sample shows how to enable TLS and mTLS for traffic to external services by loading the certificate from Azure Key Vault using the `spring-cloud-azure-starter-keyvault-jca` library. Your Java project must use Spring Boot 3.1+ and include the following dependency in your **pom.xml** file:
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.
123-
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"
122+
```xml
123+
<dependency>
124+
<groupId>com.azure.spring</groupId>
125+
<artifactId>spring-cloud-azure-starter-keyvault-jca</artifactId>
126+
<version>5.23.0</version>
127+
</dependency>
147128
```
148129

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.
130+
### Load a certificate into the truststore from Key Vault with SSL bundle
150131

151-
For an existing container app, you can use following commands to reference a secret from Key Vault and mount it to a volume:
132+
Use the following steps to load a certificate into the truststore from Azure Key Vault using the `spring-cloud-azure-starter-keyvault-jca` library:
152133

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>"
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).
158135

159-
az containerapp update \
160-
--resource-group "my-resource-group" \
161-
--name "my-app" \
162-
--secret-volume-mount "/mnt/cert"
163-
```
164-
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.
170-
171-
```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
195-
}
196-
```
136+
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).
197137

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.
138+
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).
199139

200-
### Load a certificate into the trust store
140+
1. Add the following configuration to your **application.yml** file:
201141

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`.
205-
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
142+
```yml
143+
spring:
144+
ssl:
145+
bundle:
146+
keyvault:
147+
tlsClientBundle:
148+
truststore:
149+
keyvault-ref: keyvault1
150+
cloud:
151+
azure:
152+
keyvault:
153+
jca:
154+
vaults:
155+
keyvault1:
156+
endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
157+
credential:
158+
client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID} # Required for user-assigned managed identity
159+
managed-identity-enabled: true
160+
```
230161

231-
FROM mcr.microsoft.com/openjdk/jdk:17-mariner
162+
1. To apply the Key Vault SSL bundle, update your `RestTemplate` or `WebClient` bean configuration, as shown in the following example:
232163

233-
ARG JAR_FILENAME
164+
```java
165+
// For RestTemplate
166+
@Bean
167+
RestTemplate restTemplateWithTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
168+
return restTemplateBuilder.sslBundle(sslBundles.getBundle("tlsClientBundle")).build();
169+
}
234170
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"]
171+
// For WebClient
172+
@Bean
173+
WebClient webClientWithTLS(WebClientSsl ssl) {
174+
return WebClient.builder().apply(ssl.fromBundle("tlsClientBundle")).build();
175+
}
239176
```
240177

241-
1. Rebuild the image with the following command and then upload it to the container registry:
242-
243-
```azurecli
244-
docker build -t <image-name>:<image-tag> \
245-
-f JAR.dockerfile \
246-
--build-arg JAR_FILENAME=<path-to-jar> \
247-
.
178+
### Enable mTLS communication
179+
180+
Use the following steps to set up mTLS for two-way authentication between client and server:
181+
182+
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).
183+
184+
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).
185+
186+
1. Grant the `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).
187+
188+
1. Add the following configuration to your **application.yml** file for mTLS:
189+
190+
```yml
191+
spring:
192+
ssl:
193+
bundle:
194+
keyvault:
195+
mtlsClientBundle:
196+
key:
197+
alias: client
198+
for-client-auth: true
199+
keystore:
200+
keyvault-ref: keyvault2
201+
truststore:
202+
keyvault-ref: keyvault1
203+
cloud:
204+
azure:
205+
keyvault:
206+
jca:
207+
vaults:
208+
keyvault1:
209+
endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
210+
credential:
211+
client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID} # Required for user-assigned managed identity
212+
managed-identity-enabled: true
213+
keyvault2:
214+
endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_02}
215+
credential:
216+
client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID} # Required for user-assigned managed identity
217+
managed-identity-enabled: true
248218
```
249219

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).
220+
1. To apply the Key Vault SSL bundle, update your `RestTemplate` or `WebClient` bean configuration, as shown in the following example:
251221

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).
222+
```java
223+
// For RestTemplate
224+
@Bean
225+
RestTemplate restTemplateWithMTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
226+
return restTemplateBuilder.sslBundle(sslBundles.getBundle("mtlsClientBundle")).build();
227+
}
228+
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` library 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)