diff --git a/etc/copyright-exclude.txt b/etc/copyright-exclude.txt
index cf1dcc364f8..47723733b56 100644
--- a/etc/copyright-exclude.txt
+++ b/etc/copyright-exclude.txt
@@ -30,6 +30,7 @@ jaxb.index
/MANIFEST.MF
/README
/CONTRIBUTING.md
+.crt
.pem
.p8
.pkcs8.pem
diff --git a/integrations/oci/authentication/README.md b/integrations/oci/authentication/README.md
index a4bda918363..2097b71ff06 100644
--- a/integrations/oci/authentication/README.md
+++ b/integrations/oci/authentication/README.md
@@ -11,7 +11,7 @@ Helidon supports the following Authentication Methods:
- `config-file`: based on OCI config file
- `instance-principal`: instance principal (Such as an OCI VM)
- `resource-prinicpal`: resource principal (Such as server-less functions)
-- `workload`: workload running on a k8s cluster
+- `oke-workload-identity`: identity of workload running on a k8s cluster
The first two types are always available through `helidon-integrations-oci` module.
-Instance, resource, and workload support can be added through modules in this project module.
\ No newline at end of file
+Instance, resource, and workload support can be added through modules in this project module.
diff --git a/integrations/oci/authentication/instance/pom.xml b/integrations/oci/authentication/instance/pom.xml
index fcff26ab150..031fe76a77b 100644
--- a/integrations/oci/authentication/instance/pom.xml
+++ b/integrations/oci/authentication/instance/pom.xml
@@ -63,6 +63,16 @@
slf4j-jdk14
test
+
+ io.helidon.webserver.testing.junit5
+ helidon-webserver-testing-junit5
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
diff --git a/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/AuthenticationMethodInstancePrincipal.java b/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/AuthenticationMethodInstancePrincipal.java
index 0fadf2913b8..662b9b841f1 100644
--- a/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/AuthenticationMethodInstancePrincipal.java
+++ b/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/AuthenticationMethodInstancePrincipal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -17,6 +17,7 @@
package io.helidon.integrations.oci.authentication.instance;
import java.util.Optional;
+import java.util.function.Supplier;
import io.helidon.common.LazyValue;
import io.helidon.common.Weight;
@@ -42,7 +43,7 @@ class AuthenticationMethodInstancePrincipal implements OciAuthenticationMethod {
private final LazyValue> provider;
AuthenticationMethodInstancePrincipal(OciConfig config,
- InstancePrincipalsAuthenticationDetailsProviderBuilder builder) {
+ Supplier> builder) {
provider = createProvider(config, builder);
}
@@ -58,10 +59,11 @@ public Optional provider() {
private static LazyValue>
createProvider(OciConfig config,
- InstancePrincipalsAuthenticationDetailsProviderBuilder builder) {
+ Supplier> builder) {
return LazyValue.create(() -> {
if (HelidonOci.imdsAvailable(config)) {
- return Optional.of(builder.build());
+ return builder.get()
+ .map(InstancePrincipalsAuthenticationDetailsProviderBuilder::build);
}
if (LOGGER.isLoggable(System.Logger.Level.TRACE)) {
LOGGER.log(System.Logger.Level.TRACE, "OCI Metadata service is not available, "
diff --git a/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/InstancePrincipalBuilderProvider.java b/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/InstancePrincipalBuilderProvider.java
index 433c6d03a34..5698a238dfa 100644
--- a/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/InstancePrincipalBuilderProvider.java
+++ b/integrations/oci/authentication/instance/src/main/java/io/helidon/integrations/oci/authentication/instance/InstancePrincipalBuilderProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -39,8 +39,8 @@ class InstancePrincipalBuilderProvider implements Supplier registry.get(BasicAuthenticationDetailsProvider.class));
+ assertThat(thrown.getMessage(),
+ containsString(MockedInstancePrincipalBuilderProvider.INSTANCE_PRINCIPAL_INSTANTIATION_MESSAGE));
+
+ // The following validation indicates that the instance principal provider has been configured properly
+ assertThat(MockedAuthenticationMethodInstancePrincipal.getBuilder().getMetadataBaseUrl(), is(imdsBaseUri));
+ assertThat(MockedAuthenticationMethodInstancePrincipal.getBuilder().getFederationEndpoint(), is(FEDERATION_ENDPOINT));
+ assertThat(MockedAuthenticationMethodInstancePrincipal.getBuilder().getTenancyId(), is(TENANT_ID));
+ }
+
+ public static class ImdsEmulator {
+ // This will allow HelidonOci.imdsAvailable() to be tested by making the server that simulates IMDS to return a JSON value
+ // when instance property is queried
+ private static final String IMDS_INSTANCE_RESPONSE = """
+ {
+ "displayName": "helidon-server"
+ }
+ """;
+
+ private static void emulateImdsInstance(ServerRequest req, ServerResponse res) {
+ res.send(IMDS_INSTANCE_RESPONSE);
+ }
+ }
+}
diff --git a/integrations/oci/authentication/instance/src/test/java/io/helidon/integrations/oci/authentication/instance/MockedAuthenticationMethodInstancePrincipal.java b/integrations/oci/authentication/instance/src/test/java/io/helidon/integrations/oci/authentication/instance/MockedAuthenticationMethodInstancePrincipal.java
new file mode 100644
index 00000000000..2e9e0e9610a
--- /dev/null
+++ b/integrations/oci/authentication/instance/src/test/java/io/helidon/integrations/oci/authentication/instance/MockedAuthenticationMethodInstancePrincipal.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 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.authentication.instance;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import io.helidon.common.Weight;
+import io.helidon.common.Weighted;
+import io.helidon.integrations.oci.OciConfig;
+import io.helidon.service.registry.Service;
+
+import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder;
+
+@Weight(Weighted.DEFAULT_WEIGHT)
+@Service.Provider
+class MockedAuthenticationMethodInstancePrincipal extends AuthenticationMethodInstancePrincipal {
+
+ private static InstancePrincipalsAuthenticationDetailsProviderBuilder providerBuilder;
+
+ MockedAuthenticationMethodInstancePrincipal(OciConfig config,
+ Supplier>
+ builder) {
+ super(config, builder);
+ providerBuilder = builder.get().get();
+ }
+
+ static InstancePrincipalsAuthenticationDetailsProviderBuilder getBuilder() {
+ return providerBuilder;
+ }
+}
diff --git a/integrations/oci/authentication/instance/src/test/java/io/helidon/integrations/oci/authentication/instance/MockedInstancePrincipalBuilderProvider.java b/integrations/oci/authentication/instance/src/test/java/io/helidon/integrations/oci/authentication/instance/MockedInstancePrincipalBuilderProvider.java
new file mode 100644
index 00000000000..332a77d5bf7
--- /dev/null
+++ b/integrations/oci/authentication/instance/src/test/java/io/helidon/integrations/oci/authentication/instance/MockedInstancePrincipalBuilderProvider.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2025 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.authentication.instance;
+
+import java.util.function.Supplier;
+
+import io.helidon.common.Weight;
+import io.helidon.common.Weighted;
+import io.helidon.integrations.oci.OciConfig;
+import io.helidon.service.registry.Service;
+
+import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+@Weight(Weighted.DEFAULT_WEIGHT + 10)
+@Service.Provider
+class MockedInstancePrincipalBuilderProvider extends InstancePrincipalBuilderProvider
+ implements Supplier {
+ static final String INSTANCE_PRINCIPAL_INSTANTIATION_MESSAGE = "Instance Principal has been instantiated";
+ private String metadataBaseUrl = null;
+ private String tenancyID = null;
+ private String federationEndpoint = null;
+
+ MockedInstancePrincipalBuilderProvider(OciConfig config) {
+ super(config);
+ }
+
+ @Override
+ InstancePrincipalsAuthenticationDetailsProviderBuilder getBuilder() {
+ // Mock the InstancePrincipalsAuthenticationDetailsProviderBuilder
+ final InstancePrincipalsAuthenticationDetailsProviderBuilder builder =
+ mock(InstancePrincipalsAuthenticationDetailsProviderBuilder.class);
+
+ doAnswer(invocation -> {
+ throw new IllegalArgumentException(INSTANCE_PRINCIPAL_INSTANTIATION_MESSAGE);
+ }).when(builder).build();
+
+ // Process metadataBaseUrl
+ doAnswer(invocation -> {
+ metadataBaseUrl = invocation.getArgument(0);
+ return null;
+ }).when(builder).metadataBaseUrl(any());
+ doAnswer(invocation -> {
+ return metadataBaseUrl;
+ }).when(builder).getMetadataBaseUrl();
+
+ // Process federationEndpoint
+ doAnswer(invocation -> {
+ federationEndpoint = invocation.getArgument(0);
+ return null;
+ }).when(builder).federationEndpoint(any());
+ doAnswer(invocation -> {
+ return federationEndpoint;
+ }).when(builder).getFederationEndpoint();
+
+ // Process tenancyId
+ doAnswer(invocation -> {
+ tenancyID = invocation.getArgument(0);
+ return null;
+ }).when(builder).tenancyId(any());
+ doAnswer(invocation -> {
+ return tenancyID;
+ }).when(builder).getTenancyId();
+
+ return builder;
+ }
+}
diff --git a/integrations/oci/authentication/oke-workload/pom.xml b/integrations/oci/authentication/oke-workload/pom.xml
index 233fb9f03a2..c288de33ddb 100644
--- a/integrations/oci/authentication/oke-workload/pom.xml
+++ b/integrations/oci/authentication/oke-workload/pom.xml
@@ -67,6 +67,11 @@
slf4j-jdk14
test
+
+ com.oracle.oci.sdk
+ oci-java-sdk-common-httpclient-jersey3
+ test
+
@@ -111,6 +116,18 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+ ${project.build.testResources[0].directory}/dummy-ca.crt
+
+
+
diff --git a/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkload.java b/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkload.java
index da25de69241..0910f0a5e46 100644
--- a/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkload.java
+++ b/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkload.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -21,22 +21,22 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
+import java.util.function.Supplier;
import io.helidon.common.LazyValue;
import io.helidon.common.Weight;
import io.helidon.common.Weighted;
-import io.helidon.integrations.oci.OciConfig;
import io.helidon.integrations.oci.spi.OciAuthenticationMethod;
import io.helidon.service.registry.Service;
import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
-import com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider.OkeWorkloadIdentityAuthenticationDetailsProviderBuilder;
/**
- * Instance principal authentication method, uses the
- * {@link com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider}.
+ * OKE workload identity authentication method, uses the
+ * {@link com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider}.
*/
-@Weight(Weighted.DEFAULT_WEIGHT - 40)
+@Weight(Weighted.DEFAULT_WEIGHT - 50)
@Service.Provider
class AuthenticationMethodOkeWorkload implements OciAuthenticationMethod {
private static final System.Logger LOGGER = System.getLogger(AuthenticationMethodOkeWorkload.class.getName());
@@ -53,8 +53,8 @@ class AuthenticationMethodOkeWorkload implements OciAuthenticationMethod {
private final LazyValue> provider;
- AuthenticationMethodOkeWorkload(OciConfig config) {
- provider = createProvider(config);
+ AuthenticationMethodOkeWorkload(Supplier> builder) {
+ provider = createProvider(builder);
}
@Override
@@ -67,11 +67,12 @@ public Optional provider() {
return provider.get();
}
- private static LazyValue> createProvider(OciConfig config) {
+ private static LazyValue> createProvider(
+ Supplier> builder) {
return LazyValue.create(() -> {
if (available()) {
- return Optional.of(OkeWorkloadIdentityAuthenticationDetailsProvider.builder()
- .build());
+ return builder.get()
+ .map(OkeWorkloadIdentityAuthenticationDetailsProviderBuilder::build);
}
return Optional.empty();
diff --git a/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/OkeWorkloadBuilderProvider.java b/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/OkeWorkloadBuilderProvider.java
index 3050e035e51..031238b826e 100644
--- a/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/OkeWorkloadBuilderProvider.java
+++ b/integrations/oci/authentication/oke-workload/src/main/java/io/helidon/integrations/oci/authentication/okeworkload/OkeWorkloadBuilderProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -26,7 +26,7 @@
import com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider.OkeWorkloadIdentityAuthenticationDetailsProviderBuilder;
/**
- * OKE Workload builder provider, uses the
+ * OKE Workload Identity builder provider, uses the
* {@link OkeWorkloadIdentityAuthenticationDetailsProviderBuilder}.
*/
@Service.Provider
@@ -50,6 +50,8 @@ public OkeWorkloadIdentityAuthenticationDetailsProviderBuilder get() {
config.imdsBaseUri()
.map(URI::toString)
.ifPresent(builder::metadataBaseUrl);
+ config.tenantId()
+ .ifPresent(builder::tenancyId);
return builder;
}
diff --git a/integrations/oci/authentication/oke-workload/src/test/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkloadTest.java b/integrations/oci/authentication/oke-workload/src/test/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkloadTest.java
new file mode 100644
index 00000000000..0cdbf5d77c3
--- /dev/null
+++ b/integrations/oci/authentication/oke-workload/src/test/java/io/helidon/integrations/oci/authentication/okeworkload/AuthenticationMethodOkeWorkloadTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2025 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.authentication.okeworkload;
+
+import java.util.Properties;
+
+import io.helidon.service.registry.ServiceRegistry;
+import io.helidon.service.registry.ServiceRegistryManager;
+
+import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class AuthenticationMethodOkeWorkloadTest {
+ private static ServiceRegistryManager registryManager;
+ private static ServiceRegistry registry;
+
+ void setUp(Properties p) {
+ p.put("helidon.oci.authentication-method", "oke-workload-identity");
+ System.setProperties(p);
+
+ registryManager = ServiceRegistryManager.create();
+ registry = registryManager.registry();
+ }
+
+ @AfterEach
+ void cleanUp() {
+ registry = null;
+ if (registryManager != null) {
+ registryManager.shutdown();
+ }
+ }
+
+ @Test
+ public void testOkeWorkloadIdentityConfigurationAndInstantiation() {
+ final String FEDERATION_ENDPOINT = "https://auth.us-myregion-1.oraclecloud.com";
+ final String TENANT_ID = "ocid1.tenancy.oc1..mytenancyid";
+
+ Properties p = System.getProperties();
+ p.put("helidon.oci.federation-endpoint", FEDERATION_ENDPOINT);
+ p.put("helidon.oci.tenant-id", TENANT_ID);
+ setUp(p);
+
+ // This error indicates that the oke-workload-identity provider has been instantiated
+ var thrown = assertThrows(IllegalArgumentException.class,
+ () -> registry.get(BasicAuthenticationDetailsProvider.class));
+ assertThat(thrown.getMessage(), containsString("Invalid Kubernetes ca certification"));
+ // The following validation indicates that the oke-workload-identity provider has been configured properly
+ assertThat(MockedAuthenticationMethodOkeWorkload.getBuilder().getFederationEndpoint(), is(FEDERATION_ENDPOINT));
+ assertThat(MockedAuthenticationMethodOkeWorkload.getBuilder().getTenancyId(), is(TENANT_ID));
+ }
+}
diff --git a/integrations/oci/authentication/oke-workload/src/test/java/io/helidon/integrations/oci/authentication/okeworkload/MockedAuthenticationMethodOkeWorkload.java b/integrations/oci/authentication/oke-workload/src/test/java/io/helidon/integrations/oci/authentication/okeworkload/MockedAuthenticationMethodOkeWorkload.java
new file mode 100644
index 00000000000..3c79f3c4fc4
--- /dev/null
+++ b/integrations/oci/authentication/oke-workload/src/test/java/io/helidon/integrations/oci/authentication/okeworkload/MockedAuthenticationMethodOkeWorkload.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2025 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.authentication.okeworkload;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import io.helidon.common.Weight;
+import io.helidon.common.Weighted;
+import io.helidon.service.registry.Service;
+
+import com.oracle.bmc.auth.okeworkloadidentity
+ .OkeWorkloadIdentityAuthenticationDetailsProvider.OkeWorkloadIdentityAuthenticationDetailsProviderBuilder;
+
+@Service.Provider
+class MockedAuthenticationMethodOkeWorkload extends AuthenticationMethodOkeWorkload {
+
+ private static OkeWorkloadIdentityAuthenticationDetailsProviderBuilder providerBuilder;
+
+ MockedAuthenticationMethodOkeWorkload(Supplier> builder) {
+ super(builder);
+ providerBuilder = builder.get().get();
+ }
+
+ static OkeWorkloadIdentityAuthenticationDetailsProviderBuilder getBuilder() {
+ return providerBuilder;
+ }
+}
diff --git a/integrations/oci/authentication/oke-workload/src/test/resources/dummy-ca.crt b/integrations/oci/authentication/oke-workload/src/test/resources/dummy-ca.crt
new file mode 100644
index 00000000000..653150c6a22
--- /dev/null
+++ b/integrations/oci/authentication/oke-workload/src/test/resources/dummy-ca.crt
@@ -0,0 +1,4 @@
+NOTICE:
+=======
+This file represents a dummy ca.crt that will be used by the AuthenticationMethodOkeWorkload to validate if it can proceed with
+authentication processing.
diff --git a/integrations/oci/authentication/resource/pom.xml b/integrations/oci/authentication/resource/pom.xml
index 89b90c668da..74d32e8f585 100644
--- a/integrations/oci/authentication/resource/pom.xml
+++ b/integrations/oci/authentication/resource/pom.xml
@@ -107,6 +107,18 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+ 2.2
+
+
+
diff --git a/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipal.java b/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipal.java
index 32d356c9779..2cdc21cbbc1 100644
--- a/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipal.java
+++ b/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -18,6 +18,7 @@
import java.lang.System.Logger.Level;
import java.util.Optional;
+import java.util.function.Supplier;
import io.helidon.common.LazyValue;
import io.helidon.common.Weight;
@@ -42,7 +43,7 @@ class AuthenticationMethodResourcePrincipal implements OciAuthenticationMethod {
private final LazyValue> provider;
- AuthenticationMethodResourcePrincipal(ResourcePrincipalAuthenticationDetailsProviderBuilder builder) {
+ AuthenticationMethodResourcePrincipal(Supplier> builder) {
provider = createProvider(builder);
}
@@ -57,7 +58,7 @@ public Optional provider() {
}
private static LazyValue>
- createProvider(ResourcePrincipalAuthenticationDetailsProviderBuilder builder) {
+ createProvider(Supplier> builder) {
return LazyValue.create(() -> {
// https://github.com/oracle/oci-java-sdk/blob/v2.19.0/bmc-common/src/main/java/com/oracle/bmc/auth/ResourcePrincipalAuthenticationDetailsProvider.java#L246-L251
@@ -68,7 +69,8 @@ public Optional provider() {
}
return Optional.empty();
}
- return Optional.of(builder.build());
+ return builder.get()
+ .map(ResourcePrincipalAuthenticationDetailsProviderBuilder::build);
});
}
}
diff --git a/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/ResourcePrincipalBuilderProvider.java b/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/ResourcePrincipalBuilderProvider.java
index 9c3de7bf512..b4471d9aeb9 100644
--- a/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/ResourcePrincipalBuilderProvider.java
+++ b/integrations/oci/authentication/resource/src/main/java/io/helidon/integrations/oci/authentication/resource/ResourcePrincipalBuilderProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -50,6 +50,8 @@ public ResourcePrincipalAuthenticationDetailsProviderBuilder get() {
config.imdsBaseUri()
.map(URI::toString)
.ifPresent(builder::metadataBaseUrl);
+ config.tenantId()
+ .ifPresent(builder::tenancyId);
return builder;
}
diff --git a/integrations/oci/authentication/resource/src/test/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipalTest.java b/integrations/oci/authentication/resource/src/test/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipalTest.java
new file mode 100644
index 00000000000..166ad470f67
--- /dev/null
+++ b/integrations/oci/authentication/resource/src/test/java/io/helidon/integrations/oci/authentication/resource/AuthenticationMethodResourcePrincipalTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2025 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.authentication.resource;
+
+import java.util.Properties;
+
+import io.helidon.service.registry.ServiceRegistry;
+import io.helidon.service.registry.ServiceRegistryManager;
+
+import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class AuthenticationMethodResourcePrincipalTest {
+ private static ServiceRegistryManager registryManager;
+ private static ServiceRegistry registry;
+
+ void setUp(Properties p) {
+ p.put("helidon.oci.authentication-method", "resource-principal");
+ System.setProperties(p);
+
+ registryManager = ServiceRegistryManager.create();
+ registry = registryManager.registry();
+ }
+
+ @AfterEach
+ void cleanUp() {
+ registry = null;
+ if (registryManager != null) {
+ registryManager.shutdown();
+ }
+ }
+
+ @Test
+ public void testResourcePrincipalConfigurationAndInstantiation() {
+ final String FEDERATION_ENDPOINT = "https://auth.us-myregion-1.oraclecloud.com";
+ final String TENANT_ID = "ocid1.tenancy.oc1..mytenancyid";
+
+ Properties p = System.getProperties();
+ p.put("helidon.oci.federation-endpoint", FEDERATION_ENDPOINT);
+ p.put("helidon.oci.tenant-id", TENANT_ID);
+ setUp(p);
+
+ // This error indicates that the resource principal provider has been instantiated
+ var thrown = assertThrows(IllegalArgumentException.class,
+ () -> registry.get(BasicAuthenticationDetailsProvider.class));
+ assertThat(thrown.getMessage(),
+ containsString("Resource principals authentication can only be used in certain OCI services"));
+ // The following validation indicates that the resource principal provider has been configured properly
+ assertThat(MockedAuthenticationMethodResourcePrincipal.getBuilder().getFederationEndpoint(), is(FEDERATION_ENDPOINT));
+ assertThat(MockedAuthenticationMethodResourcePrincipal.getBuilder().getTenancyId(), is(TENANT_ID));
+ }
+}
diff --git a/integrations/oci/authentication/resource/src/test/java/io/helidon/integrations/oci/authentication/resource/MockedAuthenticationMethodResourcePrincipal.java b/integrations/oci/authentication/resource/src/test/java/io/helidon/integrations/oci/authentication/resource/MockedAuthenticationMethodResourcePrincipal.java
new file mode 100644
index 00000000000..bcc64a46abb
--- /dev/null
+++ b/integrations/oci/authentication/resource/src/test/java/io/helidon/integrations/oci/authentication/resource/MockedAuthenticationMethodResourcePrincipal.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2025 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.authentication.resource;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import io.helidon.common.Weight;
+import io.helidon.common.Weighted;
+import io.helidon.service.registry.Service;
+
+import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider.ResourcePrincipalAuthenticationDetailsProviderBuilder;
+
+@Service.Provider
+class MockedAuthenticationMethodResourcePrincipal extends AuthenticationMethodResourcePrincipal {
+
+ private static ResourcePrincipalAuthenticationDetailsProviderBuilder providerBuilder;
+
+ MockedAuthenticationMethodResourcePrincipal(Supplier> builder) {
+ super(builder);
+ providerBuilder = builder.get().get();
+ }
+
+ static ResourcePrincipalAuthenticationDetailsProviderBuilder getBuilder() {
+ return providerBuilder;
+ }
+}
diff --git a/integrations/oci/oci/README.md b/integrations/oci/oci/README.md
index 63c741b50e1..3239cec81ea 100644
--- a/integrations/oci/oci/README.md
+++ b/integrations/oci/oci/README.md
@@ -38,13 +38,14 @@ The provider is looked up by using instances of `io.helidon.integrations.oci.spi
The following out-of-the-box implementations exist:
-| Provider | Weight | Description |
-|--------------------|--------|---------------------------------------------------------------|
-| Config | 90 | Uses `OciConfig` |
-| Session Token | 85 | Uses `OciConfig` or config file, if it contains session token |
-| Config File | 80 | Uses `~/.oci/config` file |
-| Resource Principal | 70 | Resource principal (such as functions) |
-| Instance Principal | 60 | Principal of the compute instance |
+| Provider | Weight | Description |
+|-----------------------|--------|---------------------------------------------------------------|
+| Config | 90 | Uses `OciConfig` |
+| Session Token | 85 | Uses `OciConfig` or config file, if it contains session token |
+| Config File | 80 | Uses `~/.oci/config` file |
+| Resource Principal | 70 | Resource principal (such as functions) |
+| Instance Principal | 60 | Principal of the compute instance |
+| OKE Workload Identity | 50 | Identity of the OKE Workload |
To create a custom instance of authentication details provider, just create a new service for service registry
with default or higher weight that provides an instance of the `BasicAuthenticationDetailsProvider`
diff --git a/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigBlueprint.java b/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigBlueprint.java
index c736ecf8d10..ee52dc444da 100644
--- a/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigBlueprint.java
+++ b/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigBlueprint.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -72,8 +72,9 @@ interface OciConfigBlueprint {
* {@code instance-principal} - use identity of the OCI instance the service is running on, uses
* {@link com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider}, and is available in a
* separate module {@code helidon-integrations-oci-authentication-resource}
- * {@code workload} - use workload identity of the OCI Kubernetes workload, available in a
- * separate module {@code helidon-integrations-oci-authentication-workload}
+ * {@code oke-workload-identity} - use identity of the OCI Kubernetes workload, uses
+ * {@code com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider}, and is available in a
+ * separate module {@code helidon-integrations-oci-authentication-oke-workload}
*
*
* @return the authentication method to apply
@@ -161,8 +162,17 @@ interface OciConfigBlueprint {
*
* @return custom federation endpoint URI
*/
+ @Option.Configured
Optional federationEndpoint();
+ /**
+ * OCI tenant id for Instance Principal, Resource Principal or OKE Workload.
+ *
+ * @return the OCI tenant id
+ */
+ @Option.Configured
+ Optional tenantId();
+
/**
* Get the config used to update the builder.
*
diff --git a/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigProvider.java b/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigProvider.java
index 5d0771bc4d9..9adb5d306b3 100644
--- a/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigProvider.java
+++ b/integrations/oci/oci/src/main/java/io/helidon/integrations/oci/OciConfigProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 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.
@@ -31,6 +31,8 @@
@Weight(Weighted.DEFAULT_WEIGHT - 10)
class OciConfigProvider implements Supplier {
private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
+ private static final String CONFIG_PREFIX = "helidon.oci";
+ private static final System.Logger LOGGER = System.getLogger(AuthenticationMethodConfig.class.getName());
private static volatile OciConfig ociConfig;
OciConfigProvider() {
@@ -71,7 +73,14 @@ private static void create() {
ConfigSources.systemProperties(),
ConfigSources.file("oci-config.yaml").optional(true),
ConfigSources.classpath("oci-config.yaml").optional(true));
-
- ociConfig = OciConfig.create(config);
+ if (config.get(CONFIG_PREFIX).exists()) {
+ ociConfig = OciConfig.create(config.get(CONFIG_PREFIX));
+ } else {
+ ociConfig = OciConfig.create(config);
+ if (LOGGER.isLoggable(System.Logger.Level.TRACE)) {
+ LOGGER.log(System.Logger.Level.TRACE,
+ String.format("OCI Configuration needs to be prefixed with \"%s\"", CONFIG_PREFIX));
+ }
+ }
}
}
diff --git a/integrations/oci/oci/src/test/java/io/helidon/integrations/oci/OciConfigProviderTest.java b/integrations/oci/oci/src/test/java/io/helidon/integrations/oci/OciConfigProviderTest.java
new file mode 100644
index 00000000000..312acddfbbc
--- /dev/null
+++ b/integrations/oci/oci/src/test/java/io/helidon/integrations/oci/OciConfigProviderTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2025 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;
+
+import java.util.Properties;
+
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class OciConfigProviderTest {
+ @Test
+ void testConfig() {
+ final String FEDERATION_ENDPOINT = "https://auth.us-myregion-1.oraclecloud.com";
+ final String TENANT_ID = "ocid1.tenancy.oc1..mytenancyid";
+ final String REGION = "us-phoenix-1";
+ final String CONFIG_FILE_PATH = "/path1/path2/.oci/config";
+
+ Properties p = System.getProperties();
+ p.put("helidon.oci.authentication-method", AuthenticationMethodConfigFile.METHOD);
+ p.put("helidon.oci.federation-endpoint", FEDERATION_ENDPOINT);
+ p.put("helidon.oci.tenant-id", TENANT_ID);
+ p.put("HELIDON_OCI_REGION", REGION);
+ p.put("helidon.oci.authentication.config-file.path", CONFIG_FILE_PATH);
+ System.setProperties(p);
+
+ // clean up ociConfig from OciConfigProvider
+ OciConfigProvider.config(null);
+ var ociConfig = new OciConfigProvider().get();
+ assertThat(ociConfig.authenticationMethod(), is(AuthenticationMethodConfigFile.METHOD));
+ assertThat(ociConfig.federationEndpoint().get().toString(), is(FEDERATION_ENDPOINT));
+ assertThat(ociConfig.tenantId().get().toString(), is(TENANT_ID));
+ assertThat(ociConfig.region().get().getRegionId(), is(REGION));
+ assertThat(ociConfig.configFileMethodConfig().get().path().get(), is(CONFIG_FILE_PATH));
+ }
+}