How TokenCredential is supported in Spring Cloud Azure
This doc discusses how TokenCredential is managed within Spring Cloud Azure and expected behaviors for each scenarios
Scenario 1
spring.cloud.azure:
storage-blob:
endpoint:
eventhub:
endpoint:
This is the most common scenario I think.
Expectation:
- There should be One
TokenCredntial bean in Spring Context
- This bean is used by both
BlobClient and EventHubClient
- The bean type should be a
ChainedTokenCredential and has the same elements as DAC
Current Behavior:
- There is One
TokenCredential bean in Spring Context
- This bean is used by both
BlobClient and EventHubClient
- The bean type is
ChainedTokenCredential and has the same elements as DAC.
- There is One
ChainedTokenCredential instance created at the JVM start-up.
Scenario 2
spring.cloud.azure:
credential:
client-id:
client-secret:
storage-blob:
endpoint:
eventhub:
endpoint:
in this case, it should be
Expectation:
- One
ServicePrincipalCredential bean in Spring Context from spring.cloud.azure.credential
- This bean is used by
BlobClient and EventHubClient
Current Behavior:
- There is One
ServicePrincipalCredential bean in Spring Context from spring.cloud.azure.credential
- There are Three
TokenCredenital instances created by Spring Cloud Azure:
- One
ChainedTokenCredential instance created at the JVM start-up.
- Two
ServicePrincipalCredential instances created from spring.cloud.azure.storage-blob.credential and spring.cloud.azure.eventhub.credential.
- The one
ServicePrincipalCredential instance created from spring.cloud.azure.storage-blob.credential is used by BlobClient
- The one
ServicePrincipalCredential instance created from spring.cloud.azure.eventhub.credential is used by EventHubClient
Scenario 3
spring.cloud.azure:
storage-blob:
endpoint:
eventhub:
endpoint:
@Configuration
UserCustommizeConfiguration{
@Bean(name="springCloudAzureDefaultCredential")
TokenCredential tokenCredential() {
}
}
In this case, it should be
Expectation:
- One
TokenCredential bean in Spring Context, which is the user-provided one
- It is used by
BlobClient and EventHubClient
- Spring Cloud Azure should NOT create any
TokenCredential instances nor bean
Current Behavior:
- There is One
TokeCredential bean in Spring Context, the user provided one.
- It is used by both
BlobClient and EventHubClient.
- There is One
ChainedTokenCredential instance created at the JVM start-up.
- Spring Cloud Azure doesn't create any
TokenCredential bean
Scenario 4
spring.cloud.azure:
storage-blob:
endpoint:
credential:
client-id:
client-secret:
eventhub:
endpoint:
@Configuration
UserCustommizeConfiguration{
@Bean(name="springCloudAzureDefaultCredential")
TokenCredential tokenCredential() {
}
}
Unlike scenario 3, the User in this scenario provides a TokenCredential bean and has credential configuration provided in application properties for the Storage Blob service.
Expectation:
- In this case, there will be One
TokenCredential bean
- The one is provided by customer configuration code, which will be used to authenticate
EventHubClient
- In this case, there will be One
TokenCredential instance
- It is created Spring Cloud Azure from
spring.cloud.azure.storage-blob.credential config, which is a ServicePrincipalTokenCredential
Current Behavior:
- There are One
TokenCredential bean
- One is provided by the customer to authenticate
EventHubClient
- There is Two
TokenCredential instances
- One is
ChainedTokenCredential instance created at the JVM start-up.
- Another one is created by Spring Cloud Azure from
spring.cloud.azure.storage-blob.credential config, which is a ServicePrincipalTokenCredential
- This one is used by the
StorageBlobClient
Scenario 5
spring.cloud.azure:
storage-blob:
endpoint:
eventhub:
endpoint:
@Configuration
UserCustommizeConfiguration{
@Bean
TokenCredential tokenCredential() {
}
}
In this case, it should be
Expectation:
Current Behavior:
- There are Two
TokeCredential beans in Spring Context,
- One
TokeCredential bean as scenario#1 created by Spring Cloud Azure. It is used by both BlobClient and EventHubClient.
- Another one is the user-provided bean, which is not used by any Spring Cloud Azure code.
- There is One
ChainedTokenCredential instance created at the JVM start-up.
Scenario 6
spring.cloud.azure:
storage-blob:
endpoint:
credential:
client-id:
client-secret:
eventhub:
endpoint:
Expectation:
- In this case, there will be One
TokenCredential bean
- The one is one is created by Spring Cloud Azure internally, which is a
ChainedTokenCredential as same as scenario 1, that will be used to authenticate EventHubClient
- In this case, there will be One
TokenCredential instance
- It is created Spring Cloud Azure from
spring.cloud.azure.storage-blob.credential config, which is a ServicePrincipalTokenCredential
Current Behavior:
- There is One
TokenCredential bean
- This bean is used by
EventHubClient
- The bean type is
ChainedTokenCredential and has the same elements as DAC.
- There are Two
TokenCredential instances created at the JVM start-up.
- One is
ChainedTokenCredential instance created at the JVM start-up.
- Another one is created by Spring Cloud Azure from
spring.cloud.azure.storage-blob.credential config, which is a ServicePrincipalTokenCredential
- This one is used by the
StorageBlobClient
Scenario 7
spring.cloud.azure:
storage-blob:
endpoint:
credential:
client-id:
client-secret:
eventhub:
endpoint:
keyvault:
secret:
endpoint:
property-source-enabled: true
This scenario consists of:
- 3 azure services are used in the application
- Storage Blob
- Event Hubs
- KeyVault Secrets
- Property source is enabled for the KeyVault Service, which means that the
SecretClient must be ready (authenticated) in Bootstrap stage.
- Storage Blob has its own credential configured
Expectation:
about TokenCredential:
- There is One
TokenCredential bean
- One
ChainedTokenCredential bean, as described in scenario 1, is created at BootstrapContext stage, so it is used by SecretClient in EnvironmentPostProcessor and EventHubClient
- There is One
TokenCredential instance
- One
ServicePrincipalTokenCredential is created by Spring Cloud Azure from spring.cloud.azure.storage-blob.credential properties
- This
ServicePrincipalTokenCredential is used to authenticate StorageBlobClient and created at building Application Context Stage.
Current Behavior:
- There is One
TokenCredential bean
- One
ChainedTokenCredential bean is created at the application context stage, and it is used by EventHubClient.
- There are Two
TokenCredential instances
- One is
ChainedTokenCredential instance created at the JVM start-up
- This one is used by the Key Vault property source
- One
ServicePrincipalTokenCredential is created by Spring Cloud Azure from spring.cloud.azure.storage-blob.credential properties
- This
ServicePrincipalTokenCredential is used to authenticate StorageBlobClient and created at the building Application Context Stage.
Scenario 8
spring.cloud.azure:
storage-blob:
endpoint:
credential:
client-id:
client-secret:
eventhub:
endpoint:
keyvault:
secret:
endpoint:
property-source-enabled: true
InstanceSupplier<TokenCredential> tokenCredentialSupplier = ctx -> new AZDTokenCredential();
SpringApplication application = new SpringApplication(MyApplication.class);
application.addBootstrapper(registry -> registry.register(TokenCredential.class, tokenCredentialSupplier));
Like scenario 7, the only difference is that user is trying to provide its own TokenCredential bean to be used by both SecretClient and EventHubClient.
Expectation:
Since this application has property source feature, it can not use the normal Configuration to define the bean, but has to do it in the bootstrap stage, see more detials at [here](https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/#vault.configdata.customization)
- There is One
TokenCredential bean
- It is provided by user from the code, is used by
SecretClient in EnvironmentPostProcessor and EventHubClient
- There is One
TokenCredential instance
- One
ServicePrincipalTokenCredential is created by Spring Cloud Azure from spring.cloud.azure.storage-blob.credential properties
- This
ServicePrincipalTokenCredential is used to authenticate StorageBlobClient and created at building Application Context Stage.
Current Behavior:
- Won't use the
TokenCredential defined in BootstrapContext
- There is One
TokenCredential bean
- One
ChainedTokenCredential bean is created at the application context stage, and it is used by EventHubClient.
- There are Two
TokenCredential instances
- One is
ChainedTokenCredential instance created at the JVM start-up
- This one is used by the Key Vault property source
- One
ServicePrincipalTokenCredential is created by Spring Cloud Azure from spring.cloud.azure.storage-blob.credential properties
- This
ServicePrincipalTokenCredential is used to authenticate StorageBlobClient and created at the building Application Context Stage.
Scenario 9
spring.cloud.azure:
storage-blob:
credential:
client-id:
eventhub:
endpoint:
If users create a DAC and set the client id:
TokenCredential credential = new DefaultAzureCredentialBuilder().managedIdentityClientId("some-client-id").build();
This credential can be used in the Azure Hosting environment and on local machines.
So this scenario is, what if storage blob wants to use a different DAC as we provide in scenario 1?
Expectation
- There is One
TokenCredential bean
- One
ChainedTokenCredential bean, as described in scenario 1, and it is used by the EventHubClient
- There is One
ChainedTokenCredential instance
- One
ChainedTokenCredential instance, created from spring.cloud.azure.storage-blob.credential
- This one is used by the
StorageBlobClient
Current Behavior
- There is One
TokenCredential bean
- One
ChainedTokenCredential bean, as described in scenario 1, and it is used by the EventHubClient
- There is One
ChainedTokenCredential instance
- No
ChainedTokenCredential instance created from spring.cloud.azure.storage-blob.credential
- One is
ChainedTokenCredential instance created at the JVM start-up
- This one is used by the
StorageBlobClient
How TokenCredential is supported in Spring Cloud Azure
This doc discusses how
TokenCredentialis managed within Spring Cloud Azure and expected behaviors for each scenariosScenario 1
This is the most common scenario I think.
Expectation:
TokenCredntialbean in Spring ContextBlobClientandEventHubClientChainedTokenCredentialand has the same elements asDACCurrent Behavior:
TokenCredentialbean in Spring ContextBlobClientandEventHubClientChainedTokenCredentialand has the same elements asDAC.ChainedTokenCredentialinstance created at the JVM start-up.Scenario 2
in this case, it should be
Expectation:
ServicePrincipalCredentialbean in Spring Context fromspring.cloud.azure.credentialBlobClientandEventHubClientCurrent Behavior:
ServicePrincipalCredentialbean in Spring Context fromspring.cloud.azure.credentialTokenCredenitalinstances created by Spring Cloud Azure:ChainedTokenCredentialinstance created at the JVM start-up.ServicePrincipalCredentialinstances created fromspring.cloud.azure.storage-blob.credentialandspring.cloud.azure.eventhub.credential.ServicePrincipalCredentialinstance created fromspring.cloud.azure.storage-blob.credentialis used byBlobClientServicePrincipalCredentialinstance created fromspring.cloud.azure.eventhub.credentialis used byEventHubClientScenario 3
In this case, it should be
Expectation:
TokenCredentialbean in Spring Context, which is the user-provided oneBlobClientandEventHubClientTokenCredentialinstances nor beanCurrent Behavior:
TokeCredentialbean in Spring Context, the user provided one.BlobClientandEventHubClient.ChainedTokenCredentialinstance created at the JVM start-up.TokenCredentialbeanScenario 4
Unlike scenario 3, the User in this scenario provides a
TokenCredentialbean and has credential configuration provided in application properties for the Storage Blob service.Expectation:
TokenCredentialbeanEventHubClientTokenCredentialinstancespring.cloud.azure.storage-blob.credentialconfig, which is aServicePrincipalTokenCredentialCurrent Behavior:
TokenCredentialbeanEventHubClientTokenCredentialinstancesChainedTokenCredentialinstance created at the JVM start-up.spring.cloud.azure.storage-blob.credentialconfig, which is aServicePrincipalTokenCredentialStorageBlobClientScenario 5
In this case, it should be
Expectation:
Current Behavior:
TokeCredentialbeans in Spring Context,TokeCredentialbean as scenario#1 created by Spring Cloud Azure. It is used by bothBlobClientandEventHubClient.ChainedTokenCredentialinstance created at the JVM start-up.Scenario 6
Expectation:
TokenCredentialbeanChainedTokenCredentialas same as scenario 1, that will be used to authenticateEventHubClientTokenCredentialinstancespring.cloud.azure.storage-blob.credentialconfig, which is aServicePrincipalTokenCredentialCurrent Behavior:
TokenCredentialbeanEventHubClientChainedTokenCredentialand has the same elements asDAC.TokenCredentialinstances created at the JVM start-up.ChainedTokenCredentialinstance created at the JVM start-up.spring.cloud.azure.storage-blob.credentialconfig, which is aServicePrincipalTokenCredentialStorageBlobClientScenario 7
This scenario consists of:
SecretClientmust be ready (authenticated) in Bootstrap stage.Expectation:
about
TokenCredential:TokenCredentialbeanChainedTokenCredentialbean, as described in scenario 1, is created atBootstrapContextstage, so it is used bySecretClientinEnvironmentPostProcessorandEventHubClientTokenCredentialinstanceServicePrincipalTokenCredentialis created by Spring Cloud Azure fromspring.cloud.azure.storage-blob.credentialpropertiesServicePrincipalTokenCredentialis used to authenticateStorageBlobClientand created at building Application Context Stage.Current Behavior:
TokenCredentialbeanChainedTokenCredentialbean is created at theapplication contextstage, and it is used byEventHubClient.TokenCredentialinstancesChainedTokenCredentialinstance created at the JVM start-upServicePrincipalTokenCredentialis created by Spring Cloud Azure fromspring.cloud.azure.storage-blob.credentialpropertiesServicePrincipalTokenCredentialis used to authenticateStorageBlobClientand created at the building Application Context Stage.Scenario 8
Like scenario 7, the only difference is that user is trying to provide its own
TokenCredentialbean to be used by bothSecretClientandEventHubClient.Expectation:
Since this application has property source feature, it can not use the normal
Configurationto define the bean, but has to do it in the bootstrap stage, see more detials at [here](https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/#vault.configdata.customization)TokenCredentialbeanSecretClientinEnvironmentPostProcessorandEventHubClientTokenCredentialinstanceServicePrincipalTokenCredentialis created by Spring Cloud Azure fromspring.cloud.azure.storage-blob.credentialpropertiesServicePrincipalTokenCredentialis used to authenticateStorageBlobClientand created at building Application Context Stage.Current Behavior:
TokenCredentialdefined inBootstrapContextTokenCredentialbeanChainedTokenCredentialbean is created at theapplication contextstage, and it is used byEventHubClient.TokenCredentialinstancesChainedTokenCredentialinstance created at the JVM start-upServicePrincipalTokenCredentialis created by Spring Cloud Azure fromspring.cloud.azure.storage-blob.credentialpropertiesServicePrincipalTokenCredentialis used to authenticateStorageBlobClientand created at the building Application Context Stage.Scenario 9
If users create a
DACand set the client id:This credential can be used in the Azure Hosting environment and on local machines.
So this scenario is, what if storage blob wants to use a different
DACas we provide in scenario 1?Expectation
TokenCredentialbeanChainedTokenCredentialbean, as described in scenario 1, and it is used by theEventHubClientChainedTokenCredentialinstanceChainedTokenCredentialinstance, created fromspring.cloud.azure.storage-blob.credentialStorageBlobClientCurrent Behavior
TokenCredentialbeanChainedTokenCredentialbean, as described in scenario 1, and it is used by theEventHubClientChainedTokenCredentialinstanceChainedTokenCredentialinstance created fromspring.cloud.azure.storage-blob.credentialChainedTokenCredentialinstance created at the JVM start-upStorageBlobClient