diff --git a/partition-core/src/main/java/org/opengroup/osdu/partition/api/PartitionApi.java b/partition-core/src/main/java/org/opengroup/osdu/partition/api/PartitionApi.java index 140245dec2e129f6b98dffbd93fcd78efdafdeb3..fc2d35c103d30a89984dd14dab542b34e99ec3e3 100644 --- a/partition-core/src/main/java/org/opengroup/osdu/partition/api/PartitionApi.java +++ b/partition-core/src/main/java/org/opengroup/osdu/partition/api/PartitionApi.java @@ -15,6 +15,7 @@ package org.opengroup.osdu.partition.api; import org.opengroup.osdu.partition.model.PartitionInfo; +import org.opengroup.osdu.partition.model.Property; import org.opengroup.osdu.partition.provider.interfaces.IPartitionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -43,7 +44,7 @@ public class PartitionApi { @GetMapping("/{partitionId}") @PreAuthorize("@authorizationFilter.hasPermissions()") - public ResponseEntity<Map<String, Object>> get(@PathVariable("partitionId") String partitionId) { + public ResponseEntity<Map<String, Property>> get(@PathVariable("partitionId") String partitionId) { PartitionInfo partitionInfo = this.partitionService.getPartition(partitionId); return ResponseEntity.ok(partitionInfo.getProperties()); } diff --git a/partition-core/src/main/java/org/opengroup/osdu/partition/model/PartitionInfo.java b/partition-core/src/main/java/org/opengroup/osdu/partition/model/PartitionInfo.java index b6a4e9f22df0263e1eb9e6c6c0deaf4fc3c37965..4f2ce72d010428f55661593bcad008f00e91e5c8 100644 --- a/partition-core/src/main/java/org/opengroup/osdu/partition/model/PartitionInfo.java +++ b/partition-core/src/main/java/org/opengroup/osdu/partition/model/PartitionInfo.java @@ -29,5 +29,5 @@ import java.util.Map; public class PartitionInfo { @Builder.Default - Map<String, Object> properties = new HashMap<>(); + Map<String, Property> properties = new HashMap<>(); } \ No newline at end of file diff --git a/partition-core/src/main/java/org/opengroup/osdu/partition/model/Property.java b/partition-core/src/main/java/org/opengroup/osdu/partition/model/Property.java new file mode 100644 index 0000000000000000000000000000000000000000..5b87d40aa6d2d3f6ea0614ec8b172e532b93adff --- /dev/null +++ b/partition-core/src/main/java/org/opengroup/osdu/partition/model/Property.java @@ -0,0 +1,16 @@ +package org.opengroup.osdu.partition.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Property { + @Builder.Default + private boolean sensitive = false; + private Object value; +} diff --git a/partition-core/src/test/java/org/opengroup/osdu/partition/api/PartitionApiTest.java b/partition-core/src/test/java/org/opengroup/osdu/partition/api/PartitionApiTest.java index 8e5ae2bc2fd03ec87ad63bb6f59daaa5533e6e24..989dcf73b8db1eeae55df00d84d2e2d21e8dd0a0 100644 --- a/partition-core/src/test/java/org/opengroup/osdu/partition/api/PartitionApiTest.java +++ b/partition-core/src/test/java/org/opengroup/osdu/partition/api/PartitionApiTest.java @@ -21,11 +21,14 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.partition.model.PartitionInfo; +import org.opengroup.osdu.partition.model.Property; import org.opengroup.osdu.partition.provider.interfaces.IPartitionService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.junit.Assert.assertEquals; @@ -63,12 +66,12 @@ public class PartitionApiTest { @Test public void should_return200AndPartitionProperties_when_gettingPartitionIdSuccessfully() { String partitionId = "partition1"; - Map<String, Object> properties = new HashMap<>(); + Map<String, Property> properties = new HashMap<>(); when(partitionService.getPartition(anyString())).thenReturn(partitionInfo); when(partitionInfo.getProperties()).thenReturn(properties); - ResponseEntity<Map<String, Object>> result = this.sut.get(partitionId); + ResponseEntity<Map<String, Property>> result = this.sut.get(partitionId); assertEquals(HttpStatus.OK, result.getStatusCode()); assertEquals(properties, result.getBody()); } diff --git a/provider/partition-azure/pom.xml b/provider/partition-azure/pom.xml index 5b120ebacf066ed16f7dd66703b1745a7181aeea..77c0f6dfca3c519db775a840020f92c42e95be0c 100644 --- a/provider/partition-azure/pom.xml +++ b/provider/partition-azure/pom.xml @@ -17,7 +17,6 @@ <properties> <azure.version>2.3.1</azure.version> - <os_core_common_version>0.0.18</os_core_common_version> </properties> <dependencies> <dependency> @@ -65,7 +64,7 @@ <dependency> <groupId>org.opengroup.osdu</groupId> <artifactId>core-lib-azure</artifactId> - <version>0.0.19</version> + <version>0.0.29</version> <exclusions> <exclusion> <groupId>org.opengroup.osdu</groupId> @@ -125,6 +124,12 @@ <version>3.3.8.RELEASE</version> </dependency> + <dependency> + <groupId>com.microsoft.azure</groupId> + <artifactId>azure-storage</artifactId> + <version>8.6.5</version> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceCacheImpl.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/cache/PartitionServiceCacheImpl.java similarity index 82% rename from provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceCacheImpl.java rename to provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/cache/PartitionServiceCacheImpl.java index 3d36ed401e35f853249ccf5c99f49f3d2114a717..c349b8d7e2423a077e5452e4015c6434243d80cc 100644 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceCacheImpl.java +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/cache/PartitionServiceCacheImpl.java @@ -1,4 +1,4 @@ -package org.opengroup.osdu.partition.provider.azure.service; +package org.opengroup.osdu.partition.provider.azure.cache; import org.opengroup.osdu.core.common.cache.VmCache; import org.opengroup.osdu.partition.model.PartitionInfo; @@ -7,7 +7,8 @@ import org.springframework.stereotype.Service; @Service public class PartitionServiceCacheImpl extends VmCache<String, PartitionInfo> implements IPartitionServiceCache { + public PartitionServiceCacheImpl() { - super(5*60, 1000); + super(5 * 60, 1000); } } diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfig.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfig.java index 074c42a4ab2c5ff19bfbe9b835fba1473ffa1101..9d04b6636747c837c593fa124325855a637cd9e5 100644 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfig.java +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfig.java @@ -15,7 +15,7 @@ package org.opengroup.osdu.partition.provider.azure.di; import com.azure.security.keyvault.secrets.SecretClient; -import org.opengroup.osdu.partition.provider.azure.utils.KeyVaultFacade; +import org.opengroup.osdu.azure.KeyVaultFacade; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,14 +35,14 @@ public class AzureBootstrapConfig { } @Bean - @Named("COSMOS_ENDPOINT") - public String cosmosEndpoint(SecretClient kv) { - return KeyVaultFacade.getKeyVaultSecret(kv, "cosmos-endpoint"); + @Named("TABLE_STORAGE_ACCOUNT_NAME") + public String storageAccountName(SecretClient kv) { + return KeyVaultFacade.getSecretWithValidation(kv, "tbl-storage"); } @Bean - @Named("COSMOS_KEY") - public String cosmosKey(SecretClient kv) { - return KeyVaultFacade.getKeyVaultSecret(kv, "cosmos-primary-key"); + @Named("TABLE_STORAGE_ACCOUNT_KEY") + public String storageAccountKey(SecretClient kv) { + return KeyVaultFacade.getSecretWithValidation(kv, "tbl-storage-key"); } } \ No newline at end of file diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/CloudTableConfiguration.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/CloudTableConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..c2348302a5174f373b4ed73202edc7d89e4dcc99 --- /dev/null +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/CloudTableConfiguration.java @@ -0,0 +1,13 @@ +package org.opengroup.osdu.partition.provider.azure.di; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Getter +public class CloudTableConfiguration { + + @Value("${partition.cloud.table-name:PartitionInfo}") + private String cloudTableName; +} diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/TableStorageClient.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/TableStorageClient.java new file mode 100644 index 0000000000000000000000000000000000000000..0ad2f6d8d489cdb5b95f25a5149aa35e06412823 --- /dev/null +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/di/TableStorageClient.java @@ -0,0 +1,56 @@ +package org.opengroup.osdu.partition.provider.azure.di; + +import com.microsoft.azure.storage.CloudStorageAccount; +import com.microsoft.azure.storage.StorageException; +import com.microsoft.azure.storage.table.CloudTable; +import com.microsoft.azure.storage.table.CloudTableClient; +import org.apache.http.HttpStatus; +import org.opengroup.osdu.common.Validators; +import org.opengroup.osdu.core.common.model.http.AppException; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import javax.inject.Named; +import java.net.URISyntaxException; +import java.security.InvalidKeyException; + +@Component +public class TableStorageClient { + + private final String CONNECTION_STRING = "DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=core.windows.net"; + + @Bean + @Lazy + public CloudTableClient getCloudTableClient( + final @Named("TABLE_STORAGE_ACCOUNT_NAME") String storageAccountName, + final @Named("TABLE_STORAGE_ACCOUNT_KEY") String storageAccountKey) { + try { + Validators.checkNotNullAndNotEmpty(storageAccountName, "storageAccountName"); + Validators.checkNotNullAndNotEmpty(storageAccountKey, "storageAccountKey"); + + final String storageConnectionString = String.format(CONNECTION_STRING, storageAccountName, storageAccountKey); + CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString); + return storageAccount.createCloudTableClient(); + } catch (URISyntaxException | InvalidKeyException e) { + throw new AppException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "Error creating cloud table storage client", e.getMessage(), e); + } + } + + @Bean + @Lazy + public CloudTable getCloudTable( + final CloudTableClient cloudTableClient, + final CloudTableConfiguration tblConfiguration) { + try { + Validators.checkNotNull(cloudTableClient, "cloudTableClient"); + Validators.checkNotNull(tblConfiguration, "tblConfiguration"); + + CloudTable cloudTable = cloudTableClient.getTableReference(tblConfiguration.getCloudTableName()); + cloudTable.createIfNotExists(); + return cloudTable; + } catch (URISyntaxException | StorageException e) { + throw new AppException(HttpStatus.SC_INTERNAL_SERVER_ERROR, String.format("Error querying cloud table: %s", tblConfiguration), e.getMessage(), e); + } + } +} diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/CloudTableStore.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/CloudTableStore.java new file mode 100644 index 0000000000000000000000000000000000000000..7bb236a5b057042ac40ac72d987d7017802f47c5 --- /dev/null +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/CloudTableStore.java @@ -0,0 +1,51 @@ +package org.opengroup.osdu.partition.provider.azure.persistence; + +import com.microsoft.azure.storage.StorageException; +import com.microsoft.azure.storage.table.*; +import org.apache.http.HttpStatus; +import org.opengroup.osdu.core.common.model.http.AppException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CloudTableStore { + + private final String PARTITION_KEY = "PartitionKey"; + + @Autowired + private CloudTable cloudTableClient; + + public boolean deleteCloudTableEntity(final Class<? extends TableEntity> clazzType, String partitionKey, String rowKey) { + + try { + TableOperation retrievePartition = TableOperation.retrieve(partitionKey, rowKey, clazzType); + TableEntity partitionEntity = this.cloudTableClient.execute(retrievePartition).getResultAsType(); + TableOperation deleteOperation = TableOperation.delete(partitionEntity); + this.cloudTableClient.execute(deleteOperation); + return true; + } catch (StorageException e) { + throw new AppException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "Error querying cloud table", e.getMessage(), e); + } + } + + public Iterable<? extends TableEntity> queryByPartitionId(final Class<? extends TableEntity> clazzType, String value) { + + String partitionFilter = TableQuery.generateFilterCondition( + PARTITION_KEY, + TableQuery.QueryComparisons.EQUAL, + value); + + TableQuery<? extends TableEntity> partitionQuery = TableQuery.from(clazzType) + .where(partitionFilter); + + return this.cloudTableClient.execute(partitionQuery); + } + + public void insertBatchEntities(TableBatchOperation batchOperation) { + try { + this.cloudTableClient.execute(batchOperation); + } catch (StorageException e) { + new AppException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "error creating partition", e.getMessage(), e); + } + } +} diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/PartitionEntity.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/PartitionEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..78904cd412a45d3552f078be3448e1c19562a2e8 --- /dev/null +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/PartitionEntity.java @@ -0,0 +1,31 @@ +package org.opengroup.osdu.partition.provider.azure.persistence; + +import com.microsoft.azure.storage.table.DynamicTableEntity; + +public class PartitionEntity extends DynamicTableEntity { + + private String partitionId; + + private String name; + + public PartitionEntity() {} + + public PartitionEntity(String partitionId, String name) { + super(partitionId, name); + + this.partitionId = partitionId; + this.name = name; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { this.name = name; } + + public String getPartitionId() { + return this.partitionId; + } + + public void setPartitionId(String partitionId) { this.partitionId = partitionId; } +} \ No newline at end of file diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/PartitionTableStore.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/PartitionTableStore.java new file mode 100644 index 0000000000000000000000000000000000000000..1090251ada6f09d2f548c1e62ea6f5eeab08235f --- /dev/null +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/persistence/PartitionTableStore.java @@ -0,0 +1,93 @@ +package org.opengroup.osdu.partition.provider.azure.persistence; + +import com.microsoft.azure.storage.table.EntityProperty; +import com.microsoft.azure.storage.table.TableBatchOperation; +import org.opengroup.osdu.partition.model.PartitionInfo; +import org.opengroup.osdu.partition.model.Property; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class PartitionTableStore { + + @Autowired + private CloudTableStore cloudTableStore; + + public void addPartition(String partitionId, PartitionInfo partitionInfo) { + + Map<String, Property> requestProperties = partitionInfo.getProperties(); + TableBatchOperation batchOperation = new TableBatchOperation(); + for (Map.Entry<String, Property> entry : requestProperties.entrySet()) { + String key = entry.getKey(); + Property property = entry.getValue(); + + PartitionEntity partitionEntity = new PartitionEntity(partitionId, key); + HashMap<String, EntityProperty> properties = new HashMap<>(); + + if (property.isSensitive()) { + property.setValue(this.getTenantSafeSecreteId(partitionId, String.valueOf(property.getValue()))); + } + properties.put("value", new EntityProperty(String.valueOf(property.getValue()))); + properties.put("sensitive", new EntityProperty(property.isSensitive())); + partitionEntity.setProperties(properties); + batchOperation.insertOrReplace(partitionEntity); + } + + this.cloudTableStore.insertBatchEntities(batchOperation); + } + + public boolean partitionExists(String partitionId) { + + List<PartitionEntity> partitionEntities = this.queryByPartitionId(partitionId); + return !partitionEntities.isEmpty(); + } + + public Map<String, Property> getPartition(String partitionId) { + Map<String, Property> out = new HashMap<>(); + + List<PartitionEntity> partitionEntities = this.queryByPartitionId(partitionId); + if (partitionEntities.isEmpty()) { + return out; + } + + for (PartitionEntity pe : partitionEntities) { + Property property = Property.builder().build(); + HashMap<String, EntityProperty> properties = pe.getProperties(); + if (properties.containsKey("sensitive")) { + property.setSensitive(properties.get("sensitive").getValueAsBoolean()); + } + if (properties.containsKey("value")) { + property.setValue(properties.get("value").getValueAsString()); + } + out.put(pe.getRowKey(), property); + } + return out; + } + + public List<PartitionEntity> queryByPartitionId(String partitionId) { + List<PartitionEntity> out = new ArrayList<>(); + Iterable<PartitionEntity> results = (Iterable<PartitionEntity>) this.cloudTableStore.queryByPartitionId(PartitionEntity.class, partitionId); + for (PartitionEntity tableEntity : results) { + tableEntity.setPartitionId(tableEntity.getPartitionKey()); + tableEntity.setName(tableEntity.getRowKey()); + out.add(tableEntity); + } + return out; + } + + public void deletePartition(String partitionId) { + Iterable<PartitionEntity> results = (Iterable<PartitionEntity>) this.cloudTableStore.queryByPartitionId(PartitionEntity.class, partitionId); + for (PartitionEntity tableEntity : results) { + this.cloudTableStore.deleteCloudTableEntity(PartitionEntity.class, tableEntity.getPartitionKey(), tableEntity.getRowKey()); + } + } + + private String getTenantSafeSecreteId(String partitionId, String secreteName) { + return String.format("%s-%s", partitionId, secreteName); + } +} diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java index 8f0cb9b67d5b1e0754138474486ee848533b40de..f2036d26130cdbda4ccd42a52837b070c05fb0b5 100644 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java @@ -14,108 +14,55 @@ package org.opengroup.osdu.partition.provider.azure.service; -import com.azure.security.keyvault.secrets.SecretClient; import org.apache.http.HttpStatus; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.partition.model.PartitionInfo; -import org.opengroup.osdu.partition.provider.azure.utils.KeyVaultFacade; -import org.opengroup.osdu.partition.provider.azure.utils.ThreadPoolService; +import org.opengroup.osdu.partition.model.Property; +import org.opengroup.osdu.partition.provider.azure.persistence.PartitionTableStore; import org.opengroup.osdu.partition.provider.interfaces.IPartitionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; -import java.util.List; import java.util.Map; @Service public class PartitionServiceImpl implements IPartitionService { @Autowired - private SecretClient secretClient; - @Autowired - private ThreadPoolService threadPoolService; - - private static final String APP_DEV_SP_USERNAME = "app-dev-sp-username"; - private static final String SERVICE_PRINCIPAL_ID = "sp-appid"; + private PartitionTableStore tableStore; @Override public PartitionInfo createPartition(String partitionId, PartitionInfo partitionInfo) { - if (this.partitionExists(partitionId)) { + if (this.tableStore.partitionExists(partitionId)) { throw new AppException(HttpStatus.SC_CONFLICT, "partition exist", "Partition with same id exist"); } - this.addTenantSecretes(partitionId, partitionInfo); + + this.tableStore.addPartition(partitionId, partitionInfo); return partitionInfo; } @Override public PartitionInfo getPartition(String partitionId) { - if (!this.partitionExists(partitionId)) { + Map<String, Property> out = new HashMap<>(); + out.putAll(this.tableStore.getPartition(partitionId)); + + if (out.isEmpty()) { throw new AppException(HttpStatus.SC_NOT_FOUND, "partition not found", String.format("%s partition not found", partitionId)); } - Map<String, Object> out = new HashMap<>(); - out.putAll(this.getTenantSecreteInfo(partitionId)); - return PartitionInfo.builder().properties(out).build(); } @Override public boolean deletePartition(String partitionId) { - if (!this.partitionExists(partitionId)) { + if (!this.tableStore.partitionExists(partitionId)) { throw new AppException(HttpStatus.SC_NOT_FOUND, "partition not found", String.format("%s partition not found", partitionId)); } - this.deleteTenantSecrets(partitionId); + this.tableStore.deletePartition(partitionId); return true; } - - private void addTenantSecretes(String partitionId, PartitionInfo partitionInfo) { - // id - KeyVaultFacade.createKeyVaultSecret(this.secretClient, getTenantSafeSecreteId(partitionId, "id"), partitionId); - - // rest of keys - for (Map.Entry<String, Object> entry : partitionInfo.getProperties().entrySet()) { - String secreteName = this.getTenantSafeSecreteId(partitionId, entry.getKey()); - KeyVaultFacade.createKeyVaultSecret(this.secretClient, secreteName, String.valueOf(entry.getValue())); - } - } - - private Map<String, Object> getTenantSecreteInfo(String partitionId) { - Map<String, Object> out = new HashMap<>(); - List<String> secreteKeys = KeyVaultFacade.getKeyVaultSecrets(secretClient, partitionId); - if (secreteKeys.isEmpty()) { - return out; - } - - for (String key : secreteKeys) { - String outKey = key.replaceFirst(String.format("%s-", partitionId), ""); - out.put(outKey, KeyVaultFacade.getKeyVaultSecret(this.secretClient, key)); - } - out.put(SERVICE_PRINCIPAL_ID, KeyVaultFacade.getKeyVaultSecret(this.secretClient, APP_DEV_SP_USERNAME)); - return out; - } - - private void deleteTenantSecrets(String partitionId) { - List<String> secreteKeys = KeyVaultFacade.getKeyVaultSecrets(secretClient, partitionId); - if (secreteKeys.isEmpty()) { - return; - } - - this.threadPoolService.createDeletePoolIfNeeded(secreteKeys.size()); - - for (String key : secreteKeys) { - this.threadPoolService.getExecutorService().submit(() -> KeyVaultFacade.deleteKeyVaultSecret(this.secretClient, key)); - } - } - - private String getTenantSafeSecreteId(String partitionId, String secreteName) { - return String.format("%s-%s", partitionId, secreteName); - } - - private boolean partitionExists(String partitionId) { - return KeyVaultFacade.secretExists(secretClient, getTenantSafeSecreteId(partitionId, "id")); - } } \ No newline at end of file diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/utils/KeyVaultFacade.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/utils/KeyVaultFacade.java deleted file mode 100644 index a1e73a5c7cc24747805ba6f3b21b44a2a5f94df5..0000000000000000000000000000000000000000 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/utils/KeyVaultFacade.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2017-2020, Schlumberger -// -// 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 org.opengroup.osdu.partition.provider.azure.utils; - -import com.azure.core.exception.HttpResponseException; -import com.azure.core.exception.ResourceNotFoundException; -import com.azure.core.http.rest.PagedIterable; -import com.azure.core.http.rest.PagedResponse; -import com.azure.core.util.polling.SyncPoller; -import com.azure.security.keyvault.secrets.SecretClient; -import com.azure.security.keyvault.secrets.models.DeletedSecret; -import com.azure.security.keyvault.secrets.models.KeyVaultSecret; -import com.azure.security.keyvault.secrets.models.SecretProperties; -import org.apache.http.HttpStatus; -import org.opengroup.osdu.common.Validators; -import org.opengroup.osdu.core.common.model.http.AppException; - -import java.util.ArrayList; -import java.util.List; - -public final class KeyVaultFacade { - - /** - * Checks if the secret exists in KV - * - * @param secretClient secret client - * @param secretName name of secret - * @return True if secrete exist - */ - public static boolean secretExists(SecretClient secretClient, String secretName) { - Validators.checkNotNull(secretClient, "secretClient can't be null"); - Validators.checkNotNullAndNotEmpty(secretName, "secretName can't null or empty"); - - try { - secretClient.getSecret(secretName); - } catch (ResourceNotFoundException e) { - return false; - } - return true; - } - - /** - * Gets all secret from KV starting with prefix. - * - * @param secretClient secret client - * @param prefix secrete key prefix - * @return List of secret keys. - */ - public static List<String> getKeyVaultSecrets(SecretClient secretClient, String prefix) { - Validators.checkNotNull(secretClient, "secretClient can't be null"); - Validators.checkNotNullAndNotEmpty(prefix, "prefix can't null or empty"); - - List<String> out = new ArrayList<>(); - PagedIterable<SecretProperties> secretProperties = secretClient.listPropertiesOfSecrets(); - for (PagedResponse<SecretProperties> resp : secretProperties.iterableByPage()) { - resp.getItems().stream().filter(value -> value.getName().startsWith(prefix)).map(SecretProperties::getName).forEach(out::add); - } - - return out; - } - - /** - * Gets a secret from KV and validates that it is not null or empty. - * - * @param secretClient secret client - * @param secretName name of secret - * @return Secret value. This is guaranteed to be not null or empty. - */ - public static String getKeyVaultSecret(SecretClient secretClient, String secretName) { - Validators.checkNotNull(secretClient, "secretClient can't be null"); - Validators.checkNotNullAndNotEmpty(secretName, "secretName can't null or empty"); - KeyVaultSecret secret; - - try { - secret = secretClient.getSecret(secretName); - } catch (ResourceNotFoundException e) { - throw new AppException(HttpStatus.SC_NOT_FOUND, "partition not found", String.format("%s partition not found", secretName)); - } - - if (secret == null) { - throw new IllegalStateException(String.format("No secret found with name %s", secretName)); - } - - String secretValue = secret.getValue(); - if (secretValue == null) { - throw new IllegalStateException(String.format( - "Secret unexpectedly missing from KeyVault response for secret with name %s", secretName)); - } - - return secretValue; - } - - /** - * Set a secret in KV and validates that it is not null or empty. - * - * @param secretClient secret client - * @param secretName name of secret - * @param secretValue value of secret - * @return true if secrete is successfully created in KV. - */ - public static boolean createKeyVaultSecret(SecretClient secretClient, String secretName, String secretValue) { - Validators.checkNotNull(secretClient, "secretClient can't be null"); - Validators.checkNotNullAndNotEmpty(secretName, "secretName can't null or empty"); - Validators.checkNotNullAndNotEmpty(secretValue, "secretValue can't be null or empty"); - - KeyVaultSecret response; - try { - response = secretClient.setSecret(secretName, secretValue); - } catch (HttpResponseException e) { - throw new AppException(e.getResponse().getStatusCode(), e.getLocalizedMessage(), e.getMessage()); - } - - return response != null; - } - - /** - * Deletes a secret in KV. - * - * @param secretClient secret client - * @param secretName name of secret - * @return true if secrete is successfully deleted in KV. - */ - public static boolean deleteKeyVaultSecret(SecretClient secretClient, String secretName) { - Validators.checkNotNull(secretClient, "secretClient can't be null"); - Validators.checkNotNullAndNotEmpty(secretName, "secretName can't null or empty"); - - SyncPoller<DeletedSecret, Void> deletedSecretVoidSyncPoller = secretClient.beginDeleteSecret(secretName); - deletedSecretVoidSyncPoller.waitForCompletion(); - - return true; - } -} \ No newline at end of file diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/utils/ThreadPoolService.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/utils/ThreadPoolService.java deleted file mode 100644 index f0a6bcda6fb37b5c7dafb37846978c8a6c165eaa..0000000000000000000000000000000000000000 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/utils/ThreadPoolService.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017-2020, Schlumberger -// -// 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 org.opengroup.osdu.partition.provider.azure.utils; - -import org.springframework.stereotype.Component; - -import javax.annotation.PreDestroy; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -@Component -public class ThreadPoolService { - - private ExecutorService threadPool; - private final Object sync = new Object(); - - public ExecutorService getExecutorService() { - return this.threadPool; - } - - @PreDestroy - public void preDestroy() { - if (threadPool == null) { - return; - } - - threadPool.shutdown(); - try { - if (!threadPool.awaitTermination(600, TimeUnit.SECONDS)) { - threadPool.shutdownNow(); - } - } catch (InterruptedException ex) { - threadPool.shutdownNow(); - Thread.currentThread().interrupt(); - } - } - - public void createDeletePoolIfNeeded(int size) { - if (threadPool != null) { - return; - } - - synchronized (sync) { - if (threadPool == null) { - threadPool = new ThreadPoolExecutor(size, size * 10, - 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); - } - } - } -} \ No newline at end of file diff --git a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfigTest.java b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfigTest.java index 1f04bb50a9c3344bb156db2ed9d0e39069c7d2fc..c834ccb29699bd2dc7bdb54aed9b9d004f82cd14 100644 --- a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfigTest.java +++ b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/di/AzureBootstrapConfigTest.java @@ -17,33 +17,34 @@ package org.opengroup.osdu.partition.provider.azure.di; import com.azure.security.keyvault.secrets.SecretClient; import com.azure.security.keyvault.secrets.models.KeyVaultSecret; import org.junit.Test; -import org.mockito.Mockito; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; public class AzureBootstrapConfigTest { private AzureBootstrapConfig bootstrapConfig = new AzureBootstrapConfig(); - private SecretClient kv = Mockito.mock(SecretClient.class); + + private SecretClient kv = mock(SecretClient.class); @Test - public void config_returnsCorrectSecret_cosmosKey() { - KeyVaultSecret secret = Mockito.mock(KeyVaultSecret.class); - doReturn("cosmos-key-secret").when(secret).getValue(); - doReturn(secret).when(kv).getSecret("cosmos-primary-key"); + public void config_returnsCorrectSecret_tblStorage() { + KeyVaultSecret secret = mock(KeyVaultSecret.class); + doReturn("tbl-storage-secret").when(secret).getValue(); + doReturn(secret).when(kv).getSecret("tbl-storage"); - String secretValue = bootstrapConfig.cosmosKey(kv); - assertEquals("Secret value was incorrect", "cosmos-key-secret", secretValue); + String secretValue = bootstrapConfig.storageAccountName(kv); + assertEquals("Secret value was incorrect", "tbl-storage-secret", secretValue); } @Test - public void config_returnsCorrectSecret_cosmosEndpoint() { - KeyVaultSecret secret = Mockito.mock(KeyVaultSecret.class); - doReturn("cosmos-endpoint-secret").when(secret).getValue(); - doReturn(secret).when(kv).getSecret("cosmos-endpoint"); + public void config_returnsCorrectSecret_tblStorageKey() { + KeyVaultSecret secret = mock(KeyVaultSecret.class); + doReturn("tbl-storage-key-secret").when(secret).getValue(); + doReturn(secret).when(kv).getSecret("tbl-storage-key"); - String secretValue = bootstrapConfig.cosmosEndpoint(kv); - assertEquals("Secret value was incorrect", "cosmos-endpoint-secret", secretValue); + String secretValue = bootstrapConfig.storageAccountKey(kv); + assertEquals("Secret value was incorrect", "tbl-storage-key-secret", secretValue); } } \ No newline at end of file diff --git a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java index 52c7c8cffb0e8ec9aa31f97b721beb97d0b38737..020fcd0b20c7b5b29f88a7f60daa7f0197d454a5 100644 --- a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java +++ b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java @@ -14,72 +14,51 @@ package org.opengroup.osdu.partition.provider.azure.service; -import com.azure.core.exception.ResourceNotFoundException; -import com.azure.security.keyvault.secrets.SecretClient; -import com.azure.security.keyvault.secrets.models.KeyVaultSecret; -import com.microsoft.applicationinsights.TelemetryClient; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; -import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.partition.model.PartitionInfo; -import org.opengroup.osdu.partition.provider.azure.utils.KeyVaultFacade; -import org.opengroup.osdu.partition.provider.azure.utils.ThreadPoolService; -import org.powermock.core.classloader.annotations.PrepareForTest; +import org.opengroup.osdu.partition.model.Property; +import org.opengroup.osdu.partition.provider.azure.persistence.PartitionTableStore; import org.powermock.modules.junit4.PowerMockRunner; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.Executors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; @RunWith(PowerMockRunner.class) -@PrepareForTest(KeyVaultFacade.class) public class PartitionServiceImplTest { @Mock - private SecretClient keyVaultClient; - @Mock - private ThreadPoolService threadPoolService; - @Mock - private TelemetryClient telemetryClient; + private PartitionTableStore tableStore; @InjectMocks private PartitionServiceImpl sut; private PartitionInfo partitionInfo = new PartitionInfo(); - private KeyVaultSecret keyVaultSecret = new KeyVaultSecret("myKey", "myValue"); + private final static String PARTITION_ID = "my-tenant"; + private Map<String, Property> properties = new HashMap<>(); @Before public void setup() { - mockStatic(KeyVaultFacade.class); - - Map<String, Object> properties = new HashMap<>(); - properties.put("id", "my-tenant"); - properties.put("storageAccount", "storage-account"); - properties.put("complianceRuleSet", "compliance-rule-set"); + properties.put("id", Property.builder().value(PARTITION_ID).build()); + properties.put("storageAccount", Property.builder().value("storage-account").sensitive(true).build()); + properties.put("complianceRuleSet", Property.builder().value("compliance-rule-set").build()); partitionInfo.setProperties(properties); - doNothing().when(telemetryClient).trackException(any(Exception.class)); } @Test public void should_ThrowConflictError_when_createPartition_whenPartitionExists() { - when(keyVaultClient.getSecret(any())).thenReturn(keyVaultSecret); + when(this.tableStore.partitionExists(PARTITION_ID)).thenReturn(true); try { - sut.createPartition(this.partitionInfo.getProperties().get("id").toString(), this.partitionInfo); + sut.createPartition(PARTITION_ID, this.partitionInfo); } catch (AppException e) { assertTrue(e.getError().getCode() == 409); assertTrue(e.getError().getReason().equalsIgnoreCase("partition exist")); @@ -89,10 +68,9 @@ public class PartitionServiceImplTest { @Test public void should_returnPartitionInfo_when_createPartition_whenPartitionDoesntExist() { - when(keyVaultClient.getSecret(any())).thenThrow(ResourceNotFoundException.class); - when(keyVaultClient.setSecret(any(), any())).thenReturn(keyVaultSecret); + when(this.tableStore.partitionExists(PARTITION_ID)).thenReturn(false); - PartitionInfo partInfo = sut.createPartition(this.partitionInfo.getProperties().get("id").toString(), this.partitionInfo); + PartitionInfo partInfo = sut.createPartition(PARTITION_ID, this.partitionInfo); assertTrue(partInfo.getProperties().size() == 3); assertTrue(partInfo.getProperties().containsKey("id")); assertTrue(partInfo.getProperties().containsKey("complianceRuleSet")); @@ -101,28 +79,20 @@ public class PartitionServiceImplTest { @Test public void should_returnPartition_when_partitionExists() { - when(keyVaultClient.getSecret(any())).thenReturn(keyVaultSecret); - when(KeyVaultFacade.secretExists(any(), anyString())).thenReturn(true); - when(KeyVaultFacade.getKeyVaultSecrets(any(), anyString())).thenReturn(Arrays.asList("my-tenant-id", "my-tenant-complianceRuleSet", "my-tenant-groups")); - when(KeyVaultFacade.getKeyVaultSecret(this.keyVaultClient, "my-tenant-id")).thenReturn("my-tenant"); - when(KeyVaultFacade.getKeyVaultSecret(this.keyVaultClient, "my-tenant-groups")).thenReturn("[\"service.storage.admin\"]"); - when(KeyVaultFacade.getKeyVaultSecret(this.keyVaultClient, "my-tenant-complianceRuleSet")).thenReturn("shared"); - when(KeyVaultFacade.getKeyVaultSecret(this.keyVaultClient, "sp-appid")).thenReturn("servicePrincipal"); - - PartitionInfo partitionInfo = this.sut.getPartition(this.partitionInfo.getProperties().get("id").toString()); - assertTrue(partitionInfo.getProperties().containsValue("my-tenant")); - assertTrue(partitionInfo.getProperties().containsKey("groups")); + when(this.tableStore.getPartition(PARTITION_ID)).thenReturn(properties); + + PartitionInfo partitionInfo = this.sut.getPartition(PARTITION_ID); + assertTrue(partitionInfo.getProperties().containsKey("storageAccount")); assertTrue(partitionInfo.getProperties().containsKey("complianceRuleSet")); assertTrue(partitionInfo.getProperties().containsKey("id")); - assertTrue(partitionInfo.getProperties().containsKey("sp-appid")); } @Test public void should_throwNotFoundException_when_partitionDoesntExist() { - when(keyVaultClient.getSecret(any())).thenThrow(ResourceNotFoundException.class); + when(this.tableStore.getPartition(PARTITION_ID)).thenReturn(new HashMap<>()); try { - sut.getPartition(this.partitionInfo.getProperties().get("id").toString()); + sut.getPartition(PARTITION_ID); } catch (AppException e) { assertTrue(e.getError().getCode() == 404); assertTrue(e.getError().getReason().equalsIgnoreCase("partition not found")); @@ -132,17 +102,14 @@ public class PartitionServiceImplTest { @Test public void should_returnTrue_when_successfullyDeletingSecretes() { - when(KeyVaultFacade.secretExists(any(), anyString())).thenReturn(true); - when(KeyVaultFacade.getKeyVaultSecrets(any(), anyString())).thenReturn(Arrays.asList("dummy-id")); - when(KeyVaultFacade.deleteKeyVaultSecret(any(), anyString())).thenReturn(true); - when(this.threadPoolService.getExecutorService()).thenReturn(Executors.newFixedThreadPool(2)); + when(this.tableStore.partitionExists(PARTITION_ID)).thenReturn(true); - assertTrue(this.sut.deletePartition("test-partition")); + assertTrue(this.sut.deletePartition(PARTITION_ID)); } @Test public void should_throwException_when_deletingNonExistentPartition() { - when(KeyVaultFacade.getKeyVaultSecret(this.keyVaultClient, "test-partition-id")).thenReturn(""); + when(this.tableStore.partitionExists(PARTITION_ID)).thenReturn(false); try { this.sut.deletePartition("test-partition"); diff --git a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/utils/KeyVaultFacadeTest.java b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/utils/KeyVaultFacadeTest.java deleted file mode 100644 index 16e72abee4ff7df2c2b700be36f9b0a374f3d44d..0000000000000000000000000000000000000000 --- a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/utils/KeyVaultFacadeTest.java +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2017-2020, Schlumberger -// -// 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 org.opengroup.osdu.partition.provider.azure.utils; - -import com.azure.core.exception.HttpResponseException; -import com.azure.core.exception.ResourceNotFoundException; -import com.azure.core.http.rest.PagedIterable; -import com.azure.core.http.rest.PagedResponse; -import com.azure.core.util.polling.SyncPoller; -import com.azure.security.keyvault.secrets.SecretClient; -import com.azure.security.keyvault.secrets.models.DeletedSecret; -import com.azure.security.keyvault.secrets.models.KeyVaultSecret; -import com.azure.security.keyvault.secrets.models.SecretProperties; -import com.azure.core.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import org.opengroup.osdu.core.common.model.http.AppException; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class KeyVaultFacadeTest { - - @Mock - private SecretClient kv; - - @Mock - private KeyVaultSecret keyVaultSecret; - - @Mock - private PagedIterable<SecretProperties> secretProperties; - - @Mock - private Iterable<PagedResponse<SecretProperties>> propertiesIterable; - - @Mock - private Iterator<PagedResponse<SecretProperties>> iterator; - - @Mock - private PagedResponse<SecretProperties> resp; - - @Mock - private KeyVaultSecret secret; - - @Mock - private SyncPoller<DeletedSecret, Void> deletedSecretVoidSyncPoller; - - @Test - public void should_returnTrue_ifSecretExists() { - when(kv.getSecret(any())).thenReturn(keyVaultSecret); - assertTrue(KeyVaultFacade.secretExists(kv, "secret")); - } - - @Test - public void should_returnFalse_ifSecretNotExists() { - when(kv.getSecret(any())).thenThrow(mock(ResourceNotFoundException.class)); - assertFalse(KeyVaultFacade.secretExists(kv, "secret")); - } - - @Test - public void should_returnCorrectSecrets() { - List<SecretProperties> secretPropertyItems = new ArrayList<>(); - SecretProperties secretProperty = mock(SecretProperties.class); - secretPropertyItems.add(secretProperty); - final String key = "cosmos-endpoint-secret"; - - when(kv.listPropertiesOfSecrets()).thenReturn(secretProperties); - when(secretProperties.iterableByPage()).thenReturn(propertiesIterable); - when(propertiesIterable.iterator()).thenReturn(iterator); - when(iterator.hasNext()).thenReturn(true, false); - when(iterator.next()).thenReturn(resp); - when(resp.getItems()).thenReturn(secretPropertyItems); - when(secretProperty.getName()).thenReturn(key); - - assertEquals(Collections.singletonList(key), KeyVaultFacade.getKeyVaultSecrets(kv, "cosmos-endpoint-secret")); - } - - @Test - public void should_throwNotFoundException_ifPartitionNotFound() { - when(kv.getSecret(any())).thenThrow(ResourceNotFoundException.class); - - try { - KeyVaultFacade.getKeyVaultSecret(kv, "secret"); - fail("Method didn't throw when I expected it to"); - } catch (AppException e) { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getError().getCode()); - assertEquals("secret partition not found", e.getError().getMessage()); - } catch (Exception e) { - fail("Wrong exception is thrown"); - } - } - - @Test - public void should_throwIllegalStateException_ifSecretIsNull() { - when(kv.getSecret(any())).thenReturn(null); - - try { - KeyVaultFacade.getKeyVaultSecret(kv, "secret"); - fail("Method didn't throw when I expected it to"); - } catch (IllegalStateException e) { - assertEquals("No secret found with name secret", e.getMessage()); - } catch (Exception e) { - fail("Wrong exception is thrown"); - } - - when(kv.getSecret(any())).thenReturn(secret); - - try { - KeyVaultFacade.getKeyVaultSecret(kv, "secret"); - fail("Method didn't throw when I expected it to"); - } catch (IllegalStateException e) { - assertEquals("Secret unexpectedly missing from KeyVault response for secret with name secret", e.getMessage()); - } catch (Exception e) { - fail("Wrong exception is thrown"); - } - } - - @Test - public void should_returnTrue_CreateKeyVaultSecretSuccessfully() { - when(kv.setSecret(any(), any())).thenReturn(secret); - assertTrue(KeyVaultFacade.createKeyVaultSecret(kv, "secret", "value")); - } - - @Test - public void should_throwAppResponseException_ifHttpResponseExceptionThrown() { - HttpResponseException httpResponseException = mock(HttpResponseException.class); - HttpResponse response = mock(HttpResponse.class); - when(kv.setSecret(any(), any())).thenThrow(httpResponseException); - when(httpResponseException.getResponse()).thenReturn(response); - when(response.getStatusCode()).thenReturn(500); - when(httpResponseException.getLocalizedMessage()).thenReturn("error"); - when(httpResponseException.getMessage()).thenReturn("error"); - - try { - KeyVaultFacade.createKeyVaultSecret(kv, "secret", "value"); - fail("Method didn't throw when I expected it to"); - } catch (AppException e) { - assertEquals(500, e.getError().getCode()); - } catch (Exception e) { - fail("Wrong exception is thrown"); - } - } - @Test - public void should_returnTrue_DeleteKeyVaultSecretSuccessfully() { - when(kv.beginDeleteSecret(any())).thenReturn(deletedSecretVoidSyncPoller); - when(deletedSecretVoidSyncPoller.waitForCompletion()).thenReturn(null); - assertTrue(KeyVaultFacade.deleteKeyVaultSecret(kv, "secret")); - } -} \ No newline at end of file diff --git a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/utils/ThreadPoolServiceTest.java b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/utils/ThreadPoolServiceTest.java deleted file mode 100644 index b3e9e1d4f7430e9e3085d75168d5b55f3acdcf32..0000000000000000000000000000000000000000 --- a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/utils/ThreadPoolServiceTest.java +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017-2020, Schlumberger -// -// 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 org.opengroup.osdu.partition.provider.azure.utils; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -@RunWith(MockitoJUnitRunner.class) -public class ThreadPoolServiceTest { - - @Test - public void createAndDestroyPool() { - ThreadPoolService threadPoolService = new ThreadPoolService(); - - assertNull(threadPoolService.getExecutorService()); - - threadPoolService.createDeletePoolIfNeeded(1); - - assertNotNull(threadPoolService.getExecutorService()); - - threadPoolService.preDestroy(); - } -} \ No newline at end of file diff --git a/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestCreatePartition.java b/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestCreatePartition.java index b416b35351465ea4afcbcd3487c7a571500e088b..0b1348d696953b698eda25d1bddfbe2ba37910b5 100644 --- a/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestCreatePartition.java +++ b/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestCreatePartition.java @@ -31,5 +31,4 @@ public class TestCreatePartition extends CreatePartitionTest { public void tearDown() { this.testUtils = null; } - } diff --git a/testing/partition-test-core/src/main/java/org/opengroup/osdu/partition/api/descriptor/CreatePartitionDescriptor.java b/testing/partition-test-core/src/main/java/org/opengroup/osdu/partition/api/descriptor/CreatePartitionDescriptor.java index 95271f89b93781b108bbe439770c03299178a444..b4fab4493de7a6deff6478188753c62be947cde4 100644 --- a/testing/partition-test-core/src/main/java/org/opengroup/osdu/partition/api/descriptor/CreatePartitionDescriptor.java +++ b/testing/partition-test-core/src/main/java/org/opengroup/osdu/partition/api/descriptor/CreatePartitionDescriptor.java @@ -37,19 +37,9 @@ public class CreatePartitionDescriptor extends RestDescriptor { sb.append("{\n"); sb.append(" \"properties\": {") .append("\"id\": \"").append(this.arg()).append("\",") - .append("\"elasticPassword\": \"test-password\",") - .append("\"serviceBusConnection\": \"test-service-bus-connection\",") - .append("\"serviceprincipalAppId\": \"test-sp\",") - .append("\"serviceBusNamespace\": \"test-service-bus\",") - .append("\"elasticUsername\": \"test-password\",") - .append("\"cosmosEndpoint\": \"test-comos-endpoint\",") - .append("\"elasticEndpoint\": \"test-elastic-endpoint\",") - .append("\"cosmosPrimaryKey\": \"test-cosmos-primary-key\",") - .append("\"groups\": \"test-groups\",") - .append("\"storageAccount\": \"test-storage-account\",") - .append("\"complianceRuleSet\": \"test-compliance-ruleSet\",") - .append("\"cosmosConnection\": \"test-cosmos-connection\",") - .append("\"storageAccountKey\": \"test-storage-accountKey\"") + .append("\"elasticPassword\": {\"sensitive\":true,\"value\":\"test-password\"},") + .append("\"serviceBusConnection\": {\"sensitive\":true,\"value\":\"test-service-bus-connection\"},") + .append("\"cosmosConnection\": \"test-cosmos-connection\"") .append("}\n") .append("}"); return sb.toString();