Skip to content

Commit d938bb7

Browse files
committed
Initial
1 parent 62ec7a3 commit d938bb7

5 files changed

Lines changed: 29 additions & 42 deletions

File tree

cloudplatform/connectivity-oauth/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/BtpServicePropertySuppliers.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,9 @@ private void attachClientKeyStore( @Nonnull final OAuth2Options.Builder optionsB
275275
private KeyStore getClientKeyStore()
276276
{
277277
final ClientIdentity clientIdentity = getClientIdentity();
278-
if( clientIdentity instanceof ZtisClientIdentity ) {
279-
return ((ZtisClientIdentity) clientIdentity).getKeyStore();
278+
//TODO: this doesn't work well with a dynamic keystore, check use cases
279+
if( clientIdentity instanceof ZtisClientIdentity ztisClientIdentity ) {
280+
return ztisClientIdentity.getKeyStore();
280281
}
281282
if( !(clientIdentity instanceof ClientCertificate) ) {
282283
return null;

cloudplatform/connectivity-oauth/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultOAuth2PropertySupplier.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,7 @@ private ZtisClientIdentity getZtisIdentity( @Nonnull final String clientid )
173173
}
174174
final ZeroTrustIdentityService ztis = ZeroTrustIdentityService.getInstance();
175175

176-
final KeyStore keyStore;
177-
try {
178-
keyStore = ztis.getOrCreateKeyStore();
179-
}
180-
catch( final Exception e ) {
181-
throw new CloudPlatformException("Failed to load X509 certificate for credential type X509_ATTESTED.", e);
182-
}
183-
return new ZtisClientIdentity(clientid, keyStore);
176+
return new ZtisClientIdentity(clientid, ztis::getOrCreateKeyStore);
184177
}
185178

186179
@Nonnull

cloudplatform/connectivity-oauth/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/OAuth2Service.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ class OAuth2Service
9797
OAuth2TokenService getTokenService( @Nullable final String tenantId )
9898
{
9999
final CacheKey key = CacheKey.fromIds(tenantId, null).append(identity);
100+
// ZTIS certificates rotate at runtime, thus we explicitly add the current KeyStore as cache key
101+
// once the certificate rotates, this produces a cache miss, ensuring we construct a new HTTP client with a new certificate
102+
if (identity instanceof final ZtisClientIdentity ztisIdentity) {
103+
key.append(ztisIdentity.getKeyStore());
104+
}
100105
return tokenServiceCache.get(key, this::createTokenService);
101106
}
102107

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
package com.sap.cloud.sdk.cloudplatform.connectivity;
22

3-
import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationKeyStoreComparator.resolveCertificatesOnly;
4-
import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationKeyStoreComparator.resolveKeyStoreHashCode;
5-
63
import java.security.KeyStore;
4+
import java.util.function.Supplier;
75

86
import javax.annotation.Nonnull;
97

10-
import org.apache.commons.lang3.builder.EqualsBuilder;
11-
import org.apache.commons.lang3.builder.HashCodeBuilder;
8+
import com.sap.cloud.sdk.cloudplatform.exception.CloudPlatformException;
9+
import lombok.EqualsAndHashCode;
1210

1311
import com.sap.cloud.security.config.ClientIdentity;
1412

15-
import lombok.AllArgsConstructor;
16-
import lombok.Getter;
13+
import lombok.ToString;
14+
import lombok.Value;
1715

1816
final class SecurityLibWorkarounds
1917
{
@@ -22,44 +20,34 @@ private SecurityLibWorkarounds()
2220
throw new IllegalStateException("This utility class should never be instantiated.");
2321
}
2422

25-
@Getter
26-
@AllArgsConstructor
23+
@Value
2724
static class ZtisClientIdentity implements ClientIdentity
2825
{
2926
@Nonnull
30-
private final String id;
27+
String id;
28+
29+
// Exclude certificates from equals & hash code since they rotate dynamically at runtime
30+
// Instead, the OAuth2Service cache explicitly checks for outdated KeyStores
3131
@Nonnull
32-
private final KeyStore keyStore;
32+
@EqualsAndHashCode.Exclude
33+
@ToString.Exclude
34+
Supplier<KeyStore> keyStoreSource;
3335

3436
@Override
3537
public boolean isCertificateBased()
3638
{
3739
return true;
3840
}
3941

40-
// The identity will be used as cache key, so it's important we correctly implement equals/hashCode
41-
@Override
42-
public boolean equals( final Object obj )
42+
@Nonnull
43+
KeyStore getKeyStore()
4344
{
44-
if( this == obj ) {
45-
return true;
45+
try {
46+
return keyStoreSource.get();
4647
}
47-
48-
if( obj == null || getClass() != obj.getClass() ) {
49-
return false;
48+
catch( final Exception e ) {
49+
throw new CloudPlatformException("Failed to load X509 certificate for credential type X509_ATTESTED.", e);
5050
}
51-
52-
final ZtisClientIdentity that = (ZtisClientIdentity) obj;
53-
return new EqualsBuilder()
54-
.append(id, that.id)
55-
.append(resolveCertificatesOnly(keyStore), resolveCertificatesOnly(that.keyStore))
56-
.isEquals();
57-
}
58-
59-
@Override
60-
public int hashCode()
61-
{
62-
return new HashCodeBuilder(41, 71).append(id).append(resolveKeyStoreHashCode(keyStore)).build();
6351
}
6452
}
6553
}

release_notes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
### 📈 Improvements
1919

20-
-
20+
- Improved the support for the credential type `X509_ATTESTED`. `HttpDestination` objects created via `ServiceBindingDestinationLoader` no longer need to be re-created for the rotation of certificates to take effect.
2121

2222
### 🐛 Fixed Issues
2323

0 commit comments

Comments
 (0)