diff --git a/ojdbc-provider-oci/README.md b/ojdbc-provider-oci/README.md index 10b494e5..2479e33b 100644 --- a/ojdbc-provider-oci/README.md +++ b/ojdbc-provider-oci/README.md @@ -256,7 +256,12 @@ in Optional Parameters OCI_INSTANCE_PRINCIPAL Instance Principal Authentication   -   + + OCI_INSTANCE_PRINCIPAL_TIMEOUT
+ (Optional) Specifies the maximum time, in seconds, to wait for the instance principal authentication process to complete.
+ The value must be a valid integer (e.g., 5, 30). Decimal values are not allowed.
+ Default: 5 seconds + OCI_RESOURCE_PRINCIPAL @@ -763,6 +768,15 @@ common set of parameters. DEFAULT + + instancePrincipalTimeout + + Specifies the maximum time, in seconds, to wait for instance principal authentication to complete.
+ The value must be a valid integer (e.g., 5, 10). Decimal values are not accepted. + + A positive integer + 5 + @@ -815,7 +829,8 @@ OCI configuration file
Authenticate as an instance principal -. +.
+You may optionally configure the timeout for this authentication using the instancePrincipalTimeout parameter.
resource-principal
diff --git a/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/authentication/AuthenticationDetailsFactory.java b/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/authentication/AuthenticationDetailsFactory.java index 5216bda7..ff0b3238 100644 --- a/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/authentication/AuthenticationDetailsFactory.java +++ b/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/authentication/AuthenticationDetailsFactory.java @@ -108,6 +108,13 @@ public final class AuthenticationDetailsFactory */ public static final Parameter USERNAME = Parameter.create(); + /** + * Timeout in seconds for instance principal authentication. + * Optional – defaults to 5 seconds if not explicitly configured. + */ + public static final Parameter INSTANCE_PRINCIPAL_TIMEOUT = + Parameter.create(); + /** *

* An OCI region provided by instances of @@ -187,7 +194,7 @@ private static AbstractAuthenticationDetailsProvider getAuthenticationDetails( case CLOUD_SHELL: return cloudShellAuthentication(); case INSTANCE_PRINCIPAL: - return instancePrincipalAuthentication(); + return instancePrincipalAuthentication(parameterSet); case RESOURCE_PRINCIPAL: return resourcePrincipalAuthentication(); case INTERACTIVE: @@ -312,7 +319,7 @@ private static AbstractAuthenticationDetailsProvider getAuthenticationDetails( } try { - return instancePrincipalAuthentication(); + return instancePrincipalAuthentication(parameters); } catch (RuntimeException notComputeInstance) { previousFailure.addSuppressed( @@ -332,17 +339,23 @@ private static AbstractAuthenticationDetailsProvider getAuthenticationDetails( *

* It is thought that authentication as an instance principal should not take * more than a few seconds to complete, so this method will throw an - * {@code IllegalStateException} if a timeout of 5 seconds is exceeded. + * {@code IllegalStateException} if the operation exceeds the configured + * timeout (5 seconds by default). + *

+ * The timeout can be overridden using the optional + * {@code INSTANCE_PRINCIPAL_TIMEOUT} parameter (value in seconds), which can + * be provided in the URI query string. *

* @return Authentication details for an instance principal. Not null. * @throws IllegalStateException If the current environment is not a compute * instance. */ private static InstancePrincipalsAuthenticationDetailsProvider - instancePrincipalAuthentication() { + instancePrincipalAuthentication(ParameterSet parameters) { + int timeoutSeconds = parameters.getOptional(INSTANCE_PRINCIPAL_TIMEOUT); try { return InstancePrincipalAuthenticationTask.FUTURE - .get(5, TimeUnit.SECONDS); + .get(timeoutSeconds, TimeUnit.SECONDS); } catch (ExecutionException exception) { throw new IllegalStateException( @@ -356,8 +369,8 @@ private static AbstractAuthenticationDetailsProvider getAuthenticationDetails( } catch (TimeoutException timeoutException) { throw new IllegalStateException( - "Authentication as an instance principal did not complete within" + - " 5 seconds", + "Authentication as an instance principal did not complete within " + + timeoutSeconds + " seconds", timeoutException); } } diff --git a/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/configuration/OciConfigurationParameters.java b/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/configuration/OciConfigurationParameters.java index 6203e5e4..fad3015c 100644 --- a/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/configuration/OciConfigurationParameters.java +++ b/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/configuration/OciConfigurationParameters.java @@ -92,6 +92,16 @@ private OciConfigurationParameters(){} .addParameter("OCI_FINGERPRINT", FINGERPRINT) .addParameter("OCI_KEY_FILE", PRIVATE_KEY) .addParameter("OCI_PASS_PHRASE", PASS_PHRASE) + .addParameter("OCI_INSTANCE_PRINCIPAL_TIMEOUT", INSTANCE_PRINCIPAL_TIMEOUT, + 5, + s -> { + try { + return Integer.parseInt(s); + }catch (NumberFormatException e) { + throw new IllegalArgumentException( "Invalid value for " + + "OCI_INSTANCE_PRINCIPAL_TIMEOUT: " + s + ". The value must be an integer."); + } + }) .build(); /** diff --git a/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/resource/OciResourceProvider.java b/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/resource/OciResourceProvider.java index 84379050..c94fdeea 100644 --- a/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/resource/OciResourceProvider.java +++ b/ojdbc-provider-oci/src/main/java/oracle/jdbc/provider/oci/resource/OciResourceProvider.java @@ -80,6 +80,17 @@ public abstract class OciResourceProvider new ResourceParameter( "username", AuthenticationDetailsFactory.USERNAME), + new ResourceParameter("instancePrincipalTimeout", + AuthenticationDetailsFactory.INSTANCE_PRINCIPAL_TIMEOUT, + "5", + s -> { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid value for instancePrincipalTimeout: " + s + + " – must be an integer."); + } + }), new ResourceParameter( "region", AuthenticationDetailsFactory.REGION,