From 0d513d4a4a4a69a0dab3d85dd3931f6765a0b735 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Thu, 10 Aug 2023 12:31:27 -0700 Subject: [PATCH] Addresses issue #4238 by introducing an OCI Secrets Retrieval API-using MicroProfile Config ConfigSource implementation, by way of a Helidon MpMetaConfigProvider Signed-off-by: Laird Nelson --- bom/pom.xml | 5 + dependencies/pom.xml | 2 +- etc/javadoc/oci/package-list | 533 ++++++++++++++++++ .../etc/spotbugs/exclude.xml | 24 + .../oci/oci-secrets-mp-config-source/pom.xml | 115 ++++ .../AbstractSecretBundleConfigSource.java | 222 ++++++++ .../secrets/mp/configsource/AdpSuppliers.java | 271 +++++++++ .../oci/secrets/mp/configsource/Guards.java | 62 ++ .../OciSecretsMpMetaConfigProvider.java | 142 +++++ .../SecretBundleByNameConfigSource.java | 36 ++ .../SecretBundleContentDetailsFunctions.java | 59 ++ .../mp/configsource/SecretsSuppliers.java | 56 ++ .../secrets/mp/configsource/Suppliers.java | 67 +++ .../secrets/mp/configsource/package-info.java | 23 + .../src/main/java/module-info.java | 36 ++ .../native-image.properties | 17 + .../mp/configsource/MetaConfigUsageTest.java | 36 ++ .../secrets/mp/configsource/UsageTest.java | 57 ++ .../src/test/resources/mp-meta-config.yaml | 6 + integrations/oci/pom.xml | 1 + pom.xml | 7 + 21 files changed, 1776 insertions(+), 1 deletion(-) create mode 100644 etc/javadoc/oci/package-list create mode 100644 integrations/oci/oci-secrets-mp-config-source/etc/spotbugs/exclude.xml create mode 100644 integrations/oci/oci-secrets-mp-config-source/pom.xml create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AbstractSecretBundleConfigSource.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AdpSuppliers.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Guards.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/OciSecretsMpMetaConfigProvider.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleByNameConfigSource.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleContentDetailsFunctions.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretsSuppliers.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Suppliers.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/package-info.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/java/module-info.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-oci-secrets-mp/native-image.properties create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/MetaConfigUsageTest.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/UsageTest.java create mode 100644 integrations/oci/oci-secrets-mp-config-source/src/test/resources/mp-meta-config.yaml diff --git a/bom/pom.xml b/bom/pom.xml index d19dbfced6e..94f1c01d661 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -276,6 +276,11 @@ helidon-config-hocon ${helidon.version} + + io.helidon.config + helidon-integrations-oci-secrets-mp-config-source + ${helidon.version} + io.helidon.config helidon-config-etcd diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 2a5d8ccf76a..96aa43ecb1e 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -130,7 +130,7 @@ 4.4.11 4.1.94.Final 0.0.19.Final - 3.21.0 + 3.23.0 21.3.0.0 19.3.0.0 3.14.9 diff --git a/etc/javadoc/oci/package-list b/etc/javadoc/oci/package-list new file mode 100644 index 00000000000..7b9d5d3c13b --- /dev/null +++ b/etc/javadoc/oci/package-list @@ -0,0 +1,533 @@ +com.oracle.bmc +com.oracle.bmc.accessgovernancecp +com.oracle.bmc.accessgovernancecp.model +com.oracle.bmc.accessgovernancecp.requests +com.oracle.bmc.accessgovernancecp.responses +com.oracle.bmc.adm +com.oracle.bmc.adm.model +com.oracle.bmc.adm.requests +com.oracle.bmc.adm.responses +com.oracle.bmc.aianomalydetection +com.oracle.bmc.aianomalydetection.model +com.oracle.bmc.aianomalydetection.requests +com.oracle.bmc.aianomalydetection.responses +com.oracle.bmc.aidocument +com.oracle.bmc.aidocument.model +com.oracle.bmc.aidocument.requests +com.oracle.bmc.aidocument.responses +com.oracle.bmc.ailanguage +com.oracle.bmc.ailanguage.model +com.oracle.bmc.ailanguage.requests +com.oracle.bmc.ailanguage.responses +com.oracle.bmc.aispeech +com.oracle.bmc.aispeech.model +com.oracle.bmc.aispeech.requests +com.oracle.bmc.aispeech.responses +com.oracle.bmc.aivision +com.oracle.bmc.aivision.model +com.oracle.bmc.aivision.requests +com.oracle.bmc.aivision.responses +com.oracle.bmc.analytics +com.oracle.bmc.analytics.model +com.oracle.bmc.analytics.requests +com.oracle.bmc.analytics.responses +com.oracle.bmc.announcementsservice +com.oracle.bmc.announcementsservice.model +com.oracle.bmc.announcementsservice.requests +com.oracle.bmc.announcementsservice.responses +com.oracle.bmc.apigateway +com.oracle.bmc.apigateway.model +com.oracle.bmc.apigateway.requests +com.oracle.bmc.apigateway.responses +com.oracle.bmc.apmconfig +com.oracle.bmc.apmconfig.model +com.oracle.bmc.apmconfig.requests +com.oracle.bmc.apmconfig.responses +com.oracle.bmc.apmcontrolplane +com.oracle.bmc.apmcontrolplane.model +com.oracle.bmc.apmcontrolplane.requests +com.oracle.bmc.apmcontrolplane.responses +com.oracle.bmc.apmsynthetics +com.oracle.bmc.apmsynthetics.model +com.oracle.bmc.apmsynthetics.requests +com.oracle.bmc.apmsynthetics.responses +com.oracle.bmc.apmtraces +com.oracle.bmc.apmtraces.model +com.oracle.bmc.apmtraces.requests +com.oracle.bmc.apmtraces.responses +com.oracle.bmc.applicationmigration +com.oracle.bmc.applicationmigration.model +com.oracle.bmc.applicationmigration.requests +com.oracle.bmc.applicationmigration.responses +com.oracle.bmc.appmgmtcontrol +com.oracle.bmc.appmgmtcontrol.model +com.oracle.bmc.appmgmtcontrol.requests +com.oracle.bmc.appmgmtcontrol.responses +com.oracle.bmc.artifacts +com.oracle.bmc.artifacts.model +com.oracle.bmc.artifacts.requests +com.oracle.bmc.artifacts.responses +com.oracle.bmc.audit +com.oracle.bmc.audit.model +com.oracle.bmc.audit.requests +com.oracle.bmc.audit.responses +com.oracle.bmc.auth +com.oracle.bmc.auth.exception +com.oracle.bmc.auth.internal +com.oracle.bmc.autoscaling +com.oracle.bmc.autoscaling.model +com.oracle.bmc.autoscaling.requests +com.oracle.bmc.autoscaling.responses +com.oracle.bmc.bastion +com.oracle.bmc.bastion.model +com.oracle.bmc.bastion.requests +com.oracle.bmc.bastion.responses +com.oracle.bmc.bds +com.oracle.bmc.bds.model +com.oracle.bmc.bds.requests +com.oracle.bmc.bds.responses +com.oracle.bmc.blockchain +com.oracle.bmc.blockchain.model +com.oracle.bmc.blockchain.requests +com.oracle.bmc.blockchain.responses +com.oracle.bmc.budget +com.oracle.bmc.budget.model +com.oracle.bmc.budget.requests +com.oracle.bmc.budget.responses +com.oracle.bmc.certificates +com.oracle.bmc.certificates.model +com.oracle.bmc.certificates.requests +com.oracle.bmc.certificates.responses +com.oracle.bmc.certificatesmanagement +com.oracle.bmc.certificatesmanagement.model +com.oracle.bmc.certificatesmanagement.requests +com.oracle.bmc.certificatesmanagement.responses +com.oracle.bmc.cims +com.oracle.bmc.cims.model +com.oracle.bmc.cims.requests +com.oracle.bmc.cims.responses +com.oracle.bmc.circuitbreaker +com.oracle.bmc.cloudbridge +com.oracle.bmc.cloudbridge.model +com.oracle.bmc.cloudbridge.requests +com.oracle.bmc.cloudbridge.responses +com.oracle.bmc.cloudguard +com.oracle.bmc.cloudguard.model +com.oracle.bmc.cloudguard.requests +com.oracle.bmc.cloudguard.responses +com.oracle.bmc.cloudmigrations +com.oracle.bmc.cloudmigrations.model +com.oracle.bmc.cloudmigrations.requests +com.oracle.bmc.cloudmigrations.responses +com.oracle.bmc.common +com.oracle.bmc.computeinstanceagent +com.oracle.bmc.computeinstanceagent.model +com.oracle.bmc.computeinstanceagent.requests +com.oracle.bmc.computeinstanceagent.responses +com.oracle.bmc.containerengine +com.oracle.bmc.containerengine.model +com.oracle.bmc.containerengine.requests +com.oracle.bmc.containerengine.responses +com.oracle.bmc.containerinstances +com.oracle.bmc.containerinstances.model +com.oracle.bmc.containerinstances.requests +com.oracle.bmc.containerinstances.responses +com.oracle.bmc.core +com.oracle.bmc.core.model +com.oracle.bmc.core.requests +com.oracle.bmc.core.responses +com.oracle.bmc.dashboardservice +com.oracle.bmc.dashboardservice.model +com.oracle.bmc.dashboardservice.requests +com.oracle.bmc.dashboardservice.responses +com.oracle.bmc.database +com.oracle.bmc.database.model +com.oracle.bmc.database.requests +com.oracle.bmc.database.responses +com.oracle.bmc.databasemanagement +com.oracle.bmc.databasemanagement.model +com.oracle.bmc.databasemanagement.requests +com.oracle.bmc.databasemanagement.responses +com.oracle.bmc.databasemigration +com.oracle.bmc.databasemigration.model +com.oracle.bmc.databasemigration.requests +com.oracle.bmc.databasemigration.responses +com.oracle.bmc.databasetools +com.oracle.bmc.databasetools.model +com.oracle.bmc.databasetools.requests +com.oracle.bmc.databasetools.responses +com.oracle.bmc.datacatalog +com.oracle.bmc.datacatalog.model +com.oracle.bmc.datacatalog.requests +com.oracle.bmc.datacatalog.responses +com.oracle.bmc.dataflow +com.oracle.bmc.dataflow.model +com.oracle.bmc.dataflow.requests +com.oracle.bmc.dataflow.responses +com.oracle.bmc.dataintegration +com.oracle.bmc.dataintegration.model +com.oracle.bmc.dataintegration.requests +com.oracle.bmc.dataintegration.responses +com.oracle.bmc.datalabelingservice +com.oracle.bmc.datalabelingservice.model +com.oracle.bmc.datalabelingservice.requests +com.oracle.bmc.datalabelingservice.responses +com.oracle.bmc.datalabelingservicedataplane +com.oracle.bmc.datalabelingservicedataplane.model +com.oracle.bmc.datalabelingservicedataplane.requests +com.oracle.bmc.datalabelingservicedataplane.responses +com.oracle.bmc.datasafe +com.oracle.bmc.datasafe.model +com.oracle.bmc.datasafe.requests +com.oracle.bmc.datasafe.responses +com.oracle.bmc.datascience +com.oracle.bmc.datascience.model +com.oracle.bmc.datascience.requests +com.oracle.bmc.datascience.responses +com.oracle.bmc.devops +com.oracle.bmc.devops.model +com.oracle.bmc.devops.requests +com.oracle.bmc.devops.responses +com.oracle.bmc.disasterrecovery +com.oracle.bmc.disasterrecovery.model +com.oracle.bmc.disasterrecovery.requests +com.oracle.bmc.disasterrecovery.responses +com.oracle.bmc.dns +com.oracle.bmc.dns.model +com.oracle.bmc.dns.requests +com.oracle.bmc.dns.responses +com.oracle.bmc.dts +com.oracle.bmc.dts.model +com.oracle.bmc.dts.requests +com.oracle.bmc.dts.responses +com.oracle.bmc.email +com.oracle.bmc.email.model +com.oracle.bmc.email.requests +com.oracle.bmc.email.responses +com.oracle.bmc.emwarehouse +com.oracle.bmc.emwarehouse.model +com.oracle.bmc.emwarehouse.requests +com.oracle.bmc.emwarehouse.responses +com.oracle.bmc.encryption +com.oracle.bmc.encryption.internal +com.oracle.bmc.events +com.oracle.bmc.events.model +com.oracle.bmc.events.requests +com.oracle.bmc.events.responses +com.oracle.bmc.filestorage +com.oracle.bmc.filestorage.model +com.oracle.bmc.filestorage.requests +com.oracle.bmc.filestorage.responses +com.oracle.bmc.fleetsoftwareupdate +com.oracle.bmc.fleetsoftwareupdate.model +com.oracle.bmc.fleetsoftwareupdate.requests +com.oracle.bmc.fleetsoftwareupdate.responses +com.oracle.bmc.functions +com.oracle.bmc.functions.model +com.oracle.bmc.functions.requests +com.oracle.bmc.functions.responses +com.oracle.bmc.fusionapps +com.oracle.bmc.fusionapps.model +com.oracle.bmc.fusionapps.requests +com.oracle.bmc.fusionapps.responses +com.oracle.bmc.genericartifactscontent +com.oracle.bmc.genericartifactscontent.model +com.oracle.bmc.genericartifactscontent.requests +com.oracle.bmc.genericartifactscontent.responses +com.oracle.bmc.goldengate +com.oracle.bmc.goldengate.model +com.oracle.bmc.goldengate.requests +com.oracle.bmc.goldengate.responses +com.oracle.bmc.governancerulescontrolplane +com.oracle.bmc.governancerulescontrolplane.model +com.oracle.bmc.governancerulescontrolplane.requests +com.oracle.bmc.governancerulescontrolplane.responses +com.oracle.bmc.healthchecks +com.oracle.bmc.healthchecks.model +com.oracle.bmc.healthchecks.requests +com.oracle.bmc.healthchecks.responses +com.oracle.bmc.helper +com.oracle.bmc.http +com.oracle.bmc.http.internal +com.oracle.bmc.http.signing +com.oracle.bmc.http.signing.internal +com.oracle.bmc.identity +com.oracle.bmc.identity.model +com.oracle.bmc.identity.requests +com.oracle.bmc.identity.responses +com.oracle.bmc.identitydataplane +com.oracle.bmc.identitydataplane.model +com.oracle.bmc.identitydataplane.requests +com.oracle.bmc.identitydataplane.responses +com.oracle.bmc.identitydomains +com.oracle.bmc.identitydomains.model +com.oracle.bmc.identitydomains.requests +com.oracle.bmc.identitydomains.responses +com.oracle.bmc.integration +com.oracle.bmc.integration.model +com.oracle.bmc.integration.requests +com.oracle.bmc.integration.responses +com.oracle.bmc.internal +com.oracle.bmc.io.internal +com.oracle.bmc.jms +com.oracle.bmc.jms.model +com.oracle.bmc.jms.requests +com.oracle.bmc.jms.responses +com.oracle.bmc.keymanagement +com.oracle.bmc.keymanagement.model +com.oracle.bmc.keymanagement.requests +com.oracle.bmc.keymanagement.responses +com.oracle.bmc.licensemanager +com.oracle.bmc.licensemanager.model +com.oracle.bmc.licensemanager.requests +com.oracle.bmc.licensemanager.responses +com.oracle.bmc.limits +com.oracle.bmc.limits.model +com.oracle.bmc.limits.requests +com.oracle.bmc.limits.responses +com.oracle.bmc.loadbalancer +com.oracle.bmc.loadbalancer.model +com.oracle.bmc.loadbalancer.requests +com.oracle.bmc.loadbalancer.responses +com.oracle.bmc.lockbox +com.oracle.bmc.lockbox.model +com.oracle.bmc.lockbox.requests +com.oracle.bmc.lockbox.responses +com.oracle.bmc.loganalytics +com.oracle.bmc.loganalytics.model +com.oracle.bmc.loganalytics.requests +com.oracle.bmc.loganalytics.responses +com.oracle.bmc.logging +com.oracle.bmc.logging.model +com.oracle.bmc.logging.requests +com.oracle.bmc.logging.responses +com.oracle.bmc.loggingingestion +com.oracle.bmc.loggingingestion.model +com.oracle.bmc.loggingingestion.requests +com.oracle.bmc.loggingingestion.responses +com.oracle.bmc.loggingsearch +com.oracle.bmc.loggingsearch.model +com.oracle.bmc.loggingsearch.requests +com.oracle.bmc.loggingsearch.responses +com.oracle.bmc.managementagent +com.oracle.bmc.managementagent.model +com.oracle.bmc.managementagent.requests +com.oracle.bmc.managementagent.responses +com.oracle.bmc.managementdashboard +com.oracle.bmc.managementdashboard.model +com.oracle.bmc.managementdashboard.requests +com.oracle.bmc.managementdashboard.responses +com.oracle.bmc.marketplace +com.oracle.bmc.marketplace.model +com.oracle.bmc.marketplace.requests +com.oracle.bmc.marketplace.responses +com.oracle.bmc.mediaservices +com.oracle.bmc.mediaservices.model +com.oracle.bmc.mediaservices.requests +com.oracle.bmc.mediaservices.responses +com.oracle.bmc.model +com.oracle.bmc.model.internal +com.oracle.bmc.monitoring +com.oracle.bmc.monitoring.model +com.oracle.bmc.monitoring.requests +com.oracle.bmc.monitoring.responses +com.oracle.bmc.mysql +com.oracle.bmc.mysql.model +com.oracle.bmc.mysql.requests +com.oracle.bmc.mysql.responses +com.oracle.bmc.networkfirewall +com.oracle.bmc.networkfirewall.model +com.oracle.bmc.networkfirewall.requests +com.oracle.bmc.networkfirewall.responses +com.oracle.bmc.networkloadbalancer +com.oracle.bmc.networkloadbalancer.model +com.oracle.bmc.networkloadbalancer.requests +com.oracle.bmc.networkloadbalancer.responses +com.oracle.bmc.nosql +com.oracle.bmc.nosql.model +com.oracle.bmc.nosql.requests +com.oracle.bmc.nosql.responses +com.oracle.bmc.objectstorage +com.oracle.bmc.objectstorage.internal +com.oracle.bmc.objectstorage.model +com.oracle.bmc.objectstorage.requests +com.oracle.bmc.objectstorage.responses +com.oracle.bmc.objectstorage.transfer +com.oracle.bmc.objectstorage.transfer.internal +com.oracle.bmc.oce +com.oracle.bmc.oce.model +com.oracle.bmc.oce.requests +com.oracle.bmc.oce.responses +com.oracle.bmc.ocicontrolcenter +com.oracle.bmc.ocicontrolcenter.model +com.oracle.bmc.ocicontrolcenter.requests +com.oracle.bmc.ocicontrolcenter.responses +com.oracle.bmc.ocvp +com.oracle.bmc.ocvp.model +com.oracle.bmc.ocvp.requests +com.oracle.bmc.ocvp.responses +com.oracle.bmc.oda +com.oracle.bmc.oda.model +com.oracle.bmc.oda.requests +com.oracle.bmc.oda.responses +com.oracle.bmc.onesubscription +com.oracle.bmc.onesubscription.model +com.oracle.bmc.onesubscription.requests +com.oracle.bmc.onesubscription.responses +com.oracle.bmc.ons +com.oracle.bmc.ons.model +com.oracle.bmc.ons.requests +com.oracle.bmc.ons.responses +com.oracle.bmc.opensearch +com.oracle.bmc.opensearch.model +com.oracle.bmc.opensearch.requests +com.oracle.bmc.opensearch.responses +com.oracle.bmc.operatoraccesscontrol +com.oracle.bmc.operatoraccesscontrol.model +com.oracle.bmc.operatoraccesscontrol.requests +com.oracle.bmc.operatoraccesscontrol.responses +com.oracle.bmc.opsi +com.oracle.bmc.opsi.model +com.oracle.bmc.opsi.requests +com.oracle.bmc.opsi.responses +com.oracle.bmc.optimizer +com.oracle.bmc.optimizer.model +com.oracle.bmc.optimizer.requests +com.oracle.bmc.optimizer.responses +com.oracle.bmc.osmanagement +com.oracle.bmc.osmanagement.model +com.oracle.bmc.osmanagement.requests +com.oracle.bmc.osmanagement.responses +com.oracle.bmc.osmanagementhub +com.oracle.bmc.osmanagementhub.model +com.oracle.bmc.osmanagementhub.requests +com.oracle.bmc.osmanagementhub.responses +com.oracle.bmc.ospgateway +com.oracle.bmc.ospgateway.model +com.oracle.bmc.ospgateway.requests +com.oracle.bmc.ospgateway.responses +com.oracle.bmc.osubbillingschedule +com.oracle.bmc.osubbillingschedule.model +com.oracle.bmc.osubbillingschedule.requests +com.oracle.bmc.osubbillingschedule.responses +com.oracle.bmc.osuborganizationsubscription +com.oracle.bmc.osuborganizationsubscription.model +com.oracle.bmc.osuborganizationsubscription.requests +com.oracle.bmc.osuborganizationsubscription.responses +com.oracle.bmc.osubsubscription +com.oracle.bmc.osubsubscription.model +com.oracle.bmc.osubsubscription.requests +com.oracle.bmc.osubsubscription.responses +com.oracle.bmc.osubusage +com.oracle.bmc.osubusage.model +com.oracle.bmc.osubusage.requests +com.oracle.bmc.osubusage.responses +com.oracle.bmc.paginator.internal +com.oracle.bmc.queue +com.oracle.bmc.queue.model +com.oracle.bmc.queue.requests +com.oracle.bmc.queue.responses +com.oracle.bmc.recovery +com.oracle.bmc.recovery.model +com.oracle.bmc.recovery.requests +com.oracle.bmc.recovery.responses +com.oracle.bmc.requests +com.oracle.bmc.resourcemanager +com.oracle.bmc.resourcemanager.model +com.oracle.bmc.resourcemanager.requests +com.oracle.bmc.resourcemanager.responses +com.oracle.bmc.resourcesearch +com.oracle.bmc.resourcesearch.model +com.oracle.bmc.resourcesearch.requests +com.oracle.bmc.resourcesearch.responses +com.oracle.bmc.responses +com.oracle.bmc.responses.internal +com.oracle.bmc.retrier +com.oracle.bmc.rover +com.oracle.bmc.rover.model +com.oracle.bmc.rover.requests +com.oracle.bmc.rover.responses +com.oracle.bmc.sch +com.oracle.bmc.sch.model +com.oracle.bmc.sch.requests +com.oracle.bmc.sch.responses +com.oracle.bmc.secrets +com.oracle.bmc.secrets.model +com.oracle.bmc.secrets.requests +com.oracle.bmc.secrets.responses +com.oracle.bmc.servicecatalog +com.oracle.bmc.servicecatalog.model +com.oracle.bmc.servicecatalog.requests +com.oracle.bmc.servicecatalog.responses +com.oracle.bmc.servicemanagerproxy +com.oracle.bmc.servicemanagerproxy.model +com.oracle.bmc.servicemanagerproxy.requests +com.oracle.bmc.servicemanagerproxy.responses +com.oracle.bmc.servicemesh +com.oracle.bmc.servicemesh.model +com.oracle.bmc.servicemesh.requests +com.oracle.bmc.servicemesh.responses +com.oracle.bmc.stackmonitoring +com.oracle.bmc.stackmonitoring.model +com.oracle.bmc.stackmonitoring.requests +com.oracle.bmc.stackmonitoring.responses +com.oracle.bmc.streaming +com.oracle.bmc.streaming.model +com.oracle.bmc.streaming.requests +com.oracle.bmc.streaming.responses +com.oracle.bmc.tenantmanagercontrolplane +com.oracle.bmc.tenantmanagercontrolplane.model +com.oracle.bmc.tenantmanagercontrolplane.requests +com.oracle.bmc.tenantmanagercontrolplane.responses +com.oracle.bmc.threatintelligence +com.oracle.bmc.threatintelligence.model +com.oracle.bmc.threatintelligence.requests +com.oracle.bmc.threatintelligence.responses +com.oracle.bmc.usage +com.oracle.bmc.usage.model +com.oracle.bmc.usage.requests +com.oracle.bmc.usage.responses +com.oracle.bmc.usageapi +com.oracle.bmc.usageapi.model +com.oracle.bmc.usageapi.requests +com.oracle.bmc.usageapi.responses +com.oracle.bmc.util +com.oracle.bmc.util.internal +com.oracle.bmc.vault +com.oracle.bmc.vault.model +com.oracle.bmc.vault.requests +com.oracle.bmc.vault.responses +com.oracle.bmc.vbsinst +com.oracle.bmc.vbsinst.model +com.oracle.bmc.vbsinst.requests +com.oracle.bmc.vbsinst.responses +com.oracle.bmc.visualbuilder +com.oracle.bmc.visualbuilder.model +com.oracle.bmc.visualbuilder.requests +com.oracle.bmc.visualbuilder.responses +com.oracle.bmc.vnmonitoring +com.oracle.bmc.vnmonitoring.model +com.oracle.bmc.vnmonitoring.requests +com.oracle.bmc.vnmonitoring.responses +com.oracle.bmc.vulnerabilityscanning +com.oracle.bmc.vulnerabilityscanning.model +com.oracle.bmc.vulnerabilityscanning.requests +com.oracle.bmc.vulnerabilityscanning.responses +com.oracle.bmc.waa +com.oracle.bmc.waa.model +com.oracle.bmc.waa.requests +com.oracle.bmc.waa.responses +com.oracle.bmc.waas +com.oracle.bmc.waas.model +com.oracle.bmc.waas.requests +com.oracle.bmc.waas.responses +com.oracle.bmc.waf +com.oracle.bmc.waf.model +com.oracle.bmc.waf.requests +com.oracle.bmc.waf.responses +com.oracle.bmc.waiter +com.oracle.bmc.waiter.internal +com.oracle.bmc.workrequests +com.oracle.bmc.workrequests.model +com.oracle.bmc.workrequests.requests +com.oracle.bmc.workrequests.responses diff --git a/integrations/oci/oci-secrets-mp-config-source/etc/spotbugs/exclude.xml b/integrations/oci/oci-secrets-mp-config-source/etc/spotbugs/exclude.xml new file mode 100644 index 00000000000..b14d464b9ef --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/etc/spotbugs/exclude.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/integrations/oci/oci-secrets-mp-config-source/pom.xml b/integrations/oci/oci-secrets-mp-config-source/pom.xml new file mode 100644 index 00000000000..1fbd99ce440 --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/pom.xml @@ -0,0 +1,115 @@ + + + + 4.0.0 + + io.helidon.integrations.oci + helidon-integrations-oci-project + 3.2.3-SNAPSHOT + + helidon-integrations-oci-secrets-mp-config-source + Helidon Config OCI Secrets MP + + + OCI Secrets Retrieval API Config Source Implementation + + + + etc/spotbugs/exclude.xml + + + + + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + org.apache.httpcomponents + httpcore + 4.4.16 + + + + + + + + + + io.helidon.common + helidon-common + + + io.helidon.config + helidon-config-mp + + + com.oracle.oci.sdk + oci-java-sdk-common + + + com.oracle.oci.sdk + oci-java-sdk-secrets + + + org.eclipse.microprofile.config + microprofile-config-api + + + + + + com.oracle.oci.sdk + oci-java-sdk-common-httpclient-jersey3 + runtime + + + + + + io.helidon.config + helidon-config-yaml-mp + test + + + org.hamcrest + hamcrest-core + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.slf4j + slf4j-jdk14 + test + + + + diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AbstractSecretBundleConfigSource.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AbstractSecretBundleConfigSource.java new file mode 100644 index 00000000000..91691e3ce30 --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AbstractSecretBundleConfigSource.java @@ -0,0 +1,222 @@ +/* + * 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.secrets.mp.configsource; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.oracle.bmc.secrets.Secrets; +import com.oracle.bmc.secrets.model.Base64SecretBundleContentDetails; +import com.oracle.bmc.secrets.model.SecretBundleContentDetails; +import org.eclipse.microprofile.config.spi.ConfigSource; + +/** + * An {@link AutoCloseable} {@link ConfigSource} that retrieves configuration property values from an Oracle Cloud + * Infrastructure Vault. + * + *

