From ec35da550bbe0fbd37990c672378bf6ad11a1165 Mon Sep 17 00:00:00 2001 From: Anders Swanson Date: Thu, 20 Jun 2024 09:58:04 -0700 Subject: [PATCH] OCI Vault Signed-off-by: Anders Swanson --- .../spring/vault/VaultAutoConfiguration.java | 81 +++++++++++++++++ .../cloud/spring/vault/VaultProperties.java | 27 ++++++ ...itional-spring-configuration-metadata.json | 6 ++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../SpringCloudOciVaultSampleApplication.java | 6 +- .../VaultController.java | 31 +++++++ .../src/main/resources/application.properties | 9 ++ .../springcloudocivaultsample/VaultIT.java | 56 ++++++++++++ spring-cloud-oci-vault/pom.xml | 4 + .../com/oracle/cloud/spring/vault/Vault.java | 31 +++++++ .../oracle/cloud/spring/vault/VaultImpl.java | 89 ++++++++++++++++++- .../cloud/spring/vault/VaultImplTest.java | 84 +++++++++++++++++ 12 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultAutoConfiguration.java create mode 100644 spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultProperties.java rename spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/{streaming => vault}/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java (57%) create mode 100644 spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultController.java create mode 100644 spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/resources/application.properties create mode 100644 spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/test/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultIT.java create mode 100644 spring-cloud-oci-vault/src/test/java/com/oracle/cloud/spring/vault/VaultImplTest.java diff --git a/spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultAutoConfiguration.java b/spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultAutoConfiguration.java new file mode 100644 index 00000000..cf4c18fd --- /dev/null +++ b/spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultAutoConfiguration.java @@ -0,0 +1,81 @@ +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ +package com.oracle.cloud.spring.vault; + + +import com.oracle.bmc.auth.RegionProvider; +import com.oracle.bmc.secrets.Secrets; +import com.oracle.bmc.secrets.SecretsClient; +import com.oracle.bmc.vault.Vaults; +import com.oracle.bmc.vault.VaultsClient; +import com.oracle.cloud.spring.autoconfigure.core.CredentialsProvider; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Bean; + +import static com.oracle.cloud.spring.autoconfigure.core.CredentialsProviderAutoConfiguration.credentialsProviderQualifier; +import static com.oracle.cloud.spring.autoconfigure.core.RegionProviderAutoConfiguration.regionProviderQualifier; + +/** + * Auto-configuration for initializing the OCI Vault component. + * Depends on {@link com.oracle.cloud.spring.autoconfigure.core.CredentialsProviderAutoConfiguration} and + * {@link com.oracle.cloud.spring.autoconfigure.core.RegionProviderAutoConfiguration} + * for loading the Authentication configuration + * + * @see Vault + */ +@AutoConfiguration +@ConditionalOnClass({Vault.class}) +@EnableConfigurationProperties(VaultProperties.class) +@ConditionalOnProperty(name = "spring.cloud.oci.vault.enabled", havingValue = "true", matchIfMissing = true) +public class VaultAutoConfiguration { + private final VaultProperties properties; + + public VaultAutoConfiguration(VaultProperties properties) { + this.properties = properties; + } + + @Bean + @RefreshScope + @ConditionalOnProperty(name = "spring.cloud.oci.genai.embedding.enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnMissingBean(Vault.class) + public Vault embeddingModel(Vaults vaults, Secrets secrets) { + return new VaultImpl(vaults, secrets, properties.getVaultId(), properties.getCompartment()); + } + + @Bean + @RefreshScope + @ConditionalOnMissingBean + public Vaults vaults(@Qualifier(regionProviderQualifier) RegionProvider regionProvider, + @Qualifier(credentialsProviderQualifier) + CredentialsProvider cp) { + Vaults vaults = VaultsClient.builder() + .build(cp.getAuthenticationDetailsProvider()); + if (regionProvider.getRegion() != null) { + vaults.setRegion(regionProvider.getRegion()); + } + return vaults; + } + + @Bean + @RefreshScope + @ConditionalOnMissingBean + public Secrets secrets(@Qualifier(regionProviderQualifier) RegionProvider regionProvider, + @Qualifier(credentialsProviderQualifier) + CredentialsProvider cp) { + Secrets secrets = SecretsClient.builder() + .build(cp.getAuthenticationDetailsProvider()); + if (regionProvider.getRegion() != null) { + secrets.setRegion(regionProvider.getRegion()); + } + return secrets; + } +} + diff --git a/spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultProperties.java b/spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultProperties.java new file mode 100644 index 00000000..c24e46ba --- /dev/null +++ b/spring-cloud-oci-autoconfigure/src/main/java/com/oracle/cloud/spring/vault/VaultProperties.java @@ -0,0 +1,27 @@ +package com.oracle.cloud.spring.vault; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = VaultProperties.PREFIX) +public class VaultProperties { + public static final String PREFIX = "spring.cloud.oci.vault"; + + private String compartment; + private String vaultId; + + public String getCompartment() { + return compartment; + } + + public void setCompartment(String compartment) { + this.compartment = compartment; + } + + public String getVaultId() { + return vaultId; + } + + public void setVaultId(String vaultId) { + this.vaultId = vaultId; + } +} diff --git a/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 0fd16369..075d2f57 100644 --- a/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -48,6 +48,12 @@ "description": "Auto-configure OCI Cloud streaming components.", "defaultValue": true }, + { + "name": "spring.cloud.oci.vault.enabled", + "type": "java.lang.Boolean", + "description": "Auto-configure OCI Cloud vault components.", + "defaultValue": true + }, { "name": "spring.cloud.oci.queue.enabled", "type": "java.lang.Boolean", diff --git a/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index d27aef49..a01364b0 100644 --- a/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-cloud-oci-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -8,3 +8,4 @@ com.oracle.cloud.spring.function.FunctionAutoConfiguration com.oracle.cloud.spring.streaming.StreamingAutoConfiguration com.oracle.cloud.spring.queue.QueueAutoConfiguration com.oracle.cloud.spring.genai.GenAIAutoConfiguration +com.oracle.cloud.spring.vault.VaultAutoConfiguration diff --git a/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/streaming/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java similarity index 57% rename from spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/streaming/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java rename to spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java index dcaf94a9..cb40a6ee 100644 --- a/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/streaming/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java +++ b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/SpringCloudOciVaultSampleApplication.java @@ -1,4 +1,8 @@ -package com.oracle.cloud.spring.sample.streaming.springcloudocivaultsample; +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ +package com.oracle.cloud.spring.sample.vault.springcloudocivaultsample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultController.java b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultController.java new file mode 100644 index 00000000..8928549e --- /dev/null +++ b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultController.java @@ -0,0 +1,31 @@ +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ +package com.oracle.cloud.spring.sample.vault.springcloudocivaultsample; + +import com.oracle.bmc.secrets.responses.GetSecretBundleByNameResponse; +import com.oracle.cloud.spring.vault.Vault; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/demoapp/api/vault/") +@Tag(name = "streaming APIs") +public class VaultController { + private final Vault vault; + + public VaultController(Vault vault) { + this.vault = vault; + } + + @GetMapping("secret") + public ResponseEntity getSecret(@RequestParam String secretName) { + GetSecretBundleByNameResponse secret = vault.getSecret(secretName); + return ResponseEntity.ok(vault.decodeBundle(secret)); + } +} diff --git a/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/resources/application.properties b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/resources/application.properties new file mode 100644 index 00000000..c4946454 --- /dev/null +++ b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/main/resources/application.properties @@ -0,0 +1,9 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + +spring.cloud.oci.region.static=us-chicago-1 +spring.cloud.oci.config.type=file + +spring.cloud.oci.vault.compartment=${OCI_COMPARTMENT_ID} +spring.cloud.oci.vault.vault-id=${OCI_VAULT_ID} +spring.cloud.oci.vault.enabled=true diff --git a/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/test/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultIT.java b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/test/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultIT.java new file mode 100644 index 00000000..46c13bdf --- /dev/null +++ b/spring-cloud-oci-samples/spring-cloud-oci-vault-sample/src/test/java/com/oracle/cloud/spring/sample/vault/springcloudocivaultsample/VaultIT.java @@ -0,0 +1,56 @@ +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ +package com.oracle.cloud.spring.sample.vault.springcloudocivaultsample; + +import java.util.Base64; +import java.util.UUID; + +import com.oracle.bmc.secrets.responses.GetSecretBundleByNameResponse; +import com.oracle.bmc.vault.model.Base64SecretContentDetails; +import com.oracle.bmc.vault.model.UpdateSecretDetails; +import com.oracle.bmc.vault.responses.UpdateSecretResponse; +import com.oracle.cloud.spring.vault.Vault; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Requires an existing vault, identified by the OCI_VAULT_ID environment variable. + */ +@SpringBootTest +@EnabledIfEnvironmentVariable(named = "OCI_COMPARTMENT_ID", matches = ".+") +@EnabledIfEnvironmentVariable(named = "OCI_VAULT_ID", matches = ".+") +public class VaultIT { + @Autowired + Vault vault; + + private final String secretName = "mysecret"; + + @Test + @Disabled + void getSecret() { + GetSecretBundleByNameResponse secret = vault.getSecret(secretName); + String decoded = vault.decodeBundle(secret); + assertThat(decoded).isNotNull(); + assertThat(decoded).hasSizeGreaterThan(1); + } + + @Test + void updateSecret() { + String content = UUID.randomUUID().toString(); + Base64SecretContentDetails contentDetails = Base64SecretContentDetails.builder() + .content(Base64.getEncoder().encodeToString(content.getBytes())) + .name(content) + .build(); + UpdateSecretResponse response = vault.updateSecret(secretName, UpdateSecretDetails.builder() + .secretContent(contentDetails) + .build()); + assertThat(response.getSecret()).isNotNull(); + } +} diff --git a/spring-cloud-oci-vault/pom.xml b/spring-cloud-oci-vault/pom.xml index c0d0329b..b4e903cd 100644 --- a/spring-cloud-oci-vault/pom.xml +++ b/spring-cloud-oci-vault/pom.xml @@ -53,6 +53,10 @@ Licensed under the Universal Permissive License v 1.0 as shown at https://oss.or com.oracle.oci.sdk oci-java-sdk-vault + + com.oracle.oci.sdk + oci-java-sdk-secrets + org.projectlombok lombok diff --git a/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/Vault.java b/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/Vault.java index fca0c6bb..adacb1b3 100644 --- a/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/Vault.java +++ b/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/Vault.java @@ -1,4 +1,35 @@ +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ package com.oracle.cloud.spring.vault; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Date; + +import com.oracle.bmc.secrets.model.Base64SecretBundleContentDetails; +import com.oracle.bmc.secrets.model.SecretBundleContentDetails; +import com.oracle.bmc.secrets.responses.GetSecretBundleByNameResponse; +import com.oracle.bmc.vault.model.CreateSecretDetails; +import com.oracle.bmc.vault.model.UpdateSecretDetails; +import com.oracle.bmc.vault.responses.CreateSecretResponse; +import com.oracle.bmc.vault.responses.ScheduleSecretDeletionResponse; +import com.oracle.bmc.vault.responses.UpdateSecretResponse; + public interface Vault { + GetSecretBundleByNameResponse getSecret(String secretName); + CreateSecretResponse createSecret(String secretName, CreateSecretDetails body); + ScheduleSecretDeletionResponse scheduleSecretDeletion(String secretName, Date timeOfDeletion); + UpdateSecretResponse updateSecret(String secretName, UpdateSecretDetails body); + + default String decodeBundle(GetSecretBundleByNameResponse bundle) { + SecretBundleContentDetails content = bundle.getSecretBundle().getSecretBundleContent(); + if (content instanceof Base64SecretBundleContentDetails) { + Base64SecretBundleContentDetails encoded = (Base64SecretBundleContentDetails) content; + return new String(Base64.getDecoder().decode(encoded.getContent()), StandardCharsets.UTF_8); + } else { + return content.toString(); + } + } } diff --git a/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/VaultImpl.java b/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/VaultImpl.java index 0b065732..8125827a 100644 --- a/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/VaultImpl.java +++ b/spring-cloud-oci-vault/src/main/java/com/oracle/cloud/spring/vault/VaultImpl.java @@ -1,4 +1,91 @@ +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ package com.oracle.cloud.spring.vault; -public class VaultImpl { +import java.util.Date; + +import com.oracle.bmc.secrets.Secrets; +import com.oracle.bmc.secrets.requests.GetSecretBundleByNameRequest; +import com.oracle.bmc.secrets.responses.GetSecretBundleByNameResponse; +import com.oracle.bmc.vault.Vaults; +import com.oracle.bmc.vault.model.CreateSecretDetails; +import com.oracle.bmc.vault.model.ScheduleSecretDeletionDetails; +import com.oracle.bmc.vault.model.UpdateSecretDetails; +import com.oracle.bmc.vault.requests.CreateSecretRequest; +import com.oracle.bmc.vault.requests.ScheduleSecretDeletionRequest; +import com.oracle.bmc.vault.requests.UpdateSecretRequest; +import com.oracle.bmc.vault.responses.CreateSecretResponse; +import com.oracle.bmc.vault.responses.ScheduleSecretDeletionResponse; +import com.oracle.bmc.vault.responses.UpdateSecretResponse; +import org.springframework.util.Assert; + +public class VaultImpl implements Vault { + private final Vaults vaults; + private final Secrets secrets; + private final String vaultId; + private final String compartmentId; + + public VaultImpl(Vaults vaults, Secrets secrets, String vaultId, String compartmentId) { + Assert.notNull(vaults, "vaults must not be null"); + Assert.notNull(secrets, "secrets must not be null"); + Assert.hasText(vaultId, "vaultId must not be empty"); + Assert.hasText(compartmentId, "compartmentId must not be empty"); + this.vaults = vaults; + this.secrets = secrets; + this.vaultId = vaultId; + this.compartmentId = compartmentId; + } + + public GetSecretBundleByNameResponse getSecret(String secretName) { + Assert.hasText(secretName, "secretName must not be empty"); + GetSecretBundleByNameRequest request = GetSecretBundleByNameRequest.builder() + .vaultId(vaultId) + .secretName(secretName) + .build(); + return secrets.getSecretBundleByName(request); + } + + public CreateSecretResponse createSecret(String secretName, CreateSecretDetails body) { + Assert.hasText(secretName, "secretName must not be empty"); + Assert.notNull(body, "body must not be null"); + CreateSecretRequest request = CreateSecretRequest.builder() + .body$(body.toBuilder() + .vaultId(vaultId) + .compartmentId(compartmentId) + .secretName(secretName) + .build()) + .build(); + return vaults.createSecret(request); + } + + public ScheduleSecretDeletionResponse scheduleSecretDeletion(String secretName, Date timeOfDeletion) { + Assert.hasText(secretName, "secretName must not be empty"); + Assert.notNull(timeOfDeletion, "timeOfDeletion must not be null"); + String secretId = getSecret(secretName) + .getSecretBundle() + .getSecretId(); + ScheduleSecretDeletionDetails body = ScheduleSecretDeletionDetails.builder() + .timeOfDeletion(timeOfDeletion) + .build(); + ScheduleSecretDeletionRequest request = ScheduleSecretDeletionRequest.builder() + .secretId(secretId) + .body$(body) + .build(); + return vaults.scheduleSecretDeletion(request); + } + + public UpdateSecretResponse updateSecret(String secretName, UpdateSecretDetails body) { + Assert.hasText(secretName, "secretName must not be empty"); + Assert.notNull(body, "body must not be null"); + String secretId = getSecret(secretName) + .getSecretBundle() + .getSecretId(); + UpdateSecretRequest request = UpdateSecretRequest.builder() + .secretId(secretId) + .body$(body) + .build(); + return vaults.updateSecret(request); + } } diff --git a/spring-cloud-oci-vault/src/test/java/com/oracle/cloud/spring/vault/VaultImplTest.java b/spring-cloud-oci-vault/src/test/java/com/oracle/cloud/spring/vault/VaultImplTest.java new file mode 100644 index 00000000..4bd551f5 --- /dev/null +++ b/spring-cloud-oci-vault/src/test/java/com/oracle/cloud/spring/vault/VaultImplTest.java @@ -0,0 +1,84 @@ +/* + ** Copyright (c) 2024, Oracle and/or its affiliates. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + */ +package com.oracle.cloud.spring.vault; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Date; + +import com.oracle.bmc.secrets.Secrets; +import com.oracle.bmc.secrets.model.Base64SecretBundleContentDetails; +import com.oracle.bmc.secrets.model.SecretBundle; +import com.oracle.bmc.secrets.responses.GetSecretBundleByNameResponse; +import com.oracle.bmc.vault.Vaults; +import com.oracle.bmc.vault.model.CreateSecretDetails; +import com.oracle.bmc.vault.model.UpdateSecretDetails; +import com.oracle.bmc.vault.responses.CreateSecretResponse; +import com.oracle.bmc.vault.responses.ScheduleSecretDeletionResponse; +import com.oracle.bmc.vault.responses.UpdateSecretResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class VaultImplTest { + private Vaults vaults; + private Secrets secrets; + private Vault vault; + + private final String compartmentId = "mycompartment"; + private final String vaultId = "myvault"; + private final String secretName = "mysecret"; + private final String secretValue = "foo"; + private final String secretValueEncoded = Base64.getEncoder().encodeToString(secretValue.getBytes(StandardCharsets.UTF_8)); + + + @BeforeEach + void setUp() { + vaults = mock(Vaults.class); + secrets = mock(Secrets.class); + vault = new VaultImpl(vaults, secrets, vaultId, compartmentId); + GetSecretBundleByNameResponse response = GetSecretBundleByNameResponse.builder() + .secretBundle(SecretBundle.builder() + .secretId(secretName) + .secretBundleContent(Base64SecretBundleContentDetails.builder() + .content(secretValueEncoded) + .build()) + .build()) + .build(); + when(secrets.getSecretBundleByName(any())).thenReturn(response); + } + + @Test + void getSecretBundle() { + GetSecretBundleByNameResponse foo = vault.getSecret(secretName); + String decoded = vault.decodeBundle(foo); + assertThat(decoded).isEqualTo(secretValue); + } + + @Test + void createSecret() { + when(vaults.createSecret(any())).thenReturn(CreateSecretResponse.builder().build()); + CreateSecretResponse response = vault.createSecret(secretName, CreateSecretDetails.builder().build()); + assertThat(response).isNotNull(); + } + + @Test + void scheduleSecretDeletion() { + when(vaults.scheduleSecretDeletion(any())).thenReturn(ScheduleSecretDeletionResponse.builder().build()); + ScheduleSecretDeletionResponse response = vault.scheduleSecretDeletion(secretName, new Date()); + assertThat(response).isNotNull(); + } + + @Test + void updateSecret() { + when(vaults.updateSecret(any())).thenReturn(UpdateSecretResponse.builder().build()); + UpdateSecretResponse response = vault.updateSecret(secretName, UpdateSecretDetails.builder().build()); + assertThat(response).isNotNull(); + } +}