Quickstart: Load application secrets using Key Vault

Note

The Basic, Standard, and Enterprise plans will be deprecated starting from mid-March, 2025, with a 3 year retirement period. We recommend transitioning to Azure Container Apps. For more information, see the Azure Spring Apps retirement announcement.

The Standard consumption and dedicated plan will be deprecated starting September 30, 2024, with a complete shutdown after six months. We recommend transitioning to Azure Container Apps. For more information, see Migrate Azure Spring Apps Standard consumption and dedicated plan to Azure Container Apps.

This article applies to: ❎ Basic/Standard ✅ Enterprise

This quickstart shows you how to securely load secrets using Azure Key Vault for apps running the Azure Spring Apps Enterprise plan.

Every application has properties that connect it to its environment and supporting services. These services include resources like databases, logging and monitoring tools, messaging platforms, and so on. Each resource requires a way to locate and access it, often in the form of URLs and credentials. This information is often protected by law, and must be kept secret in order to protect customer data. In Azure Spring Apps, you can configure applications to directly load these secrets into memory from Key Vault by using managed identities and Azure role-based access control.

Prerequisites

Provision Key Vault and store secrets

The following instructions describe how to create a Key Vault and securely save application secrets.

  1. Create variables to hold the resource names by using the following commands. Be sure to replace the placeholders with your own values.

    Note

    Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.

    export RESOURCE_GROUP=<resource-group-name>
    export KEY_VAULT_NAME=<key-vault-name>
    export POSTGRES_SERVER_NAME=<postgres-server-name>
    export POSTGRES_USERNAME=<postgres-username>
    export POSTGRES_PASSWORD=<postgres-password>
    export REDIS_CACHE_NAME=<redis-cache-name>
    export AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME=<Azure-Spring-Apps-service-instance-name>
    
  2. Use the following command to create a Key Vault to store application secrets:

    az keyvault create \
        --resource-group ${RESOURCE_GROUP} \
        --name ${KEY_VAULT_NAME}
    
  3. Use the following command to store the full database server name in Key Vault:

    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "POSTGRES-SERVER-NAME" \
        --value "${POSTGRES_SERVER_NAME}.postgres.database.azure.com"
    
  4. Use the following command to store the database name in Key Vault for the Catalog Service application:

    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "CATALOG-DATABASE-NAME" \
        --value "acmefit_catalog"
    
  5. Use the following commands to store the database login credentials in Key Vault:

    Note

    Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.

    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "POSTGRES-LOGIN-NAME" \
        --value "${POSTGRES_USERNAME}"
    
    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "POSTGRES-LOGIN-PASSWORD" \
        --value "${POSTGRES_PASSWORD}"
    
  6. Use the following command to store the database connection string in Key Vault for the Order Service application:

    Note

    Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.

    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "ConnectionStrings--OrderContext" \
        --value "Server=${POSTGRES_SERVER_NAME};Database=acmefit_order;Port=5432;Ssl Mode=Require;User Id=${POSTGRES_USERNAME};Password=${POSTGRES_PASSWORD};"
    
  7. Use the following commands to retrieve Redis connection properties and store them in Key Vault:

    Note

    Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.

    export REDIS_HOST=$(az redis show \
        --resource-group ${RESOURCE_GROUP} \
        --name ${REDIS_CACHE_NAME} | jq -r '.hostName')
    
    export REDIS_PORT=$(az redis show \
        --resource-group ${RESOURCE_GROUP} \
        --name ${REDIS_CACHE_NAME} | jq -r '.sslPort')
    
    export REDIS_PRIMARY_KEY=$(az redis list-keys \
        --resource-group ${RESOURCE_GROUP} \
        --name ${REDIS_CACHE_NAME} | jq -r '.primaryKey')
    
    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "CART-REDIS-CONNECTION-STRING" \
        --value "rediss://:${REDIS_PRIMARY_KEY}@${REDIS_HOST}:${REDIS_PORT}/0"
    
  8. If you've configured single sign-on, use the following command to store the JSON Web Key (JWK) URI in Key Vault:

    az keyvault secret set \
        --vault-name ${KEY_VAULT_NAME} \
        --name "SSO-PROVIDER-JWK-URI" \
        --value <jwk-uri>
    