Although not {@code abstract}, this class is normally used as a superclass since it (deliberately) lacks a + * zero-argument {@code public} constructor, and so hence cannot be used as a Java {@linkplain java.util.ServiceLoader + * service provider}.

+ */ +@SuppressWarnings("try") +class AbstractSecretBundleConfigSource implements AutoCloseable, ConfigSource { + + + /* + * Instance fields. + */ + + + private final Function base64Decoder; + + private final Function f; + + private final Supplier closeableSupplier; + + + /* + * Constructors. + */ + + + /** + * Creates a new {@link AbstractSecretBundleConfigSource}. + * + * @param f a {@link Function} that accepts a configuration property name (a {@link String}) and returns a {@link + * SecretBundleContentDetails} object representing the value; must not be {@code null}; must be safe for concurrent + * use by multiple threads + * + * @param closeableSupplier a {@link Supplier} of an {@link AutoCloseable} typically supplying the {@link Secrets} + * typically used by the supplied {@link Function}; must not be {@code null}; its {@link Supplier#get()} method will + * be invoked when the {@link #close()} method is invoked, and {@link AutoCloseable#close()} will be invoked on its + * return value if the return value is non-{@code null} + * + * @see #AbstractSecretBundleConfigSource(Function, Supplier, Function) + */ + AbstractSecretBundleConfigSource(Function f, + Supplier closeableSupplier) { + this(f, closeableSupplier, null); + } + + /** + * Creates a new {@link AbstractSecretBundleConfigSource}. + * + * @param f a {@link Function} that accepts a configuration property name (a {@link String}) and returns a {@link + * SecretBundleContentDetails} object representing the value; must not be {@code null}; must be safe for concurrent + * use by multiple threads + * + * @param closeableSupplier a {@link Supplier} of an {@link AutoCloseable} typically supplying the {@link Secrets} + * typically used by the supplied {@link Function}; must not be {@code null}; its {@link Supplier#get()} method will + * be invoked when the {@link #close()} method is invoked, and {@link AutoCloseable#close()} will be invoked on its + * return value if the return value is non-{@code null} + * + * @param base64Decoder a {@link Function} that accepts a Base64-encoded {@link String} to decode and decodes it, + * returning the result; may be {@code null} in which case an implementation based on {@link Base64} will be used + * instead; if non-{@code null}, must be safe for concurrent use by multiple threads + */ + AbstractSecretBundleConfigSource(Function f, + Supplier closeableSupplier, + Function base64Decoder) { + super(); + this.f = Objects.requireNonNull(f, "f"); + this.closeableSupplier = Objects.requireNonNull(closeableSupplier, "closeableSupplier"); + if (base64Decoder == null) { + this.base64Decoder = s -> s == null ? null : new String(Base64.getDecoder().decode(s), StandardCharsets.UTF_8); + } else { + this.base64Decoder = base64Decoder; + } + } + + + /* + * Instance methods. + */ + + + /** + * Closes this {@link AbstractSecretBundleConfigSource}. + * + *

During an invocation of this method, the {@link Supplier#get()} method of the {@link Supplier} of {@link + * AutoCloseable} instances supplied at construction time will be invoked, and {@link AutoCloseable#close()} will be + * invoked on its return value, if the return value is non-{@code null}.

+ * + *

This method is, and overrides of this method must be, safe for concurrent use by multiple threads.

+ * + * @see #AbstractSecretBundleConfigSource(Function, Supplier, Function) + * + * @see AutoCloseable#close() + */ + @Override // AutoCloseable + public void close() { + AutoCloseable ac = this.closeableSupplier.get(); + if (ac != null) { + try { + ac.close(); + } catch (RuntimeException runtimeException) { + throw runtimeException; + } catch (Exception exception) { + if (exception instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + throw new IllegalStateException(exception.getMessage(), exception); + } + } + } + + /** + * Returns a name for this {@link AbstractSecretBundleConfigSource}. + * + *

The default implementation of this method returns a valud as if computed by {@link Class#getName() + * this.getClass().getName()}.

+ * + *

This method does not, and overrides of this method must not, return {@code null}.

+ * + *

This method is, and overrides of this method must be, safe for concurrent use by multiple threads.

+ * + * @return a non-{@code null} name + * + * @see ConfigSource#getName() + */ + @Override // ConfigSource + public String getName() { + return this.getClass().getName(); + } + + /** + * Returns a {@link Map} representing a subset of properties which this {@link AbstractSecretBundleConfigSource} may + * be capable of reproducing, or not. + * + *

This area of the specification permits any return value. Consequently the default implementation of this method + * returns a value equal to that returned by an invocation of {@link Map#of()}.

+ * + *

Subclasses may feel free to override this method to do almost anything.

+ * + *

This method does not, and overrides of this method must not, return {@code null}.

+ * + *

This method is, and overrides of this method must be, safe for concurrent use by multiple threads.

+ * + * @return a non-{@code null}, immutable {@link Map} + */ + @Override // ConfigSource + public Map getProperties() { + return Map.of(); + } + + /** + * Returns a {@link Set} representing a subset of the property names for which this {@link + * AbstractSecretBundleConfigSource} may or may not be capable of locating values. + * + *

This area of the specification permits any return value. Consequently the default implementation of this method + * returns a value equal to that returned by an invocation of {@link Set#of()}.

+ * + *

Subclasses may feel free to override this method to do almost anything.

+ * + *

This method does not, and overrides of this method must not, return {@code null}.

+ * + *

This method is, and overrides of this method must be, safe for concurrent use by multiple threads.

+ * + * @return a non-{@code null}, immutable {@link Set} + */ + @Override // ConfigSource + public Set getPropertyNames() { + return Set.of(); + } + + /** + * Returns a value for the supplied {@code propertyName}, or {@code null} if there is no such value known at the + * moment of invocation. + * + *

This method is safe for concurrent use by multiple threads.

+ * + * @param propertyName the name of the property; may be {@code null} + * + * @return a suitable value, or {@code null} if there is no value suitable for the supplied {@code propertyName} + */ + @Override // ConfigSource + public String getValue(String propertyName) { + return + this.f.apply(propertyName) instanceof Base64SecretBundleContentDetails b64 + ? this.base64Decoder.apply(b64.getContent()) + : null; + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AdpSuppliers.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AdpSuppliers.java new file mode 100644 index 00000000000..139daed780a --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/AdpSuppliers.java @@ -0,0 +1,271 @@ +/* + * 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.secrets.mp.configsource; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.URI; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import com.oracle.bmc.Region; +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; +import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; +import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider; +import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder; +import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider; +import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider.ResourcePrincipalAuthenticationDetailsProviderBuilder; +import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider; +import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder; +import com.oracle.bmc.auth.SimplePrivateKeySupplier; +import com.oracle.bmc.auth.StringPrivateKeySupplier; + +import static java.lang.System.Logger; + +/** + * A utility class containing methods that produce {@link Supplier}s of {@link BasicAuthenticationDetailsProvider} + * instances of various kinds. + */ +final class AdpSuppliers { + + private static final Pattern COMMA_SPLITTER = Pattern.compile("(?> simple(Function> c) { + return simple(c, SimpleAuthenticationDetailsProvider::builder); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> simple(Function> c, + Supplier bs) { + return simple(c, bs, b -> b::build); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> simple(Function> c, + Supplier bs, + Function> f) { + return c.apply("oci.auth.fingerprint") + .flatMap(fingerprint -> c.apply("oci.auth.region") + .flatMap(region -> c.apply("oci.auth.tenant-id") + .flatMap(tenantId -> c.apply("oci.auth.user-id") + .map(userId -> { + var b = bs.get(); + b.fingerprint(fingerprint); + b.region(Region.valueOf(region)); + b.tenantId(tenantId); + b.userId(userId); + c.apply("oci.auth.passphrase").ifPresent(b::passPhrase); + c.apply("oci.auth.private-key") + .ifPresentOrElse(pk -> b.privateKeySupplier(new StringPrivateKeySupplier(pk)), + () -> b.privateKeySupplier(new SimplePrivateKeySupplier(c.apply("oci.auth.private-key-path") + .orElse(DEFAULT_OCI_AUTH_PRIVATE_KEY_PATH)))); + return f.apply(b); + })))); + } + + static Optional> configFile(Function> c) { + return + configFile(c.apply("oci.config.path").orElse(null), + c.apply("oci.config.profile").orElse(DEFAULT_OCI_CONFIG_PROFILE)); + } + + static Optional> configFile() { + return configFile((String) null); + } + + static Optional> configFile(String ociConfigPath) { + return configFile(ociConfigPath, DEFAULT_OCI_CONFIG_PROFILE); + } + + static Optional> configFile(String ociConfigPath, + String ociConfigProfile) { + if (ociConfigProfile == null) { + ociConfigProfile = DEFAULT_OCI_CONFIG_PROFILE; + } + ConfigFileAuthenticationDetailsProvider adp; + try { + if (ociConfigPath == null) { + adp = new ConfigFileAuthenticationDetailsProvider(ociConfigProfile); + } else { + adp = new ConfigFileAuthenticationDetailsProvider(ociConfigPath, ociConfigProfile); + } + } catch (FileNotFoundException | NoSuchFileException e) { + return Optional.empty(); + } catch (IOException e) { + // The underlying ConfigFileReader that does the real work does not throw a FileNotFoundException (as it + // probably should) when it cannot find the configuration file. To distinguish this "ordinary" IOException + // from other IOExceptions, we therefore have no choice but to parse the error message. See + // https://github.com/oracle/oci-java-sdk/blob/v3.23.0/bmc-common/src/main/java/com/oracle/bmc/ConfigFileReader.java#L91-L95. + String message = e.getMessage(); + if (message != null + && message.startsWith("Can't load the default config from ") + && message.endsWith(" because it does not exist or it is not a file.")) { + return Optional.empty(); + } + // It's not a "file not found" case; it's some other exception. + throw new UncheckedIOException(message, e); + } + return Optional.of(() -> adp); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> instancePrincipals(Function> c) { + return instancePrincipals(c, InstancePrincipalsAuthenticationDetailsProvider::builder); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> instancePrincipals(Function> c, + Supplier bs) { + return instancePrincipals(c, bs, b -> b::build); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> instancePrincipals(Function> c, + Supplier bs, + Function> f) { + int timeoutPositiveMillis = DEFAULT_OCI_IMDS_TIMEOUT_MILLIS; + try { + timeoutPositiveMillis = + Math.max(0, c.apply("oci.imds.timeout.milliseconds").map(Integer::valueOf).orElse(DEFAULT_OCI_IMDS_TIMEOUT_MILLIS)); + } catch (IllegalArgumentException conversionException) { + } + return instancePrincipals(timeoutPositiveMillis, bs, f); + } + + static Optional> instancePrincipals() { + return instancePrincipals(DEFAULT_OCI_IMDS_TIMEOUT_MILLIS); + } + + static Optional> instancePrincipals(int timeoutPositiveMillis) { + return instancePrincipals(timeoutPositiveMillis, InstancePrincipalsAuthenticationDetailsProvider::builder); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> instancePrincipals(int timeoutPositiveMillis, + Supplier bs) { + return instancePrincipals(timeoutPositiveMillis, bs, b -> b::build); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> instancePrincipals(int timeoutPositiveMillis, + Supplier bs, + Function> f) { + var b = bs.get(); + try { + if (InetAddress.getByName(URI.create(b.getMetadataBaseUrl()).getHost()).isReachable(timeoutPositiveMillis)) { + return Optional.of(f.apply(b)); + } + } catch (ConnectException e) { + } catch (IOException e) { + throw new UncheckedIOException(e.getMessage(), e); + } + return Optional.empty(); + } + + static Optional> resourcePrincipal() { + return resourcePrincipal(ResourcePrincipalAuthenticationDetailsProvider::builder); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> resourcePrincipal(Supplier bs) { + return resourcePrincipal(bs, b -> b::build); + } + + @SuppressWarnings("checkstyle:linelength") + static Optional> resourcePrincipal(Supplier bs, + Function> f) { + return Optional.ofNullable(System.getenv("OCI_RESOURCE_PRINCIPAL_VERSION") == null ? null : f.apply(bs.get())); + } + + @SuppressWarnings("checkstyle:linelength") + static Supplier adpSupplier(Function> c) { + return + adpSupplier(c.apply("oci.auth-strategies") + .or(() -> c.apply("oci.auth-strategy")) + .or(() -> Optional.of("auto")) + .stream() + .flatMap(s -> Stream.of(COMMA_SPLITTER.split(s, 0))) + .flatMap(s -> switch (s.trim().toLowerCase()) { + case "auto" -> Stream.of(simple(c), + configFile(c), + instancePrincipals(c), + resourcePrincipal()); + case "config", "simple" -> Stream.of(simple(c)); + case "config-file" -> Stream.of(configFile(c)); + case "instance-principals" -> Stream.of(instancePrincipals(c)); + case "resource-principal" -> Stream.of(resourcePrincipal()); + default -> throw new java.util.NoSuchElementException(); + })); + } + + @SuppressWarnings("checkstyle:linelength") + static Supplier adpSupplier(Optional> o0, + Optional> o1) { + return adpSupplier(Stream.of(o0, o1)); + } + + @SuppressWarnings("checkstyle:linelength") + static Supplier adpSupplier(Optional> o0, + Optional> o1, + Optional> o2) { + return adpSupplier(Stream.of(o0, o1, o2)); + } + + @SuppressWarnings("checkstyle:linelength") + static Supplier adpSupplier(Optional> o0, + Optional> o1, + Optional> o2, + Optional> o3) { + return adpSupplier(Stream.of(o0, o1, o2, o3)); + } + + @SuppressWarnings("checkstyle:linelength") + static Supplier adpSupplier(Collection>> c) { + return adpSupplier(c.stream()); + } + + @SuppressWarnings("checkstyle:linelength") + static Supplier adpSupplier(Stream>> s) { + return s + .flatMap(Optional::stream) + .findFirst() + .orElseThrow(); + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Guards.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Guards.java new file mode 100644 index 00000000000..834a024ef5f --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Guards.java @@ -0,0 +1,62 @@ +/* + * 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.secrets.mp.configsource; + +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +/** + * A utility class containing useful operations for guarding {@link Function}s. + * + * @see #guard(Function, Predicate) + */ +final class Guards { + + private Guards() { + super(); + } + + /** + * Returns a {@link Function} that guards the supplied {@link Function} with the supplied {@link Predicate}, + * returning {@code null} if the {@link Predicate}'s {@link Predicate#test(Object)} method returns {@code false}, + * and returning the result of invoking the supplied {@link Function} otherwise. + * + * @param the type of the supplied {@link Function}'s sole parameter + * + * @param the return type of the supplied {@link Function} + * + * @param f the {@link Function} to guard; must not be {@code null} + * + * @param p the {@link Predicate} used to guard the supplied {@link Function}; must not be {@code null} + * + * @return {@code null} if the supplied {@link Predicate}'s {@link Predicate#test(Object)} method returns {@code + * false}, and returning the result of invoking the supplied {@link Function} otherwise + * + * @exception NullPointerException if any argument is {@code null} + */ + static Function guard(Function f, Predicate p) { + Objects.requireNonNull(f, "f"); + Objects.requireNonNull(p, "p"); + return t -> p.test(t) ? f.apply(t) : null; + } + + static Function guardWithAcceptPattern(Function f, Pattern p) { + return guard(f, cs -> p.matcher(cs).matches()); + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/OciSecretsMpMetaConfigProvider.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/OciSecretsMpMetaConfigProvider.java new file mode 100644 index 00000000000..71bb52ecdfd --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/OciSecretsMpMetaConfigProvider.java @@ -0,0 +1,142 @@ +/* + * 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.secrets.mp.configsource; + +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; +import java.util.regex.Pattern; + +import io.helidon.common.Prioritized; +import io.helidon.config.Config; +import io.helidon.config.mp.spi.MpMetaConfigProvider; + +import com.oracle.bmc.secrets.Secrets; +import org.eclipse.microprofile.config.spi.ConfigSource; + +import static io.helidon.config.ConfigSources.classpath; +import static io.helidon.config.ConfigSources.file; +import static io.helidon.integrations.oci.secrets.mp.configsource.AdpSuppliers.adpSupplier; +import static io.helidon.integrations.oci.secrets.mp.configsource.SecretsSuppliers.secrets; +import static io.helidon.integrations.oci.secrets.mp.configsource.Suppliers.memoizedSupplier; + +/** + * An {@link MpMetaConfigProvider} implementation that {@linkplain #create(String, Config, String) creates} {@link + * ConfigSource} implementations backed by the OCI Secrets + * Retrieval API. + * + * @see MpMetaConfigProvider + * + * @see ConfigSource + */ +public final class OciSecretsMpMetaConfigProvider implements MpMetaConfigProvider, Prioritized { + + private static final String ACCEPT_PATTERN_KEY = "accept-pattern"; + + private static final int PRIORITY = 300; + + /** + * An unmodifiable, unchanging {@link Set} of types returned by the {@link #supportedTypes()} method. + */ + public static final Set SUPPORTED_TYPES = Set.of("oci-secrets"); + + private static final String VAULT_OCID_KEY = "vault-ocid"; + + /** + * Creates a new {@link OciSecretsMpMetaConfigProvider}. + * + * @deprecated For {@link java.util.ServiceLoader} use only. + */ + @Deprecated // For ServiceLoader use only. + public OciSecretsMpMetaConfigProvider() { + super(); + } + + /** + * Returns a non-{@code null}, unmodifiable, unchanging, determinate {@link Set} of identifiers under which this + * {@link OciSecretsMpMetaConfigProvider} will be registered while a set of {@link ConfigSource}s is being + * assembled. + * + * @return a non-{@code null}, unmodifiable, unchanging, determinate {@link Set} of identifiers + */ + @Override + public Set supportedTypes() { + return SUPPORTED_TYPES; + } + + /** + * Creates and returns a non-{@code null}, unmodifiable, unchanging {@link List} of {@link ConfigSource} + * implementations suitable for the supplied {@code type}, and as initially set up using the supplied {@link Config} + * and (possibly {@code null}) {@code profile}. + * + * @param type a type drawn from the {@link Set} of {@linkplain #supportedTypes() supported types}; must not be + * {@code null} + * + * @param metaConfig a {@link Config} representing meta-configuration that will be used to set up the {@link + * ConfigSource}s that are returned; must not be {@code null} + * + * @param profile a configuration profile, or {@code null} if there is none + * + * @return a non-{@code null}, unmodifiable, unchanging {@link List} of {@link ConfigSource} implementations + * + * @exception NullPointerException if {@code type} or {@code metaConfig} is {@code null} + * + * @exception IllegalArgumentException if {@code type} is not present in the determinate {@link Set} of types + * returned by an invocation of the {@link #supportedTypes()} method + * + * @exception java.util.regex.PatternSyntaxException if a regular expression syntax was not correct + * + * @see MpMetaConfigProvider#create(String, Config, String) + * + * @see #supportedTypes() + */ + @Override + public List create(String type, Config metaConfig, String profile) { + if (!this.supportedTypes().contains(Objects.requireNonNull(type, "type"))) { + throw new IllegalArgumentException("type: " + type); + } + Pattern acceptPattern = + Pattern.compile(metaConfig.get(ACCEPT_PATTERN_KEY) + .asString() + .or(() -> Optional.ofNullable(System.getProperty(ACCEPT_PATTERN_KEY))) + .orElseThrow()); + String vaultId = metaConfig.get(VAULT_OCID_KEY) + .asString() + .orElse(System.getProperty(VAULT_OCID_KEY)); + Config ociYaml = Config.just(classpath("oci.yaml").optional(), file(Paths.get("oci.yaml")).optional()); + Supplier secretsSupplier = + memoizedSupplier(secrets(adpSupplier(s -> ociYaml.get(s).asString().asOptional()))); + return + List.of(new SecretBundleByNameConfigSource(acceptPattern, + vaultId, + secretsSupplier)); + } + + /** + * Returns a (determinate) priority for this {@link OciSecretsMpMetaConfigProvider} when invoked. + * + * @return a determinate priority + */ + @Override + public int priority() { + return PRIORITY; + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleByNameConfigSource.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleByNameConfigSource.java new file mode 100644 index 00000000000..4dd2810e402 --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleByNameConfigSource.java @@ -0,0 +1,36 @@ +/* + * 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.secrets.mp.configsource; + +import java.util.function.Supplier; +import java.util.regex.Pattern; + +import com.oracle.bmc.secrets.Secrets; + +import static io.helidon.integrations.oci.secrets.mp.configsource.Guards.guardWithAcceptPattern; +import static io.helidon.integrations.oci.secrets.mp.configsource.SecretBundleContentDetailsFunctions.secretBundleContentDetailsByName; + +final class SecretBundleByNameConfigSource extends AbstractSecretBundleConfigSource { + + private SecretBundleByNameConfigSource() { + this(null, null, null); + } + + SecretBundleByNameConfigSource(Pattern acceptPattern, String vaultOcid, Supplier ss) { + super(guardWithAcceptPattern(secretBundleContentDetailsByName(vaultOcid, ss), acceptPattern), ss); + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleContentDetailsFunctions.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleContentDetailsFunctions.java new file mode 100644 index 00000000000..6acfbb5e4a0 --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretBundleContentDetailsFunctions.java @@ -0,0 +1,59 @@ +/* + * 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.secrets.mp.configsource; + +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import com.oracle.bmc.secrets.Secrets; +import com.oracle.bmc.secrets.model.SecretBundleContentDetails; +import com.oracle.bmc.secrets.requests.GetSecretBundleByNameRequest; + +final class SecretBundleContentDetailsFunctions { + + private SecretBundleContentDetailsFunctions() { + super(); + } + + @SuppressWarnings({"checkstyle:linelength"}) + static Function secretBundleContentDetailsByName(String vaultId, + Supplier ss) { + return secretBundleContentDetailsByName(vaultId, + GetSecretBundleByNameRequest::builder, + UnaryOperator.identity(), + r -> ss.get().getSecretBundleByName(r).getSecretBundle().getSecretBundleContent()); + } + + @SuppressWarnings({"checkstyle:linelength"}) + static Function secretBundleContentDetailsByName(String vaultId, + Supplier bs, + UnaryOperator op, + Function f) { + return pn -> { + if (pn == null || pn.isBlank()) { + return null; + } + var b = bs.get(); // e.g. GetSecretBundleByNameRequest.builder(); + if (vaultId != null) { + b.vaultId(vaultId); + } + b.secretName(pn); + return f.apply(op.apply(b).build()); + }; + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretsSuppliers.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretsSuppliers.java new file mode 100644 index 00000000000..e2fb5a535df --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/SecretsSuppliers.java @@ -0,0 +1,56 @@ +/* + * 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.secrets.mp.configsource; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; +import com.oracle.bmc.secrets.Secrets; +import com.oracle.bmc.secrets.SecretsClient; + +import static io.helidon.integrations.oci.secrets.mp.configsource.AdpSuppliers.adpSupplier; + +final class SecretsSuppliers { + + private SecretsSuppliers() { + super(); + } + + static Supplier secrets(Function> c) { + return secrets(adpSupplier(c)); + } + + static Supplier secrets(BasicAuthenticationDetailsProvider adp) { + Objects.requireNonNull(adp, "adp"); + return secrets(() -> adp); + } + + static Supplier secrets(Supplier adpSupplier) { + Objects.requireNonNull(adpSupplier, "adpSupplier"); + return secrets(SecretsClient.builder()::build, adpSupplier); + } + + static Supplier secrets(Function f, + Supplier adpSupplier) { + Objects.requireNonNull(f, "f"); + Objects.requireNonNull(adpSupplier, "adpSupplier"); + return () -> f.apply(adpSupplier.get()); + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Suppliers.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Suppliers.java new file mode 100644 index 00000000000..6ffc047004b --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/Suppliers.java @@ -0,0 +1,67 @@ +/* + * 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.secrets.mp.configsource; + +import java.util.function.Supplier; + +/** + * A utility class containing useful operations for {@link Supplier}s. + */ +final class Suppliers { + + private Suppliers() { + super(); + } + + /** + * Memoizes the supplied {@link + * Supplier} and returns the memoization. + * + *

The memoization will not call the supplied {@link Supplier}'s {@link Supplier#get()} method until its own {@link + * Supplier#get()} method is called.

+ * + * @param the return type of the supplied {@link Supplier} + * + * @param s the {@link Supplier} to memoize; must not be {@code null} + * + * @return a memoized version of the supplied {@link Supplier}; never {@code null} + * + * @exception NullPointerException if {@code s} is {@code null} + */ + @SuppressWarnings("unchecked") + static Supplier memoizedSupplier(Supplier s) { + if (s.getClass().getEnclosingClass() == Suppliers.class && s.getClass().isAnonymousClass()) { + return (Supplier) s; + } + return new Supplier<>() { + private Supplier d = this::compute; // no need for volatile; construction semantics + private boolean initialized; + private synchronized R compute() { + if (!this.initialized) { // no need for volatile; under lock + R r = s.get(); + this.d = () -> r; + this.initialized = true; + } + return this.d.get(); + } + @Override + public R get() { + return this.d.get(); // no need for volatile; d is either synchronized or "immutable" + } + }; + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/package-info.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/package-info.java new file mode 100644 index 00000000000..ddab0d28a04 --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/io/helidon/integrations/oci/secrets/mp/configsource/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Provides classes and interfaces for using the OCI Secrets + * Retrieval API as part of a {@linkplain org.eclipse.microprofile.config.spi.ConfigSource MicroProfile Config + * ConfigSource} implementation. + */ +package io.helidon.integrations.oci.secrets.mp.configsource; diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/java/module-info.java b/integrations/oci/oci-secrets-mp-config-source/src/main/java/module-info.java new file mode 100644 index 00000000000..a7fd6ad9fea --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/java/module-info.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** + * Provides packages containing classes and interfaces for OCI Secrets + * Retrieval API-using {@linkplain org.eclipse.microprofile.config.spi.ConfigSource configuration sources}. + */ +@SuppressWarnings({ "requires-automatic", "requires-transitive-automatic" }) +module io.helidon.integrations.oci.secrets.mp.configsource { + + exports io.helidon.integrations.oci.secrets.mp.configsource; + + requires io.helidon.common; + requires transitive io.helidon.config; + requires transitive io.helidon.config.mp; + requires transitive microprofile.config.api; + requires oci.java.sdk.common; + requires transitive oci.java.sdk.secrets; + + provides io.helidon.config.mp.spi.MpMetaConfigProvider with io.helidon.integrations.oci.secrets.mp.configsource.OciSecretsMpMetaConfigProvider; + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-oci-secrets-mp/native-image.properties b/integrations/oci/oci-secrets-mp-config-source/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-oci-secrets-mp/native-image.properties new file mode 100644 index 00000000000..ad0da01cf8c --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-oci-secrets-mp/native-image.properties @@ -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. +# + +Args=--initialize-at-build-time=io.helidon.config.oci-secrets.mp diff --git a/integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/MetaConfigUsageTest.java b/integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/MetaConfigUsageTest.java new file mode 100644 index 00000000000..3f581eed05b --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/MetaConfigUsageTest.java @@ -0,0 +1,36 @@ +/* + * 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.secrets.mp.configsource; + +import org.eclipse.microprofile.config.ConfigProvider; +import org.junit.jupiter.api.Test; + +final class MetaConfigUsageTest { + + private MetaConfigUsageTest() { + super(); + } + + /** + * Triggers {@link Config} creation which also triggers {@link io.helidon.config.mp.spi.MpMetaConfigProvider} + * loading and creation. + */ + @Test + final void testMetaConfigUsage() { + ConfigProvider.getConfig().getOptionalValue("java.home", String.class); + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/UsageTest.java b/integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/UsageTest.java new file mode 100644 index 00000000000..63647b51587 --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/test/java/io/helidon/integrations/oci/secrets/mp/configsource/UsageTest.java @@ -0,0 +1,57 @@ +/* + * 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.secrets.mp.configsource; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +final class UsageTest { + + private UsageTest() { + super(); + } + + @Test + final void testSpike() { + Config c = ConfigProvider.getConfig(); + + // Make sure non-existent, and therefore non-secret, properties are rejected idiomatically. + assertNull(c.getOptionalValue("bogus", String.class).orElse(null)); + + // Make sure non-secret properties are handled by, e.g., System properties etc. + assertEquals(System.getProperty("java.home"), c.getValue("java.home", String.class)); + + // Do the rest of this test only if the following assumptions hold. + String vaultId = System.getProperty("vault-ocid"); + assumeTrue(vaultId != null && !vaultId.isBlank()); + String expectedValue = System.getProperty("FrancqueSecret.expectedValue"); + assumeTrue(expectedValue != null && !expectedValue.isBlank()); + assumeTrue(Files.exists(Paths.get(System.getProperty("user.home"), ".oci", "config"))); + + // The vault designated by the vault OCID must hold a secret named FrancqueSecret, and its value must be equal + // to the expected value. + assertEquals(expectedValue, c.getValue("FrancqueSecret", String.class)); + } + +} diff --git a/integrations/oci/oci-secrets-mp-config-source/src/test/resources/mp-meta-config.yaml b/integrations/oci/oci-secrets-mp-config-source/src/test/resources/mp-meta-config.yaml new file mode 100644 index 00000000000..32cc37f6d2e --- /dev/null +++ b/integrations/oci/oci-secrets-mp-config-source/src/test/resources/mp-meta-config.yaml @@ -0,0 +1,6 @@ +add-default-sources: true + +sources: + - type: 'oci-secrets' + # vault-ocid: 123 + # accept-pattern: '^.+\.password$' diff --git a/integrations/oci/pom.xml b/integrations/oci/pom.xml index 783f4cc7074..ede9e7524ce 100644 --- a/integrations/oci/pom.xml +++ b/integrations/oci/pom.xml @@ -34,6 +34,7 @@ metrics + oci-secrets-mp-config-source sdk diff --git a/pom.xml b/pom.xml index 615a5d2c0bb..b5fa4a9b90e 100644 --- a/pom.xml +++ b/pom.xml @@ -158,6 +158,8 @@ http://narayana.io/docs/api/ https://www.eclipse.org/eclipselink/api/3.0/ + https://docs.oracle.com/en-us/iaas/tools/java/${version.lib.oci}/ + 2.12 https://fasterxml.github.io/jackson-annotations/javadoc/${javadoc.jackson.version}/ https://fasterxml.github.io/jackson-core/javadoc/${javadoc.jackson.version}/ @@ -375,6 +377,11 @@ ${javadoc.packagelist.dir}/microprofile-tracing + + ${javadoc.link.oci} + ${javadoc.packagelist.dir}/oci + + ${javadoc.link.weld} ${javadoc.packagelist.dir}/weld