I'm deploying a Spring Boot application to an Azure Service Fabric cluster (running locally). My goal is to pass Azure Key Vault access credentials (Tenant ID, Client ID, Client Secret, Key Vault URI) as application parameters during deployment, and have my Spring Boot application pick them up as environment variables.
However, despite defining the parameters in my ApplicationManifest.xml and referencing them in ServiceManifest.xml's EnvironmentVariables section, the Spring Boot application starts and logs the placeholder strings (e.g., [AZURE_CLIENT_SECRET]) instead of the actual values, leading to a java.lang.ExceptionInInitializerError: null during startup (likely due to failed Key Vault initialization).
Here is my ApplicationManifest.xml,
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="ebxml-demoType" ApplicationTypeVersion="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Parameters>
<Parameter Name="DataEnciphermentCertThumbprint" DefaultValue="" />
<Parameter Name="AzureTenantId" DefaultValue="" />
<Parameter Name="AzureClientId" DefaultValue="" />
<Parameter Name="AzureClientSecret" DefaultValue=""/>
<Parameter Name="AzureKeyVaultUri" DefaultValue="" />
<Parameter Name="ServerPort" DefaultValue="" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="ebxml-servicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="EnvironmentVariablesSection">
<Parameter Name="AZURE_TENANT_ID" Value="[AzureTenantId]" />
<Parameter Name="AZURE_CLIENT_ID" Value="[AzureClientId]" />
<Parameter Name="AZURE_CLIENT_SECRET" Value="[AzureClientSecret]" />
<Parameter Name="AZURE_KEYVAULT_ENDPOINT" Value="[AzureKeyVaultUri]" />
<Parameter Name="SERVER_PORT" Value="[ServerPort]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
</ServiceManifestImport>
<DefaultServices>
<Service Name="ebxml-service">
<StatelessService ServiceTypeName="ebxml-serviceType" InstanceCount="1">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
Here is the ServiceManifest.xml,
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="ebxml-servicePkg" Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<ServiceTypes>
<StatelessServiceType ServiceTypeName="ebxml-serviceType" UseImplicitHost="true">
</StatelessServiceType>
</ServiceTypes>
<CodePackage Name="code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>jre/bin/java</Program>
<Arguments>-jar service-fab-deployment-0.0.1-SNAPSHOT.jar</Arguments>
<WorkingFolder>CodePackage</WorkingFolder>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048" />
</ExeHost>
</EntryPoint>
<EnvironmentVariables>
<EnvironmentVariable Name="AZURE_TENANT_ID" Value="[AZURE_TENANT_ID]" />
<EnvironmentVariable Name="AZURE_CLIENT_ID" Value="[AZURE_CLIENT_ID]" />
<EnvironmentVariable Name="AZURE_CLIENT_SECRET" Value="[AZURE_CLIENT_SECRET]" />
<EnvironmentVariable Name="AZURE_KEYVAULT_ENDPOINT" Value="[AZURE_KEYVAULT_ENDPOINT]" />
<EnvironmentVariable Name="SERVER_PORT" Value="[SERVER_PORT]" />
</EnvironmentVariables>
</CodePackage>
<ConfigPackage Name="Config" Version="1.0.0" />
</ServiceManifest>
The Settings.xml looks like,
<?xml version="1.0" encoding="utf-8"?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Section Name="EnvironmentVariablesSection">
<Parameter Name="AZURE_TENANT_ID" Value="" />
<Parameter Name="AZURE_CLIENT_ID" Value="" />
<Parameter Name="AZURE_CLIENT_SECRET" Value="" />
<Parameter Name="AZURE_KEYVAULT_ENDPOINT" Value="" />
<Parameter Name="SERVER_PORT" Value="" />
</Section>
</Settings>
I'm starting the app using this command,
New-ServiceFabricApplication -ApplicationName "fabric:/ebxml-demo" -ApplicationTypeName "ebxml-demoType" -ApplicationTypeVersion "1.0.0" `
-ApplicationParameter @{
"AzureTenantId" = "xxx";
"AzureClientId" = "xxx";
"AzureClientSecret" = "xxx";
"AzureKeyVaultUri" = "https://xxx.vault.azure.net/";
"ServerPort" = "8080";
}
In application.properties i have these, which are pass through with the command,
server.port=${SERVER_PORT}
spring.cloud.azure.keyvault.secret.property-sources[0].endpoint=${AZURE_KEYVAULT_ENDPOINT}
spring.cloud.azure.credential.client-id=${AZURE_CLIENT_ID}
spring.cloud.azure.credential.client-secret=${AZURE_CLIENT_SECRET}
spring.cloud.azure.profile.tenant-id=${AZURE_TENANT_ID}
And also these,
spring.datasource.url=${DatabaseURL}
spring.datasource.username=${DBUsername}
spring.datasource.password=${DBPassword}
Defined in Azure Key Vault in azure cloud,
The spring boot app working when i pass secret as shown bellow in the ServiceManifest
EnvironmentVariables> with this working
<EnvironmentVariable Name="AZURE_TENANT_ID" Value="a643a9bc-5060-4ef7-aee5-1590c466b2f3" />
<EnvironmentVariable Name="AZURE_CLIENT_ID" Value="14713b12-de9e-4ede-8734-d29087674498" />
<EnvironmentVariable Name="AZURE_CLIENT_SECRET" Value="kaf8Q~uisnf_HpQkHJyreySZYCcZgZ53POt7AcKF" />
<EnvironmentVariable Name="AZURE_KEYVAULT_ENDPOINT" Value="https://ebxml-sf-kv.vault.azure.net/" />
<EnvironmentVariable Name="SERVER_PORT" Value="8080" />
</EnvironmentVariables>
Could you please guide me through this pointing what is I'm doing wring here ?
I'm away from my work PC, so I believe this is correct, but you must set the default values in the Application Manifest and/or pass them in via the ApplicationParameters or StatupServiceParameters.
You need to add the Environment Variables into the application Manifest with the ServiceManifestImport in order to tell it where to get the values from,.
You seem to want to have them dynamically input via the application parameters, so that is what I've proposed as a fix.
You are not trying this, but I could see you trying it, so fair warning: you cannot pass environmental variables or application parameters in the <Arguments> element; they will not be evaluated, and it's really dumb.
FIXED Service Manifest
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="ebxml-servicePkg" Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<ServiceTypes>
<StatelessServiceType ServiceTypeName="ebxml-serviceType" UseImplicitHost="true">
</StatelessServiceType>
</ServiceTypes>
<CodePackage Name="code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>jre/bin/java</Program>
<Arguments>-jar service-fab-deployment-0.0.1-SNAPSHOT.jar</Arguments>
<WorkingFolder>CodePackage</WorkingFolder>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048" />
</ExeHost>
</EntryPoint>
<EnvironmentVariables>
<EnvironmentVariable Name="AZURE_TENANT_ID" Value="" />
<EnvironmentVariable Name="AZURE_CLIENT_ID" Value="" />
<EnvironmentVariable Name="AZURE_CLIENT_SECRET" Value="" />
<EnvironmentVariable Name="AZURE_KEYVAULT_ENDPOINT" Value="" />
<EnvironmentVariable Name="SERVER_PORT" Value="" />
</EnvironmentVariables>
</CodePackage>
<ConfigPackage Name="Config" Version="1.0.0" />
</ServiceManifest>
FIXED Application Manifest
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="ebxml-demoType" ApplicationTypeVersion="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Parameters>
<Parameter Name="DataEnciphermentCertThumbprint" DefaultValue="" />
<Parameter Name="AzureTenantId" DefaultValue="" />
<Parameter Name="AzureClientId" DefaultValue="" />
<Parameter Name="AzureClientSecret" DefaultValue=""/>
<Parameter Name="AzureKeyVaultUri" DefaultValue="" />
<Parameter Name="ServerPort" DefaultValue="" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="ebxml-servicePkg" ServiceManifestVersion="1.0.0" />
<EnvironmentOverrides CodePackageRef="Code">
<EnvironmentVariable Name="AZURE_TENANT_ID" Value="[AZURE_TENANT_ID]" />
<EnvironmentVariable Name="AZURE_CLIENT_ID" Value="[AZURE_CLIENT_ID]" />
<EnvironmentVariable Name="AZURE_CLIENT_SECRET" Value="[AZURE_CLIENT_SECRET]" />
<EnvironmentVariable Name="AZURE_KEYVAULT_ENDPOINT" Value="[AZURE_KEYVAULT_ENDPOINT]" />
<EnvironmentVariable Name="SERVER_PORT" Value="[ServerPort]" />
</EnvironmentOverrides>
<ConfigOverrides>
<ConfigOverride Name="Config">
<!-- Dont need this unless you are using the ServiceFabric SDK from within your app to access the configuration. -->
</ConfigOverride>
</ConfigOverrides>
</ServiceManifestImport>
<DefaultServices>
<Service Name="ebxml-service">
<StatelessService ServiceTypeName="ebxml-serviceType" InstanceCount="1">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>