Grant applications access to secrets in Key Vault

The following instructions describe how to grant access to Key Vault secrets to applications deployed to the Azure Spring Apps Enterprise plan.

  1. Use the following command to enable a System Assigned Identity for the Cart Service application:

    az spring app identity assign \
        --resource-group ${RESOURCE_GROUP} \
        --name cart-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME}
    
  2. Use the following commands to set an access policy of get list on Key Vault for the Cart Service application:

    export CART_SERVICE_APP_IDENTITY=$(az spring app show \
        --resource-group ${RESOURCE_GROUP} \
        --name cart-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} | jq -r '.identity.principalId')
    
    az keyvault set-policy \
        --name ${KEY_VAULT_NAME} \
        --object-id ${CART_SERVICE_APP_IDENTITY} \
        --resource-group ${RESOURCE_GROUP} \
        --secret-permissions get list
    
  3. Use the following command to enable a System Assigned Identity for the Order Service application:

    az spring app identity assign \
        --resource-group ${RESOURCE_GROUP} \
        --name order-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME}
    
  4. Use the following commands to set an access policy of get list on Key Vault for the Order Service application:

    export ORDER_SERVICE_APP_IDENTITY=$(az spring app show \
        --resource-group ${RESOURCE_GROUP} \
        --name order-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} | jq -r '.identity.principalId')
    
    az keyvault set-policy \
        --name ${KEY_VAULT_NAME} \
        --object-id ${ORDER_SERVICE_APP_IDENTITY} \
        --resource-group ${RESOURCE_GROUP} \
        --secret-permissions get list
    
  5. Use the following command to enable a System Assigned Identity for the Catalog Service application:

    az spring app identity assign \
        --resource-group ${RESOURCE_GROUP} \
        --name catalog-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME}
    
  6. Use the following commands to set an access policy of get list on Key Vault for the Catalog Service application:

    export CATALOG_SERVICE_APP_IDENTITY=$(az spring app show \
        --resource-group ${RESOURCE_GROUP} \
        --name catalog-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} | jq -r '.identity.principalId')
    
    az keyvault set-policy \
        --name ${KEY_VAULT_NAME} \
        --object-id ${CATALOG_SERVICE_APP_IDENTITY} \
        --resource-group ${RESOURCE_GROUP} \
        --secret-permissions get list
    
  7. If you've configured single sign-on, use the following command to enable a System Assigned Identity for the Identity Service application:

    az spring app identity assign \
        --resource-group ${RESOURCE_GROUP} \
        --name identity-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME}
    
  8. If you've configured single sign-on, use the following commands to set an access policy of get list on Key Vault for the Identity Service application:

    export IDENTITY_SERVICE_APP_IDENTITY=$(az spring app show \
        --resource-group ${RESOURCE_GROUP} \
        --name identity-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} | jq -r '.identity.principalId')
    
    az keyvault set-policy \
        --name ${KEY_VAULT_NAME} \
        --object-id ${IDENTITY_SERVICE_APP_IDENTITY} \
        --resource-group ${RESOURCE_GROUP} \
        --secret-permissions get list
    

Update applications to load Key Vault secrets

