-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bridge azure properties to spring starter to authenticate #5
Changes from 9 commits
94353ba
6ec0e05
0e5ec4c
92f0f85
6fdd070
d45335a
79749ea
548b429
c332fd2
d8e972e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.azure.spring; | ||
|
||
import com.azure.core.credential.TokenCredential; | ||
import com.azure.spring.autoconfigure.unity.CredentialProperties; | ||
import com.azure.spring.autoconfigure.unity.EnvironmentProperties; | ||
import com.azure.spring.identity.CredentialPropertiesProvider; | ||
|
||
/** | ||
* An interface to provide all credential related properties based on the properties subclass. | ||
*/ | ||
public interface MappingCredentialPropertiesProvider extends CredentialPropertiesProvider { | ||
|
||
void mapAzureProperties(CredentialProperties credentialProperties, EnvironmentProperties environment); | ||
|
||
TokenCredential mappingTokenCredential(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.azure.spring; | ||
|
||
import com.azure.core.credential.TokenCredential; | ||
import com.azure.spring.autoconfigure.unity.AzureProperties; | ||
import com.azure.spring.autoconfigure.unity.CredentialProperties; | ||
import com.azure.spring.autoconfigure.unity.EnvironmentProperties; | ||
import com.azure.spring.identity.SpringEnvironmentCredentialBuilder; | ||
|
||
import java.util.Optional; | ||
|
||
/** | ||
* An implementation to provide all credential related properties based on properties subclass. | ||
*/ | ||
public class SpringMappingCredentialPropertiesProvider implements MappingCredentialPropertiesProvider { | ||
|
||
CredentialProperties credentialProperties; | ||
EnvironmentProperties environment; | ||
|
||
public SpringMappingCredentialPropertiesProvider(AzureProperties azureProperties) { | ||
if (azureProperties != null) { | ||
mapAzureProperties(azureProperties.getCredential(), azureProperties.getEnvironment()); | ||
} | ||
} | ||
|
||
@Override | ||
public void mapAzureProperties(CredentialProperties credentialProperties, | ||
EnvironmentProperties environment) { | ||
this.credentialProperties = credentialProperties; | ||
this.environment = environment; | ||
} | ||
|
||
|
||
@Override | ||
public TokenCredential mappingTokenCredential() { | ||
SpringEnvironmentCredentialBuilder mapEnvironmentCredentialBuilder = | ||
new SpringEnvironmentCredentialBuilder().credentialPropertiesProvider(this); | ||
return mapEnvironmentCredentialBuilder.build(); | ||
} | ||
|
||
@Override | ||
public String getTenantId() { | ||
return Optional.ofNullable(credentialProperties).map(CredentialProperties::getTenantId).orElse(null); | ||
} | ||
|
||
@Override | ||
public String getClientId() { | ||
return Optional.ofNullable(credentialProperties).map(CredentialProperties::getClientId).orElse(null); | ||
} | ||
|
||
@Override | ||
public String getClientSecret() { | ||
return Optional.ofNullable(credentialProperties).map(CredentialProperties::getClientSecret).orElse(null); | ||
} | ||
|
||
@Override | ||
public String getClientCertificatePath() { | ||
return Optional.ofNullable(credentialProperties).map(CredentialProperties::getCertificatePath).orElse(null); | ||
} | ||
|
||
@Override | ||
public String getCertificatePassword() { | ||
return Optional.ofNullable(credentialProperties).map(CredentialProperties::getCertificatePassword).orElse(null); | ||
} | ||
|
||
@Override | ||
public String getUsername() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public String getPassword() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public String getAuthorityHost() { | ||
return Optional.ofNullable(environment).map(EnvironmentProperties::getAuthorityHost).orElse(null); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,21 +4,34 @@ | |
package com.azure.spring.autoconfigure.cosmos; | ||
|
||
import com.azure.core.credential.AzureKeyCredential; | ||
import com.azure.core.credential.TokenCredential; | ||
import com.azure.cosmos.ConnectionMode; | ||
import com.azure.cosmos.CosmosAsyncClient; | ||
import com.azure.cosmos.CosmosClientBuilder; | ||
import com.azure.spring.autoconfigure.unity.AzureProperties; | ||
import com.azure.identity.ChainedTokenCredential; | ||
import com.azure.identity.ChainedTokenCredentialBuilder; | ||
import com.azure.spring.SpringMappingCredentialPropertiesProvider; | ||
import com.azure.spring.autoconfigure.unity.identity.AzureDefaultTokenCredentialAutoConfiguration; | ||
import com.azure.spring.data.cosmos.config.AbstractCosmosConfiguration; | ||
import com.azure.spring.data.cosmos.config.CosmosConfig; | ||
import com.azure.spring.data.cosmos.core.CosmosTemplate; | ||
import com.azure.spring.identity.AzureKeyCredentialClientBuilderCustomizer; | ||
import com.azure.spring.identity.TokenCredentialClientBuilderCustomizer; | ||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Qualifier; | ||
import org.springframework.boot.autoconfigure.AutoConfigureAfter; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource; | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.util.StringUtils; | ||
|
||
import static com.azure.spring.autoconfigure.unity.AzureProperties.AZURE_PROPERTY_BEAN_NAME; | ||
import java.util.Optional; | ||
|
||
import static com.azure.spring.autoconfigure.unity.identity.AzureDefaultTokenCredentialAutoConfiguration.DEFAULT_CHAINED_TOKEN_CREDENTIAL_BEAN_NAME; | ||
|
||
/** | ||
* Auto Configure Cosmos properties and connection policy. | ||
|
@@ -27,44 +40,96 @@ | |
@ConditionalOnClass({ CosmosAsyncClient.class, CosmosTemplate.class }) | ||
@ConditionalOnResource(resources = "classpath:cosmos.enable.config") | ||
@EnableConfigurationProperties(CosmosProperties.class) | ||
@AutoConfigureAfter(AzureDefaultTokenCredentialAutoConfiguration.class) | ||
public class CosmosAutoConfiguration extends AbstractCosmosConfiguration { | ||
private final CosmosProperties cosmosProperties; | ||
private final AzureProperties azureProperties; | ||
|
||
private final CosmosProperties properties; | ||
private static final String COSMOS_CHAINED_TOKEN_CREDENTIAL_BEAN_NAME = "cosmosChainedTokenCredential"; | ||
private static final String COSMOS_AZURE_KEY_CREDENTIAL_BEAN_NAME = "cosmosAzureKeyCredential"; | ||
|
||
public CosmosAutoConfiguration(CosmosProperties cosmosProperties, | ||
@Qualifier(AZURE_PROPERTY_BEAN_NAME) AzureProperties azureProperties) { | ||
this.cosmosProperties = cosmosProperties; | ||
this.azureProperties = azureProperties; | ||
public CosmosAutoConfiguration(CosmosProperties properties) { | ||
this.properties = properties; | ||
} | ||
|
||
@Override | ||
protected String getDatabaseName() { | ||
return cosmosProperties.getDatabase(); | ||
return properties.getDatabase(); | ||
} | ||
|
||
@Bean(COSMOS_AZURE_KEY_CREDENTIAL_BEAN_NAME) | ||
@ConditionalOnMissingBean(name = COSMOS_AZURE_KEY_CREDENTIAL_BEAN_NAME) | ||
public AzureKeyCredential cosmosAzureKeyCredential() { | ||
return Optional.ofNullable(properties.getKey()) | ||
.filter(StringUtils::hasText) | ||
.map(AzureKeyCredential::new) | ||
.orElse(null); | ||
} | ||
|
||
@Bean(COSMOS_CHAINED_TOKEN_CREDENTIAL_BEAN_NAME) | ||
@ConditionalOnMissingBean(name = COSMOS_CHAINED_TOKEN_CREDENTIAL_BEAN_NAME) | ||
public ChainedTokenCredential cosmosChainedTokenCredential( | ||
@Qualifier(DEFAULT_CHAINED_TOKEN_CREDENTIAL_BEAN_NAME) TokenCredential defaultTokenCredential) { | ||
SpringMappingCredentialPropertiesProvider provider = new SpringMappingCredentialPropertiesProvider(properties); | ||
final ChainedTokenCredentialBuilder chainedTokenCredentialBuilder = new ChainedTokenCredentialBuilder(); | ||
chainedTokenCredentialBuilder.addLast(provider.mappingTokenCredential()) | ||
.addLast(defaultTokenCredential); | ||
return chainedTokenCredentialBuilder.build(); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
public AzureKeyCredentialClientBuilderCustomizer<CosmosClientBuilder> azureKeyCredentialCustomizer( | ||
@Autowired(required = false) @Qualifier(COSMOS_AZURE_KEY_CREDENTIAL_BEAN_NAME) AzureKeyCredential cosmosAzureKeyCredential) { | ||
if (cosmosAzureKeyCredential != null) { | ||
return builder -> builder.credential(cosmosAzureKeyCredential); | ||
} | ||
return null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should discuss this design, I'm really not sure if it is the right way to do this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. btw, you can use |
||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
public TokenCredentialClientBuilderCustomizer<CosmosClientBuilder> tokenCredentialCustomizer( | ||
@Qualifier(COSMOS_CHAINED_TOKEN_CREDENTIAL_BEAN_NAME) ChainedTokenCredential cosmosChainedTokenCredential) { | ||
return builder -> builder.credential(cosmosChainedTokenCredential); | ||
} | ||
|
||
/** | ||
* Cosmos client builder configurer | ||
* @param azureKeyCredentialCustomizers Customize key credential | ||
* @param tokenCredentialCustomizers Customize token credential. | ||
* @return Cosmos client builder configurer | ||
*/ | ||
@Bean | ||
public AzureKeyCredential azureKeyCredential() { | ||
return new AzureKeyCredential(cosmosProperties.getKey()); | ||
public CosmosClientBuilderConfigurer cosmosClientBuilderConfigurer( | ||
ObjectProvider<AzureKeyCredentialClientBuilderCustomizer<CosmosClientBuilder>> azureKeyCredentialCustomizers, | ||
ObjectProvider<TokenCredentialClientBuilderCustomizer<CosmosClientBuilder>> tokenCredentialCustomizers) { | ||
CosmosClientBuilderConfigurer configurer = new CosmosClientBuilderConfigurer(); | ||
configurer.setAzureKeyCredentialCustomizer(azureKeyCredentialCustomizers.orderedStream().findFirst().orElse(null)); | ||
configurer.setTokenCredentialCustomizer(tokenCredentialCustomizers.orderedStream().findFirst().orElse(null)); | ||
return configurer; | ||
} | ||
|
||
/** | ||
* Create default CosmosClientBuilder | ||
* @param cosmosClientBuilderConfigurer Cosmos client builder configurer bean. | ||
* @return Default CosmosClientBuilder | ||
*/ | ||
@Bean | ||
public CosmosClientBuilder cosmosClientBuilder(AzureKeyCredential azureKeyCredential) { | ||
CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder(); | ||
cosmosClientBuilder.credential(azureKeyCredential) | ||
.consistencyLevel(cosmosProperties.getConsistencyLevel()) | ||
.endpoint(cosmosProperties.getUri()); | ||
if (ConnectionMode.GATEWAY == cosmosProperties.getConnectionMode()) { | ||
cosmosClientBuilder.gatewayMode(); | ||
@ConditionalOnMissingBean | ||
public CosmosClientBuilder cosmosClientBuilderCustomizer(CosmosClientBuilderConfigurer cosmosClientBuilderConfigurer) { | ||
CosmosClientBuilder builder = new CosmosClientBuilder(); | ||
builder.consistencyLevel(properties.getConsistencyLevel()) | ||
.endpoint(properties.getUri()); | ||
if (ConnectionMode.GATEWAY == properties.getConnectionMode()) { | ||
builder.gatewayMode(); | ||
} | ||
return cosmosClientBuilder; | ||
return cosmosClientBuilderConfigurer.configure(builder); | ||
} | ||
|
||
@Override | ||
public CosmosConfig cosmosConfig() { | ||
return CosmosConfig.builder() | ||
.enableQueryMetrics(cosmosProperties.isPopulateQueryMetrics()) | ||
.responseDiagnosticsProcessor(cosmosProperties.getResponseDiagnosticsProcessor()) | ||
.enableQueryMetrics(properties.isPopulateQueryMetrics()) | ||
.responseDiagnosticsProcessor(properties.getResponseDiagnosticsProcessor()) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.azure.spring.autoconfigure.cosmos; | ||
|
||
import com.azure.cosmos.CosmosClientBuilder; | ||
import com.azure.spring.identity.AbstractClientBuilderConfigurer; | ||
import com.azure.spring.identity.AzureKeyCredentialClientBuilderCustomizer; | ||
|
||
/** | ||
* Configurer for extending Azure Cosmos service client builder configuration. | ||
*/ | ||
public class CosmosClientBuilderConfigurer extends AbstractClientBuilderConfigurer<CosmosClientBuilder> { | ||
|
||
private AzureKeyCredentialClientBuilderCustomizer<CosmosClientBuilder> azureKeyCredentialCustomizer; | ||
|
||
public void setAzureKeyCredentialCustomizer(AzureKeyCredentialClientBuilderCustomizer<CosmosClientBuilder> azureKeyCredentialCustomizer) { | ||
this.azureKeyCredentialCustomizer = azureKeyCredentialCustomizer; | ||
} | ||
|
||
@Override | ||
public CosmosClientBuilder configure(CosmosClientBuilder builder) { | ||
super.configure(builder); | ||
if (azureKeyCredentialCustomizer != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about omitting the DefaultSkipCredentialCallback and setting the credential by precedence, first setting the lower precedence and higher precedence. |
||
azureKeyCredentialCustomizer.keyCredential(builder); | ||
} | ||
return builder; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null?