Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
220 changes: 220 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@ For details on compatibility, advanced configurations, and add-ons, see [Configu
```
System.setProperty("oci.javasdk.token.refresh.enabled", "false");
```
- *ConnectionPoolingApacheConfigurator*: Some clients now have `ConnectionPoolingApacheConfigurator` set as their default configurator (called out in the CHANGELOG.md file). Unless a different `ClientConfigurator` is passed when creating the client, this default configurator is used for all client instances using the `ConnectionPoolingApacheConfigurator`. For clients that now use `ConnectionPoolingApacheConfigurator`, this is enabled by default, which is a breaking change. It can be disabled using system properties exposed in `Options.java`.
- To disable it for all supported clients, set the global system property:
```
System.setProperty("oci.javasdk.ConnectionPoolingApacheConfigurator.enabled.global", "false");
```
or pass it to the Java runtime:
```
-Doci.javasdk.ConnectionPoolingApacheConfigurator.enabled.global=false
```
- To disable it for a specific client class, set the per-class system property using the fully qualified client class name:
```
System.setProperty("oci.javasdk.ConnectionPoolingApacheConfigurator.enabled.com.oracle.bmc.vault.VaultsClient", "false");
```
or pass it to the Java runtime:
```
-Doci.javasdk.ConnectionPoolingApacheConfigurator.enabled.com.oracle.bmc.vault.VaultsClient=false
```
- Sync and async clients use separate per-class properties, so if you want to disable both you must set both class-specific properties:
```
System.setProperty("oci.javasdk.ConnectionPoolingApacheConfigurator.enabled.com.oracle.bmc.vault.VaultsClient", "false");
System.setProperty("oci.javasdk.ConnectionPoolingApacheConfigurator.enabled.com.oracle.bmc.vault.VaultsAsyncClient", "false");
```
or pass them to the Java runtime:
```
-Doci.javasdk.ConnectionPoolingApacheConfigurator.enabled.com.oracle.bmc.vault.VaultsClient=false -Doci.javasdk.ConnectionPoolingApacheConfigurator.enabled.com.oracle.bmc.vault.VaultsAsyncClient=false
```
- The global property applies to all supported clients. The per-class property applies only to the named client class. Both properties default to `"true"`, and the configurator is used only when both the global property and that client class property are enabled.

## Examples

Expand Down
4 changes: 2 additions & 2 deletions bmc-accessgovernancecp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>oci-java-sdk-accessgovernancecp</artifactId>
Expand All @@ -16,7 +16,7 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
</dependency>
</dependencies>
</project>
4 changes: 2 additions & 2 deletions bmc-addons/bmc-apache-connector-provider/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-addons</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand All @@ -18,7 +18,7 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
</dependency>
</dependencies>
</project>
10 changes: 5 additions & 5 deletions bmc-addons/bmc-graalvm-addon/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>oci-java-sdk-addons</artifactId>
<groupId>com.oracle.oci.sdk</groupId>
<version>2.91.0</version>
<version>2.93.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>oci-java-sdk-addons-graalvm</artifactId>
Expand Down Expand Up @@ -127,24 +127,24 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-objectstorage-extensions</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-identity</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-core</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@
"com.oracle.bmc.containerinstances.SdkClientsMetadata",
"com.oracle.bmc.containerregistry.SdkClientsMetadata",
"com.oracle.bmc.core.SdkClientsMetadata",
"com.oracle.bmc.costad.SdkClientsMetadata",
"com.oracle.bmc.dashboardservice.SdkClientsMetadata",
"com.oracle.bmc.database.SdkClientsMetadata",
"com.oracle.bmc.databasemanagement.SdkClientsMetadata",
"com.oracle.bmc.databasemigration.SdkClientsMetadata",
"com.oracle.bmc.databasetools.SdkClientsMetadata",
"com.oracle.bmc.databasetoolsruntime.SdkClientsMetadata",
"com.oracle.bmc.datacatalog.SdkClientsMetadata",
"com.oracle.bmc.dataflow.SdkClientsMetadata",
"com.oracle.bmc.dataintegration.SdkClientsMetadata",
Expand Down
4 changes: 2 additions & 2 deletions bmc-addons/bmc-oke-workload-identity/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>oci-java-sdk-addons</artifactId>
<groupId>com.oracle.oci.sdk</groupId>
<version>2.91.0</version>
<version>2.93.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down Expand Up @@ -38,7 +38,7 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ public static class OkeWorkloadIdentityAuthenticationDetailsProviderBuilder
private ServiceAccountTokenSupplier serviceAccountTokenSupplier;

/** Flag to enable new Service Account level token caching */
private boolean isTokenCachingEnabled = false;
private boolean isTokenCachingEnabled = true;

/** Flag to check if default session key supplier is used */
private boolean isUsingDefaultSessionKeySupplier = false;

public OkeWorkloadIdentityAuthenticationDetailsProviderBuilder() {
this.serviceAccountTokenSupplier = new DefaultServiceAccountTokenProvider();
Expand Down Expand Up @@ -220,6 +223,10 @@ public OkeWorkloadIdentityAuthenticationDetailsProviderBuilder isTokenCachingEna
public OkeWorkloadIdentityAuthenticationDetailsProvider build() {
// autodetect region
autoDetectEndpointUsingMetadataUrl();

// If a sessionKeySupplier is not provided by the customer, the default supplier is used
this.isUsingDefaultSessionKeySupplier = this.sessionKeySupplier == null;

// if customer has enabled new SA level token caching then use custom implementation of
// SessionKeySupplier else it will fall back to non-caching SDK behaviour.
if (this.isTokenCachingEnabled) {
Expand Down Expand Up @@ -308,7 +315,8 @@ protected FederationClient createFederationClient(SessionKeySupplier sessionKeyS
serviceAccountTokenSupplier,
provider,
configurator,
circuitBreakerConfig);
circuitBreakerConfig,
isUsingDefaultSessionKeySupplier);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.time.Duration;
import com.oracle.bmc.util.internal.StringUtils;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -54,13 +55,24 @@ public class OkeWorkloadIdentityResourcePrincipalsFederationClient
private static final String JWT_FORMAT = "Bearer %s";
private final String KUBERNETES_SERVICE_HOST = "KUBERNETES_SERVICE_HOST";
private final int PROXYMUX_SERVER_PORT = 12250;
private static final long MAX_RETRY_DELAY_SECONDS = 900; // 15 minutes
private final ServiceAccountTokenSupplier serviceAccountTokenSupplier;
private final boolean isUsingDefaultSessionKeySupplier;

/**
* The authentication provider to sign the internal requests.
*/
private final OkeTenancyOnlyAuthenticationDetailsProvider provider;

/** Tracks the time of the last failed refresh attempt. */
private volatile Instant lastFailureTime = null;

/**
* The duration for which token refresh should be skipped after a failure. Calculated as a
* fraction of the remaining token validity.
*/
private volatile Duration backoffDuration = Duration.ZERO;

/**
* Constructor of OkeWorkloadIdentityResourcePrincipalsFederationClient.
* @param federationEndpoint
Expand All @@ -86,6 +98,37 @@ public OkeWorkloadIdentityResourcePrincipalsFederationClient(
circuitBreakerConfiguration);
this.serviceAccountTokenSupplier = serviceAccountTokenSupplier;
this.provider = okeTenancyOnlyAuthenticationDetailsProvider;
this.isUsingDefaultSessionKeySupplier = true;
}

/**
* Constructor of OkeWorkloadIdentityResourcePrincipalsFederationClient.
* @param federationEndpoint
* @param sessionKeySupplier the session key supplier.
* @param okeTenancyOnlyAuthenticationDetailsProvider the key pair authentication details provider.
* @param clientConfigurator the reset client configurator.
* @param isUsingDefaultSessionKeySupplier the flag to indicate the type of session key supplier
*/
public OkeWorkloadIdentityResourcePrincipalsFederationClient(
String federationEndpoint,
SessionKeySupplier sessionKeySupplier,
ServiceAccountTokenSupplier serviceAccountTokenSupplier,
OkeTenancyOnlyAuthenticationDetailsProvider okeTenancyOnlyAuthenticationDetailsProvider,
ClientConfigurator clientConfigurator,
CircuitBreakerConfiguration circuitBreakerConfiguration,
boolean isUsingDefaultSessionKeySupplier) {

// we don't use a resourcePrincipalTokenEndpoint, therefore blank
super(
"",
federationEndpoint,
sessionKeySupplier,
okeTenancyOnlyAuthenticationDetailsProvider,
clientConfigurator,
circuitBreakerConfiguration);
this.serviceAccountTokenSupplier = serviceAccountTokenSupplier;
this.provider = okeTenancyOnlyAuthenticationDetailsProvider;
this.isUsingDefaultSessionKeySupplier = isUsingDefaultSessionKeySupplier;
}

/**
Expand All @@ -97,24 +140,62 @@ public OkeWorkloadIdentityResourcePrincipalsFederationClient(
@Override
public String getSecurityToken() {
SecurityTokenAdapter securityTokenAdapter = getSecurityTokenAdapter();
boolean isTokenValid = securityTokenAdapter.isValid();

// Check for valid token and ongoing backoff period
if (isTokenValid && lastFailureTime != null) {
// Check if we are still within the calculated backoff period
Duration elapsedSinceFailure = Duration.between(lastFailureTime, Instant.now());
if (elapsedSinceFailure.compareTo(backoffDuration) < 0) {
// Skip the token refresh request because of previous failure and valid token
LOG.info(
"Skipping token refresh due to recent failure (backoff active for {}s). Returning cached token.",
backoffDuration.getSeconds());
return securityTokenAdapter.getSecurityToken();
}
LOG.info("Backoff period expired. Attempting token refresh.");
}

try {
Duration time = Duration.ZERO;
if (securityTokenAdapter.isValid()) {
if (securityTokenAdapter.getTokenValidDuration() != null) {
// Calculate the half of the token's total valid duration
Duration halfDuration =
securityTokenAdapter.getTokenValidDuration().dividedBy(2);
// Generate Jitter Factor: a random value between 0.95 and 1.05 (i.e., ±5%)
double jitterFactor = 1.0 + (Math.random() * 0.1 - 0.05);
// Apply the jitter factor
time = halfDuration.multipliedBy((long) (jitterFactor * 1000)).dividedBy(1000);
}
if (isTokenValid) {
// Calculate the half of the token's total valid duration
Duration halfDuration = securityTokenAdapter.getTokenValidDuration().dividedBy(2);
// Generate Jitter Factor: a random value between 0.95 and 1.05 (i.e., ±5%)
double jitterFactor = 1.0 + (Math.random() * 0.1 - 0.05);
time = halfDuration.multipliedBy((long) (jitterFactor * 1000)).dividedBy(1000);
}
String token = refreshAndGetSecurityTokenIfExpiringWithin(time);

// Success: clear any pending failure state
lastFailureTime = null;
backoffDuration = Duration.ZERO;

logTokenInfo(token);
return token;
} catch (Exception e) {
LOG.info("Refresh RPST token failed, use cached RPST token.", e);
LOG.error(
"Refresh Workload Identity Auth token failed, use cached Workload Identity Auth token.",
e);
// Mark previous execution as failed
lastFailureTime = Instant.now();

if (isTokenValid) {
Duration remainingDuration = securityTokenAdapter.getTokenRemainingDuration();
LOG.info("remainingDurationSeconds: {}", remainingDuration.getSeconds());

backoffDuration =
remainingDuration.getSeconds() < Duration.ofHours(2).getSeconds()
? Duration.ofSeconds(0)
: Duration.ofSeconds(MAX_RETRY_DELAY_SECONDS);
LOG.error(
"Token refresh failed. Initiating backoff for {}s.",
backoffDuration.getSeconds());
} else {
backoffDuration = Duration.ZERO;
LOG.error("Token refresh failed and cached token is invalid/expired. No backoff");
}

return securityTokenAdapter.getSecurityToken();
}
}
Expand Down Expand Up @@ -172,6 +253,10 @@ protected SecurityTokenAdapter getSecurityTokenFromServer() {
String opcRequestId = generateRequestId();
LOG.debug("Request id for resourcePrincipalSessionTokens request: '{}'", opcRequestId);

if (isUsingDefaultSessionKeySupplier) {
LOG.info("Using default session key supplier");
}

/* If the SettableSessionKeySupplier is configured as sessionKeySupplier then prefer new ServiceAccount
* level token caching which involves calling new caching enabled endpoint of proxymux else
* fallback to old endpoint
Expand Down Expand Up @@ -211,9 +296,12 @@ private SecurityTokenAdapter getSecurityTokenFromServerV1(String token, String o

try {
setProxymuxEndPoint();
String base64EncodedPublicKey = AuthUtils.base64EncodeNoChunking(publicKey);
if (StringUtils.isBlank(base64EncodedPublicKey)) {
throw new IllegalArgumentException("Public key cannot be blank");
}
GetOkeResourcePrincipalSessionTokenRequest getOkeResourcePrincipalSessionTokenRequest =
new GetOkeResourcePrincipalSessionTokenRequest(
AuthUtils.base64EncodeNoChunking(publicKey));
new GetOkeResourcePrincipalSessionTokenRequest(base64EncodedPublicKey);
WebTarget target = restClient.getBaseTarget().path("resourcePrincipalSessionTokens");
Invocation.Builder ib = target.request();

Expand Down
4 changes: 2 additions & 2 deletions bmc-addons/bmc-resteasy-client-configurator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-addons</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand All @@ -25,7 +25,7 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
</dependency>
</dependencies>
</project>
4 changes: 2 additions & 2 deletions bmc-addons/bmc-sasl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>oci-java-sdk-addons</artifactId>
<groupId>com.oracle.oci.sdk</groupId>
<version>2.91.0</version>
<version>2.93.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down Expand Up @@ -62,7 +62,7 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
</dependency>
</dependencies>

Expand Down
2 changes: 1 addition & 1 deletion bmc-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk</artifactId>
<version>2.91.0</version>
<version>2.93.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Loading