After granting access to read secrets from Key Vault, use the following steps to update the applications to use the new secret values in their configurations.

  1. Use the following command to retrieve the URI for Key Vault to be used in updating applications:

    export KEYVAULT_URI=$(az keyvault show --name ${KEY_VAULT_NAME} --resource-group ${RESOURCE_GROUP} | jq -r '.properties.vaultUri')
    
  2. Use the following command to retrieve the URL for Spring Cloud Gateway to be used in updating applications:

    export GATEWAY_URL=$(az spring gateway show \
        --resource-group ${RESOURCE_GROUP} \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} | jq -r '.properties.url')
    
  3. Use the following command to remove the Service Connector binding the Order Service application and the Azure Database for PostgreSQL Flexible Server:

    az spring connection delete \
        --resource-group ${RESOURCE_GROUP} \
        --app order-service \
        --connection order_service_db \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --deployment default \
        --yes
    
  4. Use the following command to update the Order Service environment with the URI to access Key Vault:

    Note

    Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.

    az spring app update \
        --resource-group ${RESOURCE_GROUP} \
        --name order-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --env "ConnectionStrings__KeyVaultUri=${KEYVAULT_URI}" "AcmeServiceSettings__AuthUrl=https://${GATEWAY_URL}" "DatabaseProvider=Postgres"
    
  5. Use the following command to remove the Service Connector binding the Catalog Service application and the Azure Database for PostgreSQL Flexible Server:

    az spring connection delete \
        --resource-group ${RESOURCE_GROUP} \
        --app catalog-service \
        --connection catalog_service_db \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --deployment default \
        --yes
    
  6. Use the following command to update the Catalog Service environment and configuration pattern to access Key Vault:

    az spring app update \
        --resource-group ${RESOURCE_GROUP} \
        --name catalog-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --config-file-pattern catalog/default,catalog/key-vault \
        --env "SPRING_CLOUD_AZURE_KEYVAULT_SECRET_PROPERTY_SOURCES_0_ENDPOINT=${KEYVAULT_URI}" "SPRING_CLOUD_AZURE_KEYVAULT_SECRET_PROPERTY_SOURCES_0_NAME='acme-fitness-store-vault'" "SPRING_PROFILES_ACTIVE=default,key-vault"
    
  7. Use the following command to remove the Service Connector binding the Cart Service application and the Azure Cache for Redis:

    az spring connection delete \
        --resource-group ${RESOURCE_GROUP} \
        --app cart-service \
        --connection cart_service_cache \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --deployment default \
        --yes
    
  8. Use the following command to update the Cart Service environment to access Key Vault:

    az spring app update \
        --resource-group ${RESOURCE_GROUP} \
        --name cart-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --env "CART_PORT=8080" "KEYVAULT_URI=${KEYVAULT_URI}" "AUTH_URL=https://${GATEWAY_URL}"
    
  9. If you've configured single sign-on, use the following command to update the Identity Service environment and configuration pattern to access Key Vault:

    az spring app update \
        --resource-group ${RESOURCE_GROUP} \
        --name identity-service \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} \
        --config-file-pattern identity/default,identity/key-vault \
        --env "SPRING_CLOUD_AZURE_KEYVAULT_SECRET_PROPERTY_SOURCES_0_ENDPOINT=${KEYVAULT_URI}" "SPRING_CLOUD_AZURE_KEYVAULT_SECRET_PROPERTY_SOURCES_0_NAME='acme-fitness-store-vault'" "SPRING_PROFILES_ACTIVE=default,key-vault"
    
  10. Use the following commands to retrieve the URL for Spring Cloud Gateway:

    export GATEWAY_URL=$(az spring gateway show \
        --resource-group ${RESOURCE_GROUP} \
        --service ${AZURE_SPRING_APPS_SERVICE_INSTANCE_NAME} | jq -r '.properties.url')
    
    echo "https://${GATEWAY_URL}"
    

    You can open the output URL in a browser to explore the updated application.

Clean up resources

If you plan to continue working with subsequent quickstarts and tutorials, you might want to leave these resources in place. When no longer needed, delete the resource group, which deletes the resources in the resource group. To delete the resource group by using Azure CLI, use the following commands:

echo "Enter the Resource Group name:" &&
read resourceGroupName &&
az group delete --name $resourceGroupName &&
echo "Press [ENTER] to continue ..."

Next steps

Continue on to any of the following optional quickstarts: