authStrategies = new java.util.ArrayList<>();
+ private String configPath;
+ private String configProfile = "DEFAULT";
+ private String authFingerprint;
+ private String authKeyFile = "oci_api_key.pem";
+ private String authPrivateKeyPath;
+ private char[] authPrivateKey;
+ private char[] authPassphrase;
+ private String authRegion;
+ private String authTenantId;
+ private String authUserId;
+ private String imdsHostName = "169.254.169.254";
+ private java.time.Duration imdsTimeout = java.time.Duration.parse("PT0.1S");
+
+ /**
+ * Protected to support extensibility.
+ *
+ */
+ protected BuilderBase() {
+ }
+
+ /**
+ * Update this builder from an existing prototype instance.
+ *
+ * @param prototype existing prototype to update this builder from
+ * @return updated builder instance
+ */
+ public BUILDER from(OciConfig prototype) {
+ authStrategy(prototype.authStrategy());
+ addAuthStrategies(prototype.authStrategies());
+ configPath(prototype.configPath());
+ configProfile(prototype.configProfile());
+ authFingerprint(prototype.authFingerprint());
+ authKeyFile(prototype.authKeyFile());
+ authPrivateKeyPath(prototype.authPrivateKeyPath());
+ authPrivateKey(prototype.authPrivateKey());
+ authPassphrase(prototype.authPassphrase());
+ authRegion(prototype.authRegion());
+ authTenantId(prototype.authTenantId());
+ authUserId(prototype.authUserId());
+ imdsHostName(prototype.imdsHostName());
+ imdsTimeout(prototype.imdsTimeout());
+ return identity();
+ }
+ /**
+ * Update this builder from an existing prototype builder instance.
+ *
+ * @param builder existing builder prototype to update this builder from
+ * @return updated builder instance
+ */
+ public BUILDER from(BuilderBase, ?> builder) {
+ builder.authStrategy().ifPresent(this::authStrategy);
+ addAuthStrategies(builder.authStrategies());
+ builder.configPath().ifPresent(this::configPath);
+ builder.configProfile().ifPresent(this::configProfile);
+ builder.authFingerprint().ifPresent(this::authFingerprint);
+ authKeyFile(builder.authKeyFile());
+ builder.authPrivateKeyPath().ifPresent(this::authPrivateKeyPath);
+ builder.authPrivateKey().ifPresent(this::authPrivateKey);
+ builder.authPassphrase().ifPresent(this::authPassphrase);
+ builder.authRegion().ifPresent(this::authRegion);
+ builder.authTenantId().ifPresent(this::authTenantId);
+ builder.authUserId().ifPresent(this::authUserId);
+ imdsHostName(builder.imdsHostName());
+ imdsTimeout(builder.imdsTimeout());
+ return identity();
+ }
+ /**
+ * Handles providers and decorators.
+ */
+ protected void preBuildPrototype() {
+ }
+ /**
+ * Validates required properties.
+ */
+ protected void validatePrototype() {
+ }
+ /**
+ * Update builder from configuration (node of this type).
+ * If a value is present in configuration, it would override currently configured values.
+ *
+ * @param config configuration instance used to obtain values to update this builder
+ * @return updated builder instance
+ */
+// @Override
+ public BUILDER config(Config config) {
+ Objects.requireNonNull(config);
+ this.config = config;
+ config.get("auth-strategy").as(String.class).ifPresent(this::authStrategy);
+ config.get("auth-strategies").asList(String.class).ifPresent(this::authStrategies);
+ config.get("config.path").as(String.class).ifPresent(this::configPath);
+ config.get("config.profile").as(String.class).ifPresent(this::configProfile);
+ config.get("auth.fingerprint").as(String.class).ifPresent(this::authFingerprint);
+ config.get("auth.keyFile").as(String.class).ifPresent(this::authKeyFile);
+ config.get("auth.private-key-path").as(String.class).ifPresent(this::authPrivateKeyPath);
+ config.get("auth.private-key").asString().map(String::toCharArray).ifPresent(this::authPrivateKey);
+ config.get("auth.passphrase").asString().map(String::toCharArray).ifPresent(this::authPassphrase);
+ config.get("auth.region").as(String.class).ifPresent(this::authRegion);
+ config.get("auth.tenant-id").as(String.class).ifPresent(this::authTenantId);
+ config.get("auth.user-id").as(String.class).ifPresent(this::authUserId);
+ config.get("imds.hostname").as(String.class).ifPresent(this::imdsHostName);
+ config.get("imds.timeout.milliseconds").as(java.time.Duration.class).ifPresent(this::imdsTimeout);
+ return identity();
+ }
+ /**
+ * The singular authentication strategy to apply. This will be preferred over {@link #authStrategies()} if both are
+ * present.
+ *
+ * @param authStrategy the singular authentication strategy to be applied
+ * @return updated builder instance
+ * @see #authStrategy()
+ */
+ BUILDER authStrategy(Optional extends String> authStrategy) {
+ Objects.requireNonNull(authStrategy);
+ this.authStrategy = authStrategy.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authStrategy()
+ */
+ public BUILDER clearAuthStrategy() {
+ this.authStrategy = null;
+ return identity();
+ }
+ /**
+ * The singular authentication strategy to apply. This will be preferred over {@link #authStrategies()} if both are
+ * present.
+ *
+ * @param authStrategy the singular authentication strategy to be applied
+ * @return updated builder instance
+ * @see #authStrategy()
+ */
+ public BUILDER authStrategy(String authStrategy) {
+ Objects.requireNonNull(authStrategy);
+ this.authStrategy = authStrategy;
+ return identity();
+ }
+ /**
+ * The list of authentication strategies that will be attempted by
+ * {@link com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider} when one is
+ * called for. This is only used if {@link #authStrategy()} is not present.
+ *
+ *
+ * - {@code auto} - if present in the list, or if no value
+ * for this property exists, the behavior will be as if {@code
+ * config,config-file,instance-principals,resource-principal}
+ * were supplied instead.
+ * - {@code config} - the
+ * {@link com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code config-file} - the
+ * {@link com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code instance-principals} - the
+ * {@link com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider}
+ * will be used.
+ * - {@code resource-principal} - the
+ * {@link com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider}
+ * will be used.
+ *
+ *
+ * If there are many strategy descriptors supplied, the
+ * first one that is deemed to be available or suitable will
+ * be used and all others will be ignored.
+ *
+ * @param authStrategies the list of authentication strategies that will be applied, defaulting to {@code auto}
+ * @return updated builder instance
+ * @see #authStrategies()
+ */
+ public BUILDER authStrategies(java.util.List extends String> authStrategies) {
+ Objects.requireNonNull(authStrategies);
+ this.authStrategies.clear();
+ this.authStrategies.addAll(authStrategies);
+ return identity();
+ }
+ /**
+ * The list of authentication strategies that will be attempted by
+ * {@link com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider} when one is
+ * called for. This is only used if {@link #authStrategy()} is not present.
+ *
+ *
+ * - {@code auto} - if present in the list, or if no value
+ * for this property exists, the behavior will be as if {@code
+ * config,config-file,instance-principals,resource-principal}
+ * were supplied instead.
+ * - {@code config} - the
+ * {@link com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code config-file} - the
+ * {@link com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code instance-principals} - the
+ * {@link com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider}
+ * will be used.
+ * - {@code resource-principal} - the
+ * {@link com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider}
+ * will be used.
+ *
+ *
+ * If there are many strategy descriptors supplied, the
+ * first one that is deemed to be available or suitable will
+ * be used and all others will be ignored.
+ *
+ * @param authStrategies the list of authentication strategies that will be applied, defaulting to {@code auto}
+ * @return updated builder instance
+ * @see #authStrategies()
+ */
+ public BUILDER addAuthStrategies(java.util.List extends String> authStrategies) {
+ Objects.requireNonNull(authStrategies);
+ this.authStrategies.addAll(authStrategies);
+ return identity();
+ }
+ /**
+ * The OCI configuration profile path.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property must also be present and then the
+ * {@linkplain com.oracle.bmc.ConfigFileReader#parse(String)}
+ * method will be passed this value. It is expected to be passed with a
+ * valid OCI configuration file path.
+ *
+ * @param configPath the OCI configuration profile path
+ * @return updated builder instance
+ * @see #configPath()
+ */
+ BUILDER configPath(Optional extends String> configPath) {
+ Objects.requireNonNull(configPath);
+ this.configPath = configPath.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #configPath()
+ */
+ public BUILDER clearConfigPath() {
+ this.configPath = null;
+ return identity();
+ }
+ /**
+ * The OCI configuration profile path.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property must also be present and then the
+ * {@linkplain com.oracle.bmc.ConfigFileReader#parse(String)}
+ * method will be passed this value. It is expected to be passed with a
+ * valid OCI configuration file path.
+ *
+ * @param configPath the OCI configuration profile path
+ * @return updated builder instance
+ * @see #configPath()
+ */
+ public BUILDER configPath(String configPath) {
+ Objects.requireNonNull(configPath);
+ this.configPath = configPath;
+ return identity();
+ }
+ /**
+ * The OCI configuration/auth profile name.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property may also be optionally provided in order to override the default
+ * {@value #DEFAULT_PROFILE_NAME}.
+ *
+ * @param configProfile the optional OCI configuration/auth profile name
+ * @return updated builder instance
+ * @see #configProfile()
+ */
+ BUILDER configProfile(Optional extends String> configProfile) {
+ Objects.requireNonNull(configProfile);
+ this.configProfile = configProfile.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #configProfile()
+ */
+ public BUILDER clearConfigProfile() {
+ this.configProfile = null;
+ return identity();
+ }
+ /**
+ * The OCI configuration/auth profile name.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property may also be optionally provided in order to override the default
+ * {@value #DEFAULT_PROFILE_NAME}.
+ *
+ * @param configProfile the optional OCI configuration/auth profile name
+ * @return updated builder instance
+ * @see #configProfile()
+ */
+ public BUILDER configProfile(String configProfile) {
+ Objects.requireNonNull(configProfile);
+ this.configProfile = configProfile;
+ return identity();
+ }
+ /**
+ * The OCI authentication fingerprint.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the API signing key's fingerprint.
+ * See {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getFingerprint()} for more details.
+ *
+ * @param authFingerprint the OCI authentication fingerprint
+ * @return updated builder instance
+ * @see #authFingerprint()
+ */
+ BUILDER authFingerprint(Optional extends String> authFingerprint) {
+ Objects.requireNonNull(authFingerprint);
+ this.authFingerprint = authFingerprint.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authFingerprint()
+ */
+ public BUILDER clearAuthFingerprint() {
+ this.authFingerprint = null;
+ return identity();
+ }
+ /**
+ * The OCI authentication fingerprint.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the API signing key's fingerprint.
+ * See {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getFingerprint()} for more details.
+ *
+ * @param authFingerprint the OCI authentication fingerprint
+ * @return updated builder instance
+ * @see #authFingerprint()
+ */
+ public BUILDER authFingerprint(String authFingerprint) {
+ Objects.requireNonNull(authFingerprint);
+ this.authFingerprint = authFingerprint;
+ return identity();
+ }
+ /**
+ * The OCI authentication key file.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file must exist in the
+ * {@code user.home} directory. Alternatively, this property can be set using either {@link #authPrivateKey()} or
+ * using {@link #authPrivateKeyPath()}.
+ *
+ * @param authKeyFile the OCI authentication key file
+ * @return updated builder instance
+ * @see #authKeyFile()
+ */
+ public BUILDER authKeyFile(String authKeyFile) {
+ Objects.requireNonNull(authKeyFile);
+ this.authKeyFile = authKeyFile;
+ return identity();
+ }
+ /**
+ * The OCI authentication key file path.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file path is
+ * an alternative for using {@link #authKeyFile()} where the file must exist in the {@code user.home} directory.
+ * Alternatively, this property can be set using {@link #authPrivateKey()}.
+ *
+ * @param authPrivateKeyPath the OCI authentication key file path
+ * @return updated builder instance
+ * @see #authPrivateKeyPath()
+ */
+ BUILDER authPrivateKeyPath(Optional extends String> authPrivateKeyPath) {
+ Objects.requireNonNull(authPrivateKeyPath);
+ this.authPrivateKeyPath = authPrivateKeyPath.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authPrivateKeyPath()
+ */
+ public BUILDER clearAuthPrivateKeyPath() {
+ this.authPrivateKeyPath = null;
+ return identity();
+ }
+ /**
+ * The OCI authentication key file path.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file path is
+ * an alternative for using {@link #authKeyFile()} where the file must exist in the {@code user.home} directory.
+ * Alternatively, this property can be set using {@link #authPrivateKey()}.
+ *
+ * @param authPrivateKeyPath the OCI authentication key file path
+ * @return updated builder instance
+ * @see #authPrivateKeyPath()
+ */
+ public BUILDER authPrivateKeyPath(String authPrivateKeyPath) {
+ Objects.requireNonNull(authPrivateKeyPath);
+ this.authPrivateKeyPath = authPrivateKeyPath;
+ return identity();
+ }
+ /**
+ * The OCI authentication private key.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. Alternatively, this property
+ * can be set using either {@link #authKeyFile()} residing in the {@code user.home} directory, or using
+ * {@link #authPrivateKeyPath()}.
+ *
+ * @param authPrivateKey the OCI authentication private key
+ * @return updated builder instance
+ * @see #authPrivateKey()
+ */
+ BUILDER authPrivateKey(Optional extends char[]> authPrivateKey) {
+ Objects.requireNonNull(authPrivateKey);
+ this.authPrivateKey = authPrivateKey.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authPrivateKey()
+ */
+ public BUILDER clearAuthPrivateKey() {
+ this.authPrivateKey = null;
+ return identity();
+ }
+ /**
+ * The OCI authentication private key.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. Alternatively, this property
+ * can be set using either {@link #authKeyFile()} residing in the {@code user.home} directory, or using
+ * {@link #authPrivateKeyPath()}.
+ *
+ * @param authPrivateKey the OCI authentication private key
+ * @return updated builder instance
+ * @see #authPrivateKey()
+ */
+ public BUILDER authPrivateKey(char[] authPrivateKey) {
+ Objects.requireNonNull(authPrivateKey);
+ this.authPrivateKey = authPrivateKey;
+ return identity();
+ }
+ /**
+ * The OCI authentication private key.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. Alternatively, this property
+ * can be set using either {@link #authKeyFile()} residing in the {@code user.home} directory, or using
+ * {@link #authPrivateKeyPath()}.
+ *
+ * @param authPrivateKey the OCI authentication private key
+ * @return updated builder instance
+ * @see #authPrivateKey()
+ */
+ public BUILDER authPrivateKey(String authPrivateKey) {
+ Objects.requireNonNull(authPrivateKey);
+ this.authPrivateKey = authPrivateKey.toCharArray();
+ return identity();
+ }
+ /**
+ * The OCI authentication passphrase.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPassphraseCharacters()}.
+ *
+ * @param authPassphrase the OCI authentication passphrase
+ * @return updated builder instance
+ * @see #authPassphrase()
+ */
+ BUILDER authPassphrase(Optional extends char[]> authPassphrase) {
+ Objects.requireNonNull(authPassphrase);
+ this.authPassphrase = authPassphrase.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authPassphrase()
+ */
+ public BUILDER clearAuthPassphrase() {
+ this.authPassphrase = null;
+ return identity();
+ }
+ /**
+ * The OCI authentication passphrase.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPassphraseCharacters()}.
+ *
+ * @param authPassphrase the OCI authentication passphrase
+ * @return updated builder instance
+ * @see #authPassphrase()
+ */
+ public BUILDER authPassphrase(char[] authPassphrase) {
+ Objects.requireNonNull(authPassphrase);
+ this.authPassphrase = authPassphrase;
+ return identity();
+ }
+ /**
+ * The OCI authentication passphrase.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPassphraseCharacters()}.
+ *
+ * @param authPassphrase the OCI authentication passphrase
+ * @return updated builder instance
+ * @see #authPassphrase()
+ */
+ public BUILDER authPassphrase(String authPassphrase) {
+ Objects.requireNonNull(authPassphrase);
+ this.authPassphrase = authPassphrase.toCharArray();
+ return identity();
+ }
+ /**
+ * The OCI region.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, either this property or {@link com.oracle.bmc.auth.RegionProvider} must be provide a value in order
+ * to set the {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getRegion()}.
+ *
+ * @param authRegion the OCI region
+ * @return updated builder instance
+ * @see #authRegion()
+ */
+ BUILDER authRegion(Optional extends String> authRegion) {
+ Objects.requireNonNull(authRegion);
+ this.authRegion = authRegion.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authRegion()
+ */
+ public BUILDER clearAuthRegion() {
+ this.authRegion = null;
+ return identity();
+ }
+ /**
+ * The OCI region.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, either this property or {@link com.oracle.bmc.auth.RegionProvider} must be provide a value in order
+ * to set the {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getRegion()}.
+ *
+ * @param authRegion the OCI region
+ * @return updated builder instance
+ * @see #authRegion()
+ */
+ public BUILDER authRegion(String authRegion) {
+ Objects.requireNonNull(authRegion);
+ this.authRegion = authRegion;
+ return identity();
+ }
+ /**
+ * The OCI tenant id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getTenantId()}.
+ *
+ * @param authTenantId the OCI tenant id
+ * @return updated builder instance
+ * @see #authTenantId()
+ */
+ BUILDER authTenantId(Optional extends String> authTenantId) {
+ Objects.requireNonNull(authTenantId);
+ this.authTenantId = authTenantId.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authTenantId()
+ */
+ public BUILDER clearAuthTenantId() {
+ this.authTenantId = null;
+ return identity();
+ }
+ /**
+ * The OCI tenant id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getTenantId()}.
+ *
+ * @param authTenantId the OCI tenant id
+ * @return updated builder instance
+ * @see #authTenantId()
+ */
+ public BUILDER authTenantId(String authTenantId) {
+ Objects.requireNonNull(authTenantId);
+ this.authTenantId = authTenantId;
+ return identity();
+ }
+ /**
+ * The OCI user id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getUserId()}.
+ *
+ * @param authUserId the OCI user id
+ * @return updated builder instance
+ * @see #authUserId()
+ */
+ BUILDER authUserId(Optional extends String> authUserId) {
+ Objects.requireNonNull(authUserId);
+ this.authUserId = authUserId.orElse(null);
+ return identity();
+ }
+ /**
+ * Clear existing value of this property.
+ * @return updated builder instance
+ * @see #authUserId()
+ */
+ public BUILDER clearAuthUserId() {
+ this.authUserId = null;
+ return identity();
+ }
+ /**
+ * The OCI user id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getUserId()}.
+ *
+ * @param authUserId the OCI user id
+ * @return updated builder instance
+ * @see #authUserId()
+ */
+ public BUILDER authUserId(String authUserId) {
+ Objects.requireNonNull(authUserId);
+ this.authUserId = authUserId;
+ return identity();
+ }
+ /**
+ * The OCI IMDS hostname.
+ *
+ * This configuration property is used to identify the metadata service url.
+ *
+ * @param imdsHostName the OCI IMDS hostname
+ * @return updated builder instance
+ * @see #imdsHostName()
+ */
+ public BUILDER imdsHostName(String imdsHostName) {
+ Objects.requireNonNull(imdsHostName);
+ this.imdsHostName = imdsHostName;
+ return identity();
+ }
+ /**
+ * The OCI IMDS connection timeout. This is used to auto-detect availability.
+ *
+ * This configuration property is used when attempting to connect to the metadata service.
+ *
+ * @param imdsTimeout the OCI IMDS connection timeout
+ * @return updated builder instance
+ * @see #imdsTimeout()
+ */
+ public BUILDER imdsTimeout(java.time.Duration imdsTimeout) {
+ Objects.requireNonNull(imdsTimeout);
+ this.imdsTimeout = imdsTimeout;
+ return identity();
+ }
+ /**
+ * The singular authentication strategy to apply. This will be preferred over {@link #authStrategies()} if both are
+ * present.
+ *
+ * @return the auth strategy
+ */
+ public Optional authStrategy() {
+ return Optional.ofNullable(authStrategy);
+ }
+ /**
+ * The list of authentication strategies that will be attempted by
+ * {@link com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider} when one is
+ * called for. This is only used if {@link #authStrategy()} is not present.
+ *
+ *
+ * - {@code auto} - if present in the list, or if no value
+ * for this property exists, the behavior will be as if {@code
+ * config,config-file,instance-principals,resource-principal}
+ * were supplied instead.
+ * - {@code config} - the
+ * {@link com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code config-file} - the
+ * {@link com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code instance-principals} - the
+ * {@link com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider}
+ * will be used.
+ * - {@code resource-principal} - the
+ * {@link com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider}
+ * will be used.
+ *
+ *
+ * If there are many strategy descriptors supplied, the
+ * first one that is deemed to be available or suitable will
+ * be used and all others will be ignored.
+ *
+ * @return the auth strategies
+ */
+ public java.util.List authStrategies() {
+ return authStrategies;
+ }
+ /**
+ * The OCI configuration profile path.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property must also be present and then the
+ * {@linkplain com.oracle.bmc.ConfigFileReader#parse(String)}
+ * method will be passed this value. It is expected to be passed with a
+ * valid OCI configuration file path.
+ *
+ * @return the config path
+ */
+ public Optional configPath() {
+ return Optional.ofNullable(configPath);
+ }
+ /**
+ * The OCI configuration/auth profile name.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property may also be optionally provided in order to override the default
+ * {@value #DEFAULT_PROFILE_NAME}.
+ *
+ * @return the config profile
+ */
+ public Optional configProfile() {
+ return Optional.ofNullable(configProfile);
+ }
+ /**
+ * The OCI authentication fingerprint.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the API signing key's fingerprint.
+ * See {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getFingerprint()} for more details.
+ *
+ * @return the auth fingerprint
+ */
+ public Optional authFingerprint() {
+ return Optional.ofNullable(authFingerprint);
+ }
+ /**
+ * The OCI authentication key file.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file must exist in the
+ * {@code user.home} directory. Alternatively, this property can be set using either {@link #authPrivateKey()} or
+ * using {@link #authPrivateKeyPath()}.
+ *
+ * @return the auth key file
+ */
+ public String authKeyFile() {
+ return authKeyFile;
+ }
+ /**
+ * The OCI authentication key file path.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file path is
+ * an alternative for using {@link #authKeyFile()} where the file must exist in the {@code user.home} directory.
+ * Alternatively, this property can be set using {@link #authPrivateKey()}.
+ *
+ * @return the auth private key path
+ */
+ public Optional authPrivateKeyPath() {
+ return Optional.ofNullable(authPrivateKeyPath);
+ }
+ /**
+ * The OCI authentication private key.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. Alternatively, this property
+ * can be set using either {@link #authKeyFile()} residing in the {@code user.home} directory, or using
+ * {@link #authPrivateKeyPath()}.
+ *
+ * @return the auth private key
+ */
+ public Optional authPrivateKey() {
+ return Optional.ofNullable(authPrivateKey);
+ }
+ /**
+ * The OCI authentication passphrase.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPassphraseCharacters()}.
+ *
+ * @return the auth passphrase
+ */
+ public Optional authPassphrase() {
+ return Optional.ofNullable(authPassphrase);
+ }
+ /**
+ * The OCI region.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, either this property or {@link com.oracle.bmc.auth.RegionProvider} must be provide a value in order
+ * to set the {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getRegion()}.
+ *
+ * @return the auth region
+ */
+ public Optional authRegion() {
+ return Optional.ofNullable(authRegion);
+ }
+ /**
+ * The OCI tenant id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getTenantId()}.
+ *
+ * @return the auth tenant id
+ */
+ public Optional authTenantId() {
+ return Optional.ofNullable(authTenantId);
+ }
+ /**
+ * The OCI user id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getUserId()}.
+ *
+ * @return the auth user id
+ */
+ public Optional authUserId() {
+ return Optional.ofNullable(authUserId);
+ }
+ /**
+ * The OCI IMDS hostname.
+ *
+ * This configuration property is used to identify the metadata service url.
+ *
+ * @return the imds host name
+ */
+ public String imdsHostName() {
+ return imdsHostName;
+ }
+ /**
+ * The OCI IMDS connection timeout. This is used to auto-detect availability.
+ *
+ * This configuration property is used when attempting to connect to the metadata service.
+ *
+ * @return the imds timeout
+ */
+ public java.time.Duration imdsTimeout() {
+ return imdsTimeout;
+ }
+ /**
+ * If this instance was configured, this would be the config instance used.
+ *
+ * @return config node used to configure this builder, or empty if not configured
+ */
+ public Optional config() {
+ return Optional.ofNullable(config);
+ }
+ @Override
+ public String toString() {
+ return "OciConfigBuilder{"
+ + "authStrategy=" + authStrategy + ","
+ + "authStrategies=" + authStrategies + ","
+ + "configPath=" + configPath + ","
+ + "configProfile=" + configProfile + ","
+ + "authFingerprint=" + authFingerprint + ","
+ + "authKeyFile=" + authKeyFile + ","
+ + "authPrivateKeyPath=" + authPrivateKeyPath + ","
+ + "authPrivateKey=" + (authPrivateKey == null ? "null" : "****") + ","
+ + "authPassphrase=" + (authPassphrase == null ? "null" : "****") + ","
+ + "authRegion=" + authRegion + ","
+ + "authTenantId=" + authTenantId + ","
+ + "authUserId=" + authUserId + ","
+ + "imdsHostName=" + imdsHostName + ","
+ + "imdsTimeout=" + imdsTimeout
+ + "}";
+ }
+ /**
+ * Generated implementation of the prototype, can be extended by descendant prototype implementations.
+ */
+ protected static class OciConfigImpl implements OciConfig {
+ private final Optional authStrategy;
+ private final java.util.List authStrategies;
+ private final Optional configPath;
+ private final Optional configProfile;
+ private final Optional authFingerprint;
+ private final String authKeyFile;
+ private final Optional authPrivateKeyPath;
+ private final Optional authPrivateKey;
+ private final Optional authPassphrase;
+ private final Optional authRegion;
+ private final Optional authTenantId;
+ private final Optional authUserId;
+ private final String imdsHostName;
+ private final java.time.Duration imdsTimeout;
+
+ /**
+ * Create an instance providing a builder.
+ * @param builder extending builder base of this prototype
+ */
+ protected OciConfigImpl(BuilderBase, ?> builder) {
+ this.authStrategy = builder.authStrategy();
+ this.authStrategies = java.util.List.copyOf(builder.authStrategies());
+ this.configPath = builder.configPath();
+ this.configProfile = builder.configProfile();
+ this.authFingerprint = builder.authFingerprint();
+ this.authKeyFile = builder.authKeyFile();
+ this.authPrivateKeyPath = builder.authPrivateKeyPath();
+ this.authPrivateKey = builder.authPrivateKey();
+ this.authPassphrase = builder.authPassphrase();
+ this.authRegion = builder.authRegion();
+ this.authTenantId = builder.authTenantId();
+ this.authUserId = builder.authUserId();
+ this.imdsHostName = builder.imdsHostName();
+ this.imdsTimeout = builder.imdsTimeout();
+ }
+
+ @Override
+ public Optional authStrategy() {
+ return authStrategy;
+ }
+
+ @Override
+ public java.util.List authStrategies() {
+ return authStrategies;
+ }
+
+ @Override
+ public Optional configPath() {
+ return configPath;
+ }
+
+ @Override
+ public Optional configProfile() {
+ return configProfile;
+ }
+
+ @Override
+ public Optional authFingerprint() {
+ return authFingerprint;
+ }
+
+ @Override
+ public String authKeyFile() {
+ return authKeyFile;
+ }
+
+ @Override
+ public Optional authPrivateKeyPath() {
+ return authPrivateKeyPath;
+ }
+
+ @Override
+ public Optional authPrivateKey() {
+ return authPrivateKey;
+ }
+
+ @Override
+ public Optional authPassphrase() {
+ return authPassphrase;
+ }
+
+ @Override
+ public Optional authRegion() {
+ return authRegion;
+ }
+
+ @Override
+ public Optional authTenantId() {
+ return authTenantId;
+ }
+
+ @Override
+ public Optional authUserId() {
+ return authUserId;
+ }
+
+ @Override
+ public String imdsHostName() {
+ return imdsHostName;
+ }
+
+ @Override
+ public java.time.Duration imdsTimeout() {
+ return imdsTimeout;
+ }
+ @Override
+ public String toString() {
+ return "OciConfig{"
+ + "authStrategy=" + authStrategy + ","
+ + "authStrategies=" + authStrategies + ","
+ + "configPath=" + configPath + ","
+ + "configProfile=" + configProfile + ","
+ + "authFingerprint=" + authFingerprint + ","
+ + "authKeyFile=" + authKeyFile + ","
+ + "authPrivateKeyPath=" + authPrivateKeyPath + ","
+ + "authPrivateKey=" + (authPrivateKey.isPresent() ? "****" : "null") + ","
+ + "authPassphrase=" + (authPassphrase.isPresent() ? "****" : "null") + ","
+ + "authRegion=" + authRegion + ","
+ + "authTenantId=" + authTenantId + ","
+ + "authUserId=" + authUserId + ","
+ + "imdsHostName=" + imdsHostName + ","
+ + "imdsTimeout=" + imdsTimeout
+ + "}";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof OciConfig other)) {
+ return false;
+ }
+ return Objects.equals(authStrategy, other.authStrategy())
+ && Objects.equals(authStrategies, other.authStrategies())
+ && Objects.equals(configPath, other.configPath())
+ && Objects.equals(configProfile, other.configProfile())
+ && Objects.equals(authFingerprint, other.authFingerprint())
+ && Objects.equals(authKeyFile, other.authKeyFile())
+ && Objects.equals(authPrivateKeyPath, other.authPrivateKeyPath())
+ && Objects.equals(authPrivateKey, other.authPrivateKey())
+ && Objects.equals(authPassphrase, other.authPassphrase())
+ && Objects.equals(authRegion, other.authRegion())
+ && Objects.equals(authTenantId, other.authTenantId())
+ && Objects.equals(authUserId, other.authUserId())
+ && Objects.equals(imdsHostName, other.imdsHostName())
+ && Objects.equals(imdsTimeout, other.imdsTimeout());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(authStrategy, authStrategies, configPath, configProfile, authFingerprint, authKeyFile,
+ authPrivateKeyPath, authPrivateKey, authPassphrase, authRegion, authTenantId, authUserId,
+ imdsHostName, imdsTimeout);
+ }
+ }
+ }
+
+ /**
+ * Fluent API builder for {@link OciConfig}.
+ */
+ class Builder extends BuilderBase implements io.helidon.common.Builder {
+ private Builder() {
+ }
+
+ /**
+ * Builds the prototype.
+ *
+ * @return the prototype
+ */
+ public OciConfig buildPrototype() {
+ preBuildPrototype();
+ validatePrototype();
+ return new OciConfigImpl(this);
+ }
+
+ @Override
+ public OciConfig build() {
+ return buildPrototype();
+ }
+
+ }
+}
diff --git a/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/OciConfigBlueprint.java b/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/OciConfigBlueprint.java
new file mode 100644
index 00000000000..f8fe1a6df99
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/OciConfigBlueprint.java
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.integrations.oci.sdk.runtime;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import io.helidon.config.metadata.ConfiguredOption;
+import io.helidon.config.metadata.ConfiguredValue;
+
+import com.oracle.bmc.ConfigFileReader;
+
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.ALL_STRATEGIES;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.VAL_AUTO;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.VAL_CONFIG;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.VAL_CONFIG_FILE;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.VAL_INSTANCE_PRINCIPALS;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.VAL_RESOURCE_PRINCIPAL;
+
+/**
+ * Configuration used by {@link OciAuthenticationDetailsProvider}.
+ *
+ * Access the global {@link OciConfig} using the {@link OciExtension#ociConfig()} method.
+ * The configuration for this is delivered via a special {@value OciExtension#DEFAULT_OCI_GLOBAL_CONFIG_FILE} file. Minimally,
+ * this configuration file should have a key named {@value OciAuthenticationDetailsProvider#KEY_AUTH_STRATEGY} or else a
+ * list of auth strategies having a key named {@value OciAuthenticationDetailsProvider#KEY_AUTH_STRATEGIES}. In the later, all
+ * of the named auth strategies will be checked in the order they were specified for availability in the runtime environment (see
+ * details below). Here is an example for what the configuration would look like when a single auth strategy is explicitly
+ * configured :
+ *
+ * # oci.yaml
+ * auth-strategy : "config"
+ *
+ * And here is another example when the runtime should search true multi auth strategies in order to select the first one
+ * available in the runtime environment:
+ *
+ * # oci.yaml
+ * # if instance-principals are available then use it, going down the chain checking for availability, etc.
+ * auth-strategies: "instance-principals, config-file, resource-principal, config"
+ *
+ *
+ *
+ * Each configured {@link OciAuthenticationDetailsProvider#KEY_AUTH_STRATEGY} has varying constraints:
+ *
+ * - instance-principals - the JVM must be able to detect that it is running on a OCI compute node instance.
+ * - resource-principal - the env variable {@value OciAuthenticationDetailsProvider#TAG_RESOURCE_PRINCIPAL_VERSION} is
+ * required to be set in the runtime environment.
+ * - config-file - the {@code $HOME/.oci/config} is available on the file system. This configuration also allows for the
+ * optional key named {@code config-profile} to be used to override the file location in the runtime environment.
+ * - config - this configuration allows for these additional values to be set: {@code auth-tenant-id},
+ * {@code auth-user-id}, {@code auth-region}, {@code auth-fingerprint}, {@code auth-passphrase()}, and
+ * {@code auth-private-key}. Note that this configuration is only recommended in a development (i.e., non-production)
+ * environment since it relies on these additional security-sensitive values to be set. Note that these values cannot be
+ * sourced out of the Vault since this configuration source is primordial - the vault is not accessible here.
+ *
+ * See {@link #authStrategies()} for additional details.
+ *
+ * The default value for {@link OciAuthenticationDetailsProvider#KEY_AUTH_STRATEGY} is set to {@code auto}, meaning that
+ * the authentication strategy will follow a search heuristic to determine the appropriate setting. When running in the OCI
+ * runtime environment (i.e., the JVM is running on a detectable OCI compute node instance) then {@code instance-principals}
+ * is used, with a final fallback set to be {@code config-file} (i.e., $HOME/.oci/config).
+ *
+ * @see OciExtension
+ */
+interface OciConfigBlueprint {
+ /**
+ * Config key of this config.
+ */
+ String CONFIG_KEY = "oci";
+ /**
+ * Primary hostname of metadata service.
+ */
+ String IMDS_HOSTNAME = "169.254.169.254";
+ /**
+ * Redefine the constant, as it is private in BMC.
+ */
+ String DEFAULT_PROFILE_NAME = "DEFAULT";
+
+ /**
+ * The singular authentication strategy to apply. This will be preferred over {@link #authStrategies()} if both are
+ * present.
+ *
+ * @return the singular authentication strategy to be applied
+ */
+ @ConfiguredOption(allowedValues = {
+ @ConfiguredValue(value = VAL_AUTO, description = "auto select first applicable"),
+ @ConfiguredValue(value = VAL_CONFIG, description = "simple authentication provider"),
+ @ConfiguredValue(value = VAL_CONFIG_FILE, description = "config file authentication provider"),
+ @ConfiguredValue(value = VAL_INSTANCE_PRINCIPALS, description = "instance principals authentication provider"),
+ @ConfiguredValue(value = VAL_RESOURCE_PRINCIPAL, description = "resource principals authentication provider"),
+ })
+ Optional authStrategy();
+
+ /**
+ * The list of authentication strategies that will be attempted by
+ * {@link com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider} when one is
+ * called for. This is only used if {@link #authStrategy()} is not present.
+ *
+ *
+ * - {@code auto} - if present in the list, or if no value
+ * for this property exists.
+ * - {@code config} - the
+ * {@link com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code config-file} - the
+ * {@link com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider}
+ * will be used, customized with other configuration
+ * properties described here.
+ * - {@code instance-principals} - the
+ * {@link com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider}
+ * will be used.
+ * - {@code resource-principal} - the
+ * {@link com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider}
+ * will be used.
+ *
+ *
+ * If there are more than one strategy descriptors defined, the
+ * first one that is deemed to be available/suitable will be used and all others will be ignored.
+ *
+ * @return the list of authentication strategies that will be applied, defaulting to {@code auto}
+ * @see io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.AuthStrategy
+ */
+ @ConfiguredOption(allowedValues = {
+ @ConfiguredValue(value = VAL_AUTO, description = "auto select first applicable"),
+ @ConfiguredValue(value = VAL_CONFIG, description = "simple authentication provider"),
+ @ConfiguredValue(value = VAL_CONFIG_FILE, description = "config file authentication provider"),
+ @ConfiguredValue(value = VAL_INSTANCE_PRINCIPALS, description = "instance principals authentication provider"),
+ @ConfiguredValue(value = VAL_RESOURCE_PRINCIPAL, description = "resource principal authentication provider"),
+ })
+ List authStrategies();
+
+ /**
+ * The OCI configuration profile path.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property must also be present and then the
+ * {@linkplain ConfigFileReader#parse(String)}
+ * method will be passed this value. It is expected to be passed with a
+ * valid OCI configuration file path.
+ *
+ * @return the OCI configuration profile path
+ */
+ @ConfiguredOption(key = "config.path")
+ Optional configPath();
+
+ /**
+ * The OCI configuration/auth profile name.
+ *
+ * This configuration property has an effect only when {@code config-file} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #fileConfigIsPresent()}.
+ * When it is present, this property may also be optionally provided in order to override the default
+ * {@value #DEFAULT_PROFILE_NAME}.
+ *
+ * @return the optional OCI configuration/auth profile name
+ */
+ @ConfiguredOption(value = DEFAULT_PROFILE_NAME, key = "config.profile")
+ Optional configProfile();
+
+ /**
+ * The OCI authentication fingerprint.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the API signing key's fingerprint.
+ * See {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getFingerprint()} for more details.
+ *
+ * @return the OCI authentication fingerprint
+ */
+ @ConfiguredOption(key = "auth.fingerprint")
+ Optional authFingerprint();
+
+ /**
+ * The OCI authentication key file.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file must exist in the
+ * {@code user.home} directory. Alternatively, this property can be set using either {@link #authPrivateKey()} or
+ * using {@link #authPrivateKeyPath()}.
+ *
+ * @return the OCI authentication key file
+ */
+ @ConfiguredOption(value = "oci_api_key.pem", key = "auth.keyFile")
+ String authKeyFile();
+
+ /**
+ * The OCI authentication key file path.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. This file path is
+ * an alternative for using {@link #authKeyFile()} where the file must exist in the {@code user.home} directory.
+ * Alternatively, this property can be set using {@link #authPrivateKey()}.
+ *
+ * @return the OCI authentication key file path
+ */
+ @ConfiguredOption(key = "auth.private-key-path")
+ Optional authPrivateKeyPath();
+
+ /**
+ * The OCI authentication private key.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPrivateKey()}. Alternatively, this property
+ * can be set using either {@link #authKeyFile()} residing in the {@code user.home} directory, or using
+ * {@link #authPrivateKeyPath()}.
+ *
+ * @return the OCI authentication private key
+ */
+ // See https://github.com/helidon-io/helidon/issues/6908
+ @ConfiguredOption(key = "auth.private-key")
+// @Prototype.Confidential
+ Optional authPrivateKey();
+
+ /**
+ * The OCI authentication passphrase.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider#getPassphraseCharacters()}.
+ *
+ * @return the OCI authentication passphrase
+ */
+ // See https://github.com/helidon-io/helidon/issues/6908
+ @ConfiguredOption(key = "auth.passphrase")
+// @Prototype.Confidential
+ Optional authPassphrase();
+
+ /**
+ * The OCI region.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, either this property or {@link com.oracle.bmc.auth.RegionProvider} must be provide a value in order
+ * to set the {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getRegion()}.
+ *
+ * @return the OCI region
+ */
+ @ConfiguredOption(key = "auth.region")
+ Optional authRegion();
+
+ /**
+ * The OCI tenant id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}. This is also known as {@link #simpleConfigIsPresent()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getTenantId()}.
+ *
+ * @return the OCI tenant id
+ */
+ @ConfiguredOption(key = "auth.tenant-id")
+ Optional authTenantId();
+
+ /**
+ * The OCI user id.
+ *
+ * This configuration property has an effect only when {@code config} is, explicitly or implicitly,
+ * present in the value for the {@link #authStrategies()}.
+ * When it is present, this property must be provided in order to set the
+ * {@linkplain com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider#getUserId()}.
+ *
+ * @return the OCI user id
+ */
+ @ConfiguredOption(key = "auth.user-id")
+ Optional authUserId();
+
+ /**
+ * The OCI IMDS hostname.
+ *
+ * This configuration property is used to identify the metadata service url.
+ *
+ * @return the OCI IMDS hostname
+ */
+ @ConfiguredOption(value = IMDS_HOSTNAME, key = "imds.hostname")
+ String imdsHostName();
+
+ /**
+ * The OCI IMDS connection timeout. This is used to auto-detect availability.
+ *
+ * This configuration property is used when attempting to connect to the metadata service.
+ *
+ * @return the OCI IMDS connection timeout
+ */
+ @ConfiguredOption(value = "PT0.1S", key = "imds.timeout.milliseconds")
+ Duration imdsTimeout();
+
+ /**
+ * The list of {@link io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.AuthStrategy} names
+ * (excluding {@link io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.AuthStrategy#AUTO}) that
+ * are potentially applicable for use. Here, "potentially applicable for use" means that it is set using the
+ * {@link #authStrategy()} attribute on this config bean. If not present then the fall-back looks to use the values
+ * explicitly or implicitly set by {@link #authStrategies()}. Note that the order of this list is important as it pertains
+ * to the search/strategy ordering.
+ *
+ * @return the list of potential auth strategies that are applicable
+ */
+ default List potentialAuthStrategies() {
+ String authStrategy = authStrategy().orElse(null);
+ if (authStrategy != null
+ && !VAL_AUTO.equalsIgnoreCase(authStrategy)
+ && !authStrategy.isBlank()) {
+ if (!ALL_STRATEGIES.contains(authStrategy)) {
+ throw new IllegalStateException("Unknown auth strategy: " + authStrategy);
+ }
+
+ return List.of(authStrategy);
+ }
+
+ List result = new ArrayList<>();
+ authStrategies().stream()
+ .map(String::trim)
+ .filter(Predicate.not(String::isBlank))
+ .forEach(s -> {
+ if (!ALL_STRATEGIES.contains(s) && !VAL_AUTO.equals(s)) {
+ throw new IllegalStateException("Unknown auth strategy: " + s);
+ }
+ result.add(s);
+ });
+ if (result.isEmpty() || result.contains(VAL_AUTO)) {
+ return ALL_STRATEGIES;
+ }
+
+ return result;
+ }
+
+ /**
+ * Determines whether sufficient configuration is present on this bean to be used for OCI's "file-based" authentication
+ * provider. This matches to the {@link io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.AuthStrategy#CONFIG_FILE}.
+ *
+ * @return true if there is sufficient attributes defined for file-based OCI authentication provider applicability
+ * @see OciAuthenticationDetailsProvider
+ * @see com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider
+ */
+ default boolean fileConfigIsPresent() {
+ // the implementation will use ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault()), so we are
+ // therefore relaxing the criteria here for matching, and instead just verifying that parseDefaults will "work" later
+ // as the fallback mechanism.
+ if ((configPath().isPresent() && !configProfile().get().isBlank())
+ || (configProfile().isPresent() && configProfile().get().isBlank())) {
+ return true;
+ }
+
+ try {
+ ConfigFileReader.ConfigFile ignoredCfgFile = ConfigFileReader.parseDefault();
+ Objects.requireNonNull(ignoredCfgFile);
+ return true;
+ } catch (Exception e) {
+ OciAuthenticationDetailsProvider.LOGGER.log(System.Logger.Level.DEBUG,
+ "file config is not available: " + e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * Determines whether sufficient configuration is present on this bean to be used for OCI's "simple" authentication provider.
+ * This matches to the {@link io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.AuthStrategy#CONFIG}.
+ *
+ * @return true if there is sufficient attributes defined for simple OCI authentication provider applicability
+ * @see OciAuthenticationDetailsProvider
+ */
+ default boolean simpleConfigIsPresent() {
+ return authTenantId().isPresent()
+ && authUserId().isPresent()
+ && authPassphrase().isPresent()
+ && authFingerprint().isPresent()
+ // don't test region since it can alternatively come from the region provider
+ // && authRegion().isPresent()
+ && (authPrivateKey().isPresent()
+ || authPrivateKeyPath().isPresent());
+ }
+
+}
diff --git a/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/OciExtension.java b/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/OciExtension.java
new file mode 100644
index 00000000000..9ac0b23f646
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/OciExtension.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.integrations.oci.sdk.runtime;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import io.helidon.common.LazyValue;
+import io.helidon.config.Config;
+import io.helidon.config.ConfigSources;
+
+import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider;
+
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.KEY_AUTH_STRATEGIES;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.KEY_AUTH_STRATEGY;
+import static io.helidon.integrations.oci.sdk.runtime.OciAuthenticationDetailsProvider.select;
+import static java.util.function.Predicate.not;
+
+/**
+ * This class enables configuration access for integration to the Oracle Cloud Infrastructure Java SDK. It is intended for
+ * non-Helidon MP, non-CDI usage scenarios. For usages that involve
+ * Helidon MP and CDI please refer to
+ * {@code io.helidon.integrations.oci.sdk.cdi.OciExtension} instead. This
+ * integration will follow the same terminology and usage pattern as specified
+ * for Helidon MP integration.
+ *
+ * @see Oracle Cloud Infrastructure Java SDK
+ */
+public final class OciExtension {
+ static final String DEFAULT_OCI_GLOBAL_CONFIG_FILE = "oci.yaml";
+ static final System.Logger LOGGER = System.getLogger(OciExtension.class.getName());
+ static final LazyValue DEFAULT_OCI_CONFIG_BEAN = LazyValue.create(() -> OciConfig.builder()
+ .authStrategies(Arrays.stream(OciAuthenticationDetailsProvider.AuthStrategy.values())
+ .filter(not(it -> it == OciAuthenticationDetailsProvider.AuthStrategy.AUTO))
+ .map(OciAuthenticationDetailsProvider.AuthStrategy::id)
+ .toList())
+ .build());
+ private static String overrideOciConfigFile;
+ private static volatile Supplier ociConfigSupplier;
+
+ private OciExtension() {
+ }
+
+ /**
+ * The configured authentication provider strategy type name. Note, however, that the authentication strategy returned may not
+ * necessarily be available. The configured authentication provider merely returns what is configured via
+ * {@value OciAuthenticationDetailsProvider#KEY_AUTH_STRATEGY} and/or
+ * {@value OciAuthenticationDetailsProvider#KEY_AUTH_STRATEGIES}. In order to additionally check if the provider is available,
+ * the {@code verifyIsAvailable} argument should be {@code true}.
+ *
+ * @param verifyIsAvailable flag to indicate whether the provider should be checked for availability
+ * @return the configured authentication type name
+ */
+ public static Class extends AbstractAuthenticationDetailsProvider>
+ configuredAuthenticationDetailsProvider(boolean verifyIsAvailable) {
+ return select(ociConfig(), verifyIsAvailable).authStrategy().type();
+ }
+
+ /**
+ * Returns the global {@link OciConfig} bean that is currently defined in the bootstrap environment.
+ *
+ * The implementation will first look for an {@code oci.yaml} file, and if found will use that file to establish the global
+ * oci-specific bootstrap {@link io.helidon.config.spi.ConfigSource}.
+ *
+ * The final fallback mechanism will use an {@code auto} authentication strategy - see {@link OciConfigBlueprint} for details.
+ *
+ * @return the bootstrap oci config bean
+ * @see OciConfigBlueprint
+ * @see #ociConfigSupplier
+ */
+ public static OciConfig ociConfig() {
+ Config config = configSupplier().get();
+ if (isSufficientlyConfigured(config)) {
+ // we are good as-is
+ return OciConfig.create(config);
+ }
+
+ // fallback
+ LOGGER.log(System.Logger.Level.DEBUG, "No bootstrap - using default oci config");
+ return DEFAULT_OCI_CONFIG_BEAN.get();
+ }
+
+ /**
+ * The supplier for the globally configured OCI authentication provider.
+ *
+ * @return the supplier for the globally configured authentication provider
+ * @see #configSupplier()
+ */
+ public static Supplier extends AbstractAuthenticationDetailsProvider> ociAuthenticationProvider() {
+ // note that in v4 will use service registry, but here in v3 no extensibility is offered
+ return () -> Objects.requireNonNull(new OciAuthenticationDetailsProvider().get());
+ }
+
+ /**
+ * The supplier for the raw config-backed by the OCI config source(s).
+ *
+ * @return the supplier for the raw config-backed by the OCI config source(s)
+ * @see #ociAuthenticationProvider()
+ * @see #configSupplier(Supplier)
+ */
+ public static Supplier configSupplier() {
+ if (ociConfigSupplier == null) {
+ configSupplier(() -> {
+ // we do it this way to allow for any system and env vars to be used for the auth-strategy definition
+ // (not advertised in the javadoc)
+ String ociConfigFile = ociConfigFilename();
+ return Config.create(
+ ConfigSources.classpath(ociConfigFile).optional(),
+ ConfigSources.file(ociConfigFile).optional());
+ });
+ }
+
+ return ociConfigSupplier;
+ }
+
+ /**
+ * Establishes the supplier for the raw config-backed by the OCI config source(s).
+ *
+ * @param configSupplier the config supplier
+ * @see #configSupplier()
+ */
+ public static void configSupplier(Supplier configSupplier) {
+ ociConfigSupplier = configSupplier;
+ }
+
+ /**
+ * Returns {@code true} if the given config is sufficiently configured in order to identity an OCI authentication strategy.
+ * If {@code false} then {@link OciAuthenticationDetailsProvider.AuthStrategy#AUTO} will be applied.
+ *
+ * @param config the config
+ * @return true if the given config can be used to identify an OCI authentication strategy
+ */
+ static boolean isSufficientlyConfigured(Config config) {
+ return (config != null
+ && (config.get(KEY_AUTH_STRATEGY).exists()
+ || config.get(KEY_AUTH_STRATEGIES).exists()));
+ }
+
+ // in support for testing a variant of oci.yaml
+ static void ociConfigFileName(String fileName) {
+ overrideOciConfigFile = fileName;
+ ociConfigSupplier = null;
+ }
+
+ // in support for testing a variant of oci.yaml
+ static String ociConfigFilename() {
+ return (overrideOciConfigFile == null) ? DEFAULT_OCI_GLOBAL_CONFIG_FILE : overrideOciConfigFile;
+ }
+
+}
diff --git a/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/package-info.java b/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/package-info.java
new file mode 100644
index 00000000000..ebfc0a37202
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/main/java/io/helidon/integrations/oci/sdk/runtime/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Helidon Runtime Integrations to support OCI SDK.
+ */
+package io.helidon.integrations.oci.sdk.runtime;
diff --git a/integrations/oci/sdk/runtime/src/main/java/module-info.java b/integrations/oci/sdk/runtime/src/main/java/module-info.java
new file mode 100644
index 00000000000..f17b3cea816
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/main/java/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Helidon Integrations to support OCI Runtime module.
+ */
+module io.helidon.integrations.oci.sdk.runtime {
+ requires static jakarta.inject;
+ requires static io.helidon.config.metadata;
+
+ requires io.helidon.common;
+ requires transitive io.helidon.config;
+ requires oci.java.sdk.common;
+
+ exports io.helidon.integrations.oci.sdk.runtime;
+}
diff --git a/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciAuthenticationDetailsProviderTest.java b/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciAuthenticationDetailsProviderTest.java
new file mode 100644
index 00000000000..4faf90c0d35
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciAuthenticationDetailsProviderTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.integrations.oci.sdk.runtime;
+
+import java.util.Objects;
+
+import io.helidon.config.Config;
+
+import com.oracle.bmc.Region;
+import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
+import org.hamcrest.MatcherAssert;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class OciAuthenticationDetailsProviderTest {
+
+ @BeforeEach
+ @AfterEach
+ void reset() {
+ OciExtension.ociConfigFileName(null);
+ }
+
+ @Test
+ void testCanReadPath() {
+ MatcherAssert.assertThat(OciAuthenticationDetailsProvider.canReadPath("./target"),
+ is(true));
+ MatcherAssert.assertThat(OciAuthenticationDetailsProvider.canReadPath("./~bogus~"),
+ is(false));
+ }
+
+ @Test
+ void testUserHomePrivateKeyPath() {
+ OciConfig ociConfig = Objects.requireNonNull(OciExtension.ociConfig());
+ MatcherAssert.assertThat(OciAuthenticationDetailsProvider.userHomePrivateKeyPath(ociConfig),
+ endsWith("/.oci/oci_api_key.pem"));
+
+ ociConfig = OciConfig.builder(ociConfig)
+ .configPath("/decoy/path")
+ .authKeyFile("key.pem")
+ .build();
+ MatcherAssert.assertThat(OciAuthenticationDetailsProvider.userHomePrivateKeyPath(ociConfig),
+ endsWith("/.oci/key.pem"));
+ }
+
+ @Test
+ void authStrategiesAvailability() {
+ Config config = OciExtensionTest.createTestConfig(
+ OciExtensionTest.ociAuthConfigStrategies(OciAuthenticationDetailsProvider.VAL_AUTO),
+ OciExtensionTest.ociAuthSimpleConfig("tenant", "user", "phrase", "fp", null, null, "region"))
+ .get(OciConfig.CONFIG_KEY);
+ OciConfig cfg = OciConfig.create(config);
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.AUTO.isAvailable(cfg),
+ is(true));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.CONFIG.isAvailable(cfg),
+ is(false));
+ // this code is dependent upon whether and OCI config-file is present - so leaving this commented out intentionally
+// assertThat(OciAuthenticationDetailsProvider.AuthStrategy.CONFIG_FILE.isAvailable(cfg),
+// is(true));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.INSTANCE_PRINCIPALS.isAvailable(cfg),
+ is(false));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.RESOURCE_PRINCIPAL.isAvailable(cfg),
+ is(false));
+
+ config = OciExtensionTest.createTestConfig(
+ OciExtensionTest.ociAuthConfigStrategies(OciAuthenticationDetailsProvider.VAL_AUTO),
+ OciExtensionTest.ociAuthConfigFile("./target", null),
+ OciExtensionTest.ociAuthSimpleConfig("tenant", "user", "phrase", "fp", "pk", "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.AUTO.isAvailable(cfg),
+ is(true));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.CONFIG.isAvailable(cfg),
+ is(true));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.CONFIG_FILE.isAvailable(cfg),
+ is(true));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.INSTANCE_PRINCIPALS.isAvailable(cfg),
+ is(false));
+ assertThat(OciAuthenticationDetailsProvider.AuthStrategy.RESOURCE_PRINCIPAL.isAvailable(cfg),
+ is(false));
+ }
+
+ @Test
+ void selectionWhenNoConfigIsSet() {
+ Config config = Config.create();
+ assertThat(OciExtension.isSufficientlyConfigured(config),
+ is(false));
+ }
+
+ @Test
+ void selectionWhenFileConfigIsSetWithAuto() {
+ Config config = OciExtensionTest.createTestConfig(
+ OciExtensionTest.ociAuthConfigStrategies(OciAuthenticationDetailsProvider.VAL_AUTO),
+ OciExtensionTest.ociAuthConfigFile("./target", "profile"))
+ .get("oci");
+ assertThat(OciExtension.isSufficientlyConfigured(config),
+ is(true));
+ }
+
+ @Test
+ void selectionWhenSimpleConfigIsSetWithAuto() {
+ Config config = OciExtensionTest.createTestConfig(
+ OciExtensionTest.ociAuthConfigStrategies(OciAuthenticationDetailsProvider.VAL_AUTO),
+ OciExtensionTest.ociAuthSimpleConfig("tenant", "user", "passphrase", "fp", "privKey", null, "us-phoenix-1"))
+ .get("oci");
+ assertThat(OciExtension.isSufficientlyConfigured(config),
+ is(true));
+
+ OciExtension.configSupplier(() -> config);
+ AbstractAuthenticationDetailsProvider authProvider = OciExtension.ociAuthenticationProvider().get();
+ assertThat(authProvider.getClass(),
+ equalTo(SimpleAuthenticationDetailsProvider.class));
+ SimpleAuthenticationDetailsProvider auth = (SimpleAuthenticationDetailsProvider) authProvider;
+ assertThat(auth.getTenantId(),
+ equalTo("tenant"));
+ assertThat(auth.getUserId(),
+ equalTo("user"));
+ assertThat(auth.getRegion(),
+ equalTo(Region.US_PHOENIX_1));
+ assertThat(new String(auth.getPassphraseCharacters()),
+ equalTo("passphrase"));
+ }
+
+}
diff --git a/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciAvailabilityTest.java b/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciAvailabilityTest.java
new file mode 100644
index 00000000000..7e1a7f136a3
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciAvailabilityTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.integrations.oci.sdk.runtime;
+
+import java.util.Objects;
+
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class OciAvailabilityTest {
+
+ @Test
+ void isRunningOnOci() {
+ OciConfig ociConfigBean = Objects.requireNonNull(OciExtension.ociConfig());
+ assertThat(OciAvailabilityDefault.runningOnOci(ociConfigBean),
+ is(false));
+ }
+
+}
diff --git a/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciExtensionTest.java b/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciExtensionTest.java
new file mode 100644
index 00000000000..b87863e3d28
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/test/java/io/helidon/integrations/oci/sdk/runtime/OciExtensionTest.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.integrations.oci.sdk.runtime;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import io.helidon.config.Config;
+import io.helidon.config.ConfigSources;
+import io.helidon.config.MapConfigSource;
+
+import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static io.helidon.common.testing.junit5.OptionalMatcher.optionalValue;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Tests for {@link OciExtension} and {@link OciConfig}.
+ */
+class OciExtensionTest {
+
+ @AfterEach
+ void reset() {
+ OciExtension.ociConfigFileName(null);
+ }
+
+ @Test
+ void ociConfig() {
+ assertThat(OciExtension.ociConfig(),
+ notNullValue());
+ assertThat(OciExtension.ociConfig(),
+ equalTo(OciExtension.ociConfig()));
+ }
+
+ @Test
+ void potentialAuthStrategies() {
+ Config config = createTestConfig(ociAuthConfigStrategies(null))
+ .get(OciConfig.CONFIG_KEY);
+ OciConfig cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("instance-principals", "resource-principal", "config", "config-file"));
+
+ config = createTestConfig(ociAuthConfigStrategies("auto"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("instance-principals", "resource-principal", "config", "config-file"));
+
+ config = createTestConfig(ociAuthConfigStrategies(null, "instance-principals", "auto"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("instance-principals", "resource-principal", "config", "config-file"));
+
+ config = createTestConfig(ociAuthConfigStrategies(null, "instance-principals", "resource-principal"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("instance-principals", "resource-principal"));
+
+ config = createTestConfig(ociAuthConfigStrategies("config", "auto"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("config"));
+
+ config = createTestConfig(ociAuthConfigStrategies("config", "config", "config-file"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("config"));
+
+ config = createTestConfig(ociAuthConfigStrategies("auto", "config", "config-file"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("config", "config-file"));
+
+ config = createTestConfig(ociAuthConfigStrategies("", ""))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.potentialAuthStrategies(),
+ contains("instance-principals", "resource-principal", "config", "config-file"));
+ }
+
+ @Test
+ void bogusAuthStrategyAttempted() {
+ Config config = createTestConfig(ociAuthConfigStrategies("bogus"))
+ .get(OciConfig.CONFIG_KEY);
+ OciConfig cfg = OciConfig.create(config);
+ IllegalStateException e = assertThrows(IllegalStateException.class, cfg::potentialAuthStrategies);
+ assertThat(e.getMessage(),
+ equalTo("Unknown auth strategy: bogus"));
+
+ config = createTestConfig(ociAuthConfigStrategies(null, "config", "bogus"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ e = assertThrows(IllegalStateException.class, cfg::potentialAuthStrategies);
+ assertThat(e.getMessage(),
+ equalTo("Unknown auth strategy: bogus"));
+ }
+
+ @Test
+ void fileConfigIsPresent() {
+ Config config = createTestConfig(ociAuthConfigFile("path", "profile"))
+ .get(OciConfig.CONFIG_KEY);
+ OciConfig cfg = OciConfig.create(config);
+ assertThat(cfg.fileConfigIsPresent(),
+ is(true));
+ assertThat(cfg.configProfile().orElseThrow(),
+ equalTo("profile"));
+
+ config = createTestConfig(ociAuthConfigFile("path", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.fileConfigIsPresent(), is(true));
+ assertThat(cfg.configProfile().orElseThrow(),
+ equalTo("DEFAULT"));
+
+ config = createTestConfig(ociAuthConfigFile("", ""))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ // the ConfigFile type provider always works, since OCI SDK API assumes that too
+ assertThat(cfg.fileConfigIsPresent(),
+ is(true));
+
+ config = createTestConfig(ociAuthConfigFile(null, null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ // this will be true if there is a ~/.oci/config based configuration, false otherwise
+ // assertThat(cfg.fileConfigIsPresent(),
+ // is(true));
+ }
+
+ @Test
+ void simpleConfigIsPresent() {
+ Config config = createTestConfig(ociAuthSimpleConfig("tenant", "user", "phrase", "fp", "pk", "pkp", "region"))
+ .get(OciConfig.CONFIG_KEY);
+ OciConfig cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(true));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", "user", "phrase", "fp", "pk", "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(true));
+
+ config = createTestConfig(ociAuthSimpleConfig(null, "user", "phrase", "fp", "pk", "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(false));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", null, "phrase", "fp", "pk", "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(false));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", "user", null, "fp", "pk", "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(false));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", "user", "phrase", null, "pk", "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(false));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", "user", "phrase", "fp", null, "pkp", null))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(true));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", "user", "phrase", "fp", "pk", null, "region"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(true));
+
+ config = createTestConfig(ociAuthSimpleConfig("tenant", "user", "phrase", "fp", null, null, "region"))
+ .get(OciConfig.CONFIG_KEY);
+ cfg = OciConfig.create(config);
+ assertThat(cfg.simpleConfigIsPresent(),
+ is(false));
+ }
+
+ @Test
+ void defaultOciConfigAttributes() {
+ assertThat(OciExtension.ociConfig().authKeyFile(),
+ equalTo("oci_api_key.pem"));
+ assertThat(OciExtension.ociConfig().imdsHostName(),
+ equalTo(OciConfig.IMDS_HOSTNAME));
+ assertThat(OciExtension.ociConfig().imdsTimeout().toMillis(),
+ equalTo(100L));
+ }
+
+ @Test
+ void ociYamlConfigFile() {
+ // setup (tear down happens after each run)
+ OciExtension.ociConfigFileName("test-oci-resource-principal.yaml");
+
+ OciConfig ociConfig = OciExtension.ociConfig();
+ assertThat(ociConfig.authStrategy(),
+ optionalValue(equalTo("resource-principal")));
+
+ // note that we can't actually instantiate these when there is no auth provider configured in the environment
+ IllegalArgumentException e = assertThrows(java.lang.IllegalArgumentException.class,
+ () -> OciExtension.ociAuthenticationProvider().get());
+ assertThat(e.getMessage(),
+ equalTo(OciAuthenticationDetailsProvider.TAG_RESOURCE_PRINCIPAL_VERSION + " environment variable missing"));
+ assertThat(OciExtension.configuredAuthenticationDetailsProvider(false),
+ equalTo(ResourcePrincipalAuthenticationDetailsProvider.class));
+
+ OciExtension.ociConfigFileName("test-oci-config-file.yaml");
+ Supplier extends AbstractAuthenticationDetailsProvider> authProvider = OciExtension.ociAuthenticationProvider();
+
+ try {
+ // in the case where there is actually an oci configuration in this environment
+ AbstractAuthenticationDetailsProvider auth = authProvider.get();
+ assertThat(auth,
+ instanceOf(ConfigFileAuthenticationDetailsProvider.class));
+ assertThat(OciExtension.configuredAuthenticationDetailsProvider(true),
+ equalTo(ConfigFileAuthenticationDetailsProvider.class));
+ assertThat(OciExtension.configuredAuthenticationDetailsProvider(false),
+ equalTo(ConfigFileAuthenticationDetailsProvider.class));
+ } catch (NoSuchElementException ispe) {
+ assertThat(ispe.getMessage(),
+ equalTo("No instances of com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider available for use. "
+ + "Verify your configuration named: oci"));
+ assertThat(OciExtension.configuredAuthenticationDetailsProvider(false),
+ equalTo(ConfigFileAuthenticationDetailsProvider.class));
+ }
+ }
+
+ @Test
+ void ociRawConfigShouldBeCached() {
+ assertSame(Objects.requireNonNull(OciExtension.configSupplier()),
+ OciExtension.configSupplier(),
+ "The oci configuration from the config source should be cached");
+ }
+
+ static Config createTestConfig(MapConfigSource.Builder... builders) {
+ return Config.builder(builders)
+ .disableEnvironmentVariablesSource()
+ .disableSystemPropertiesSource()
+ .build();
+ }
+
+ static MapConfigSource.Builder ociAuthConfigStrategies(String strategy,
+ String... strategies) {
+ Map map = new HashMap<>();
+ if (strategy != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth-strategy", strategy);
+ }
+ if (strategies != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth-strategies", String.join(",", strategies));
+ }
+ return ConfigSources.create(map, "config-oci-auth-strategies");
+ }
+
+ static MapConfigSource.Builder ociAuthConfigFile(String configPath,
+ String profile) {
+ Map map = new HashMap<>();
+ if (configPath != null) {
+ map.put(OciConfig.CONFIG_KEY + ".config.path", configPath);
+ }
+ if (profile != null) {
+ map.put(OciConfig.CONFIG_KEY + ".config.profile", String.join(",", profile));
+ }
+ return ConfigSources.create(map, "config-oci-auth-config");
+ }
+
+ static MapConfigSource.Builder ociAuthSimpleConfig(String tenantId,
+ String userId,
+ String passPhrase,
+ String fingerPrint,
+ String privateKey,
+ String privateKeyPath,
+ String region) {
+ Map map = new HashMap<>();
+ if (tenantId != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.tenant-id", tenantId);
+ }
+ if (userId != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.user-id", userId);
+ }
+ if (passPhrase != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.passphrase", passPhrase);
+ }
+ if (fingerPrint != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.fingerprint", fingerPrint);
+ }
+ if (privateKey != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.private-key", privateKey);
+ }
+ if (privateKeyPath != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.private-key-path", privateKeyPath);
+ }
+ if (region != null) {
+ map.put(OciConfig.CONFIG_KEY + ".auth.region", region);
+ }
+ return ConfigSources.create(map, "config-oci-auth-simple");
+ }
+
+}
diff --git a/integrations/oci/sdk/runtime/src/test/resources/test-oci-config-file.yaml b/integrations/oci/sdk/runtime/src/test/resources/test-oci-config-file.yaml
new file mode 100644
index 00000000000..c03f5d6e2c0
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/test/resources/test-oci-config-file.yaml
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2023 Oracle and/or its affiliates.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# should resolve to "config-file" as the configured (by probably not available) auth strategy
+auth-strategies: ["config-file", "resource-principal", "config", "instance-principals"]
diff --git a/integrations/oci/sdk/runtime/src/test/resources/test-oci-resource-principal.yaml b/integrations/oci/sdk/runtime/src/test/resources/test-oci-resource-principal.yaml
new file mode 100644
index 00000000000..dff6ca17bd7
--- /dev/null
+++ b/integrations/oci/sdk/runtime/src/test/resources/test-oci-resource-principal.yaml
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2023 Oracle and/or its affiliates.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+auth-strategy: "resource-principal"