Search in sources :

Example 1 with GrantRoleRequestBody

use of bio.terra.workspace.model.GrantRoleRequestBody in project terra-workspace-manager by DataBiosphere.

the class ControlledApplicationSharedGcsBucketLifecycle method doUserJourney.

@Override
public void doUserJourney(TestUserSpecification unused, WorkspaceApi workspaceApi) throws Exception {
    ApiClient ownerApiClient = ClientTestUtils.getClientForTestUser(owner, server);
    ApiClient wsmappApiClient = ClientTestUtils.getClientForTestUser(wsmapp, server);
    WorkspaceApplicationApi ownerWsmAppApi = new WorkspaceApplicationApi(ownerApiClient);
    ControlledGcpResourceApi wsmappResourceApi = new ControlledGcpResourceApi(wsmappApiClient);
    // Owner adds a reader and a writer to the workspace
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(reader.userEmail), getWorkspaceId(), IamRole.READER);
    logger.info("Added {} as a reader to workspace {}", reader.userEmail, getWorkspaceId());
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(writer.userEmail), getWorkspaceId(), IamRole.WRITER);
    logger.info("Added {} as a writer to workspace {}", writer.userEmail, getWorkspaceId());
    // Create the cloud context
    String projectId = CloudContextMaker.createGcpCloudContext(getWorkspaceId(), workspaceApi);
    assertNotNull(projectId);
    logger.info("Created project {}", projectId);
    // Create the bucket - should fail because application is not enabled
    String bucketResourceName = RandomStringUtils.random(6, true, false);
    ApiException createBucketFails = assertThrows(ApiException.class, () -> GcsBucketUtils.makeControlledGcsBucketAppShared(wsmappResourceApi, getWorkspaceId(), bucketResourceName, CloningInstructionsEnum.NOTHING));
    // TODO: [PF-1208] this should be FORBIDDEN (403), but we are throwing the wrong thing
    assertEquals(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED, createBucketFails.getCode());
    logger.info("Failed to create bucket, as expected");
    // Enable the application in the workspace
    WorkspaceApplicationDescription applicationDescription = ownerWsmAppApi.enableWorkspaceApplication(getWorkspaceId(), TEST_WSM_APP);
    assertThat(applicationDescription.getApplicationState(), equalTo(ApplicationState.OPERATING));
    logger.info("Enabled application in the workspace");
    // Validate that it is enabled
    WorkspaceApplicationDescription retrievedDescription = ownerWsmAppApi.getWorkspaceApplication(getWorkspaceId(), TEST_WSM_APP);
    assertThat(applicationDescription, equalTo(retrievedDescription));
    assertThat(applicationDescription.getWorkspaceApplicationState(), equalTo(WorkspaceApplicationState.ENABLED));
    // Create the bucket - should work this time
    CreatedControlledGcpGcsBucket createdBucket = GcsBucketUtils.makeControlledGcsBucketAppShared(wsmappResourceApi, getWorkspaceId(), bucketResourceName, CloningInstructionsEnum.NOTHING);
    bucketName = createdBucket.getGcpBucket().getAttributes().getBucketName();
    assertNotNull(bucketName);
    logger.info("Created bucket {}", bucketName);
    // Try to disable; should error because you cannot disable an app if it owns resources
    // in the workspace.
    ApiException disableAppFails = assertThrows(ApiException.class, () -> ownerWsmAppApi.disableWorkspaceApplication(getWorkspaceId(), TEST_WSM_APP));
    assertEquals(HttpStatusCodes.STATUS_CODE_BAD_REQUEST, disableAppFails.getCode());
    logger.info("Failed to disable app, as expected");
    try (GcsBucketAccessTester tester = new GcsBucketAccessTester(wsmapp, bucketName, projectId)) {
        tester.checkAccess(wsmapp, ControlledResourceIamRole.EDITOR);
        tester.checkAccess(owner, ControlledResourceIamRole.WRITER);
        tester.checkAccess(writer, ControlledResourceIamRole.WRITER);
        tester.checkAccess(reader, ControlledResourceIamRole.READER);
    }
    // The reader should be able to enumerate the bucket.
    ResourceApi readerResourceApi = ClientTestUtils.getResourceClient(reader, server);
    ResourceList bucketList = readerResourceApi.enumerateResources(getWorkspaceId(), 0, 5, ResourceType.GCS_BUCKET, StewardshipType.CONTROLLED);
    assertEquals(1, bucketList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.GCS_BUCKET, bucketList);
    // Owner cannot delete the bucket through WSM
    ControlledGcpResourceApi ownerResourceApi = new ControlledGcpResourceApi(ownerApiClient);
    ApiException cannotDelete = assertThrows(ApiException.class, () -> GcsBucketUtils.deleteControlledGcsBucket(createdBucket.getResourceId(), getWorkspaceId(), ownerResourceApi));
    // TODO: [PF-1208] this should be FORBIDDEN (403), but we are throwing the wrong thing
    assertEquals(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED, cannotDelete.getCode());
    logger.info("Owner delete failed as expected");
    // Application can delete the bucket through WSM
    GcsBucketUtils.deleteControlledGcsBucket(createdBucket.getResourceId(), getWorkspaceId(), wsmappResourceApi);
    logger.info("Application delete succeeded");
}
Also used : ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) WorkspaceApplicationApi(bio.terra.workspace.api.WorkspaceApplicationApi) WorkspaceApplicationDescription(bio.terra.workspace.model.WorkspaceApplicationDescription) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ApiClient(bio.terra.workspace.client.ApiClient) ApiException(bio.terra.workspace.client.ApiException) CreatedControlledGcpGcsBucket(bio.terra.workspace.model.CreatedControlledGcpGcsBucket) GcsBucketAccessTester(scripts.utils.GcsBucketAccessTester)

Example 2 with GrantRoleRequestBody

use of bio.terra.workspace.model.GrantRoleRequestBody in project terra-workspace-manager by DataBiosphere.

the class PrivateControlledGcsBucketLifecycle method doUserJourney.

@Override
public void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    String projectId = CloudContextMaker.createGcpCloudContext(getWorkspaceId(), workspaceApi);
    ControlledGcpResourceApi workspaceOwnerResourceApi = ClientTestUtils.getControlledGcpResourceClient(testUser, server);
    ControlledGcpResourceApi privateUserResourceApi = ClientTestUtils.getControlledGcpResourceClient(privateResourceUser, server);
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(workspaceReader.userEmail), getWorkspaceId(), IamRole.READER);
    logger.info("Added {} as a reader to workspace {}", workspaceReader.userEmail, getWorkspaceId());
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(privateResourceUser.userEmail), getWorkspaceId(), IamRole.WRITER);
    logger.info("Added {} as a writer to workspace {}", privateResourceUser.userEmail, getWorkspaceId());
    // Create a private bucket, which privateResourceUser assigns to themselves.
    // Cloud IAM permissions may take several minutes to sync, so we retry this operation until
    // it succeeds.
    CreatedControlledGcpGcsBucket bucket = ClientTestUtils.getWithRetryOnException(() -> createPrivateBucket(privateUserResourceApi));
    UUID resourceId = bucket.getResourceId();
    // Retrieve the bucket resource from WSM
    logger.info("Retrieving bucket resource id {}", resourceId.toString());
    GcpGcsBucketResource gotBucket = privateUserResourceApi.getBucket(getWorkspaceId(), resourceId);
    String bucketName = gotBucket.getAttributes().getBucketName();
    assertEquals(bucket.getGcpBucket().getAttributes().getBucketName(), bucketName);
    // Assert the bucket is assigned to privateResourceUser, even though resource user was
    // not specified
    assertEquals(privateResourceUser.userEmail, gotBucket.getMetadata().getControlledResourceMetadata().getPrivateResourceUser().getUserName());
    try (GcsBucketAccessTester tester = new GcsBucketAccessTester(privateResourceUser, bucketName, projectId)) {
        tester.checkAccessWait(privateResourceUser, ControlledResourceIamRole.EDITOR);
        // workspace owner can do nothing
        tester.checkAccess(testUser, null);
        tester.checkAccess(workspaceReader, null);
    }
    // Any workspace user should be able to enumerate all buckets, even though they can't access
    // their contents.
    ResourceApi readerApi = ClientTestUtils.getResourceClient(workspaceReader, server);
    ResourceList bucketList = readerApi.enumerateResources(getWorkspaceId(), 0, 5, ResourceType.GCS_BUCKET, StewardshipType.CONTROLLED);
    assertEquals(1, bucketList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.GCS_BUCKET, bucketList);
    // Workspace owner has DELETER role and can delete the bucket through WSM
    var ownerDeleteResult = deleteBucket(workspaceOwnerResourceApi, resourceId);
    ClientTestUtils.assertJobSuccess("owner delete bucket", ownerDeleteResult.getJobReport(), ownerDeleteResult.getErrorReport());
    // verify the bucket was deleted from WSM metadata
    ApiException bucketIsMissing = assertThrows(ApiException.class, () -> workspaceOwnerResourceApi.getBucket(getWorkspaceId(), resourceId), "Incorrectly found a deleted bucket!");
    assertEquals(HttpStatusCodes.STATUS_CODE_NOT_FOUND, bucketIsMissing.getCode());
    // also verify it was deleted from GCP
    Storage ownerStorageClient = ClientTestUtils.getGcpStorageClient(testUser, projectId);
    Bucket maybeBucket = ownerStorageClient.get(bucketName);
    assertNull(maybeBucket);
    // TODO: PF-1218 - change these to negative tests - should error - when
    // the ticket is complete. These exercise two create cases with currently
    // valid combinations of private user.
    PrivateResourceIamRoles roles = new PrivateResourceIamRoles();
    roles.add(ControlledResourceIamRole.READER);
    // Supply all private user parameters
    PrivateResourceUser privateUserFull = new PrivateResourceUser().userName(privateResourceUser.userEmail).privateResourceIamRoles(roles);
    CreatedControlledGcpGcsBucket userFullBucket = GcsBucketUtils.makeControlledGcsBucket(privateUserResourceApi, getWorkspaceId(), RESOURCE_PREFIX + UUID.randomUUID().toString(), /*bucketName=*/
    null, AccessScope.PRIVATE_ACCESS, ManagedBy.USER, CloningInstructionsEnum.NOTHING, privateUserFull);
    assertNotNull(userFullBucket.getGcpBucket().getAttributes().getBucketName());
    deleteBucket(workspaceOwnerResourceApi, userFullBucket.getResourceId());
    // Supply just the roles, but no email
    PrivateResourceUser privateUserNoEmail = new PrivateResourceUser().userName(null).privateResourceIamRoles(roles);
    CreatedControlledGcpGcsBucket userNoEmailBucket = GcsBucketUtils.makeControlledGcsBucket(privateUserResourceApi, getWorkspaceId(), RESOURCE_PREFIX + UUID.randomUUID().toString(), /*bucketName=*/
    null, AccessScope.PRIVATE_ACCESS, ManagedBy.USER, CloningInstructionsEnum.NOTHING, privateUserNoEmail);
    assertNotNull(userNoEmailBucket.getGcpBucket().getAttributes().getBucketName());
    deleteBucket(workspaceOwnerResourceApi, userNoEmailBucket.getResourceId());
    String uniqueBucketName = String.format("terra_%s_bucket", UUID.randomUUID().toString().replace("-", "_"));
    CreatedControlledGcpGcsBucket bucketWithBucketNameSpecified = GcsBucketUtils.makeControlledGcsBucket(privateUserResourceApi, getWorkspaceId(), RESOURCE_PREFIX + UUID.randomUUID().toString(), /*bucketName=*/
    uniqueBucketName, AccessScope.PRIVATE_ACCESS, ManagedBy.USER, CloningInstructionsEnum.NOTHING, privateUserFull);
    assertEquals(uniqueBucketName, bucketWithBucketNameSpecified.getGcpBucket().getAttributes().getBucketName());
    deleteBucket(workspaceOwnerResourceApi, bucketWithBucketNameSpecified.getResourceId());
}
Also used : GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) PrivateResourceUser(bio.terra.workspace.model.PrivateResourceUser) GcsBucketAccessTester(scripts.utils.GcsBucketAccessTester) GcpGcsBucketResource(bio.terra.workspace.model.GcpGcsBucketResource) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) Storage(com.google.cloud.storage.Storage) Bucket(com.google.cloud.storage.Bucket) CreatedControlledGcpGcsBucket(bio.terra.workspace.model.CreatedControlledGcpGcsBucket) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) UUID(java.util.UUID) PrivateResourceIamRoles(bio.terra.workspace.model.PrivateResourceIamRoles) CreatedControlledGcpGcsBucket(bio.terra.workspace.model.CreatedControlledGcpGcsBucket) ApiException(bio.terra.workspace.client.ApiException)

Example 3 with GrantRoleRequestBody

use of bio.terra.workspace.model.GrantRoleRequestBody in project terra-workspace-manager by DataBiosphere.

the class ReferencedDataRepoSnapshotLifecycle method doUserJourney.

@Override
protected void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    ReferencedGcpResourceApi referencedGcpResourceApi = ClientTestUtils.getReferencedGcpResourceClient(testUser, server);
    // Add the "partial access" user as a workspace reader. This does not give them access to any
    // underlying referenced resources.
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(partialAccessUser.userEmail), getWorkspaceId(), IamRole.READER);
    // Create the reference
    DataRepoSnapshotResource snapshotResource = DataRepoUtils.makeDataRepoSnapshotReference(referencedGcpResourceApi, getWorkspaceId(), MultiResourcesUtils.makeName(), snapshotId, tdrInstance);
    snapshotResourceId = snapshotResource.getMetadata().getResourceId();
    // Get the reference
    ResourceApi resourceApi = ClientTestUtils.getResourceClient(testUser, server);
    testGetReference(snapshotResource, referencedGcpResourceApi, resourceApi);
    // Create a second workspace to clone the reference into, owned by the same user
    testCloneReference(snapshotResource, referencedGcpResourceApi, workspaceApi);
    // Validate snapshot access
    testValidateReference(testUser);
    // Update reference
    testUpdateReference(referencedGcpResourceApi);
    // Delete the reference
    referencedGcpResourceApi.deleteDataRepoSnapshotReference(getWorkspaceId(), snapshotResourceId);
    // Enumerating all resources with no filters should be empty
    ResourceList enumerateResult = resourceApi.enumerateResources(getWorkspaceId(), 0, 100, null, null);
    assertTrue(enumerateResult.getResources().isEmpty());
}
Also used : ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi) DataRepoSnapshotResource(bio.terra.workspace.model.DataRepoSnapshotResource)

Example 4 with GrantRoleRequestBody

use of bio.terra.workspace.model.GrantRoleRequestBody in project terra-workspace-manager by DataBiosphere.

the class ControlledApplicationPrivateGcsBucketLifecycle method doUserJourney.

@Override
public void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    ApiClient ownerApiClient = ClientTestUtils.getClientForTestUser(owner, server);
    ApiClient wsmappApiClient = ClientTestUtils.getClientForTestUser(wsmapp, server);
    WorkspaceApplicationApi ownerWsmAppApi = new WorkspaceApplicationApi(ownerApiClient);
    ControlledGcpResourceApi wsmappResourceApi = new ControlledGcpResourceApi(wsmappApiClient);
    // Owner adds a reader and a writer to the workspace
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(reader.userEmail), getWorkspaceId(), IamRole.READER);
    logger.info("Added {} as a reader to workspace {}", reader.userEmail, getWorkspaceId());
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(writer.userEmail), getWorkspaceId(), IamRole.WRITER);
    logger.info("Added {} as a writer to workspace {}", writer.userEmail, getWorkspaceId());
    // Create the cloud context
    String projectId = CloudContextMaker.createGcpCloudContext(getWorkspaceId(), workspaceApi);
    assertNotNull(projectId);
    logger.info("Created project {}", projectId);
    // Enable the application in the workspace
    WorkspaceApplicationDescription applicationDescription = ownerWsmAppApi.enableWorkspaceApplication(getWorkspaceId(), TEST_WSM_APP);
    assertThat(applicationDescription.getApplicationState(), equalTo(ApplicationState.OPERATING));
    logger.info("Enabled application {} in the workspace {}", TEST_WSM_APP, getWorkspaceId());
    // CASE 1: Create a bucket with no assigned user
    testNoAssignedUser(wsmappResourceApi, projectId);
    // CASE 2: Create a bucket with workspace writer as READER
    testAssignedReader(wsmappResourceApi, projectId);
    // CASE 3: Create a bucket with workspace reader as WRITER
    testAssignedWriter(wsmappResourceApi, projectId);
    // All buckets should be visible to enumeration
    ResourceApi ownerResourceApi = ClientTestUtils.getResourceClient(owner, server);
    ResourceList bucketList = ownerResourceApi.enumerateResources(getWorkspaceId(), 0, 5, ResourceType.GCS_BUCKET, StewardshipType.CONTROLLED);
    assertEquals(3, bucketList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.GCS_BUCKET, bucketList);
}
Also used : ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) WorkspaceApplicationApi(bio.terra.workspace.api.WorkspaceApplicationApi) WorkspaceApplicationDescription(bio.terra.workspace.model.WorkspaceApplicationDescription) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ApiClient(bio.terra.workspace.client.ApiClient)

Example 5 with GrantRoleRequestBody

use of bio.terra.workspace.model.GrantRoleRequestBody in project terra-workspace-manager by DataBiosphere.

the class ControlledBigQueryDatasetLifecycle method doUserJourney.

@Override
protected void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    ControlledGcpResourceApi ownerResourceApi = ClientTestUtils.getControlledGcpResourceClient(testUser, server);
    // Add a writer the source workspace. Reader is already added by the base class
    logger.info("Adding {} as writer to workspace {}", writer.userEmail, getWorkspaceId());
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(writer.userEmail), getWorkspaceId(), IamRole.WRITER);
    SamClientUtils.dumpResourcePolicy(testUser, server, "workspace", getWorkspaceId().toString());
    // Create a shared BigQuery dataset
    GcpBigQueryDatasetResource createdDataset = BqDatasetUtils.makeControlledBigQueryDatasetUserShared(ownerResourceApi, getWorkspaceId(), DATASET_RESOURCE_NAME, /*datasetId=*/
    null, /*cloningInstructions=*/
    null);
    assertEquals(DATASET_RESOURCE_NAME, createdDataset.getAttributes().getDatasetId());
    UUID resourceId = createdDataset.getMetadata().getResourceId();
    // Retrieve the dataset resource
    logger.info("Retrieving dataset resource id {}", resourceId.toString());
    GcpBigQueryDatasetResource fetchedResource = ownerResourceApi.getBigQueryDataset(getWorkspaceId(), resourceId);
    assertEquals(createdDataset, fetchedResource);
    assertEquals(DATASET_RESOURCE_NAME, fetchedResource.getAttributes().getDatasetId());
    createControlledDatasetWithBothResourceNameAndDatasetIdSpecified(ownerResourceApi);
    BigQuery ownerBqClient = ClientTestUtils.getGcpBigQueryClient(testUser, getSourceProjectId());
    BigQuery writerBqClient = ClientTestUtils.getGcpBigQueryClient(writer, getSourceProjectId());
    BigQuery readerBqClient = ClientTestUtils.getGcpBigQueryClient(getWorkspaceReader(), getSourceProjectId());
    // Workspace owner can create a table in this dataset
    Table table = createTable(ownerBqClient, getSourceProjectId());
    String tableName = table.getTableId().getTable();
    // Workspace reader can read the table
    // This is the reader's first use of cloud APIs after being added to the workspace, so we
    // retry this operation until cloud IAM has properly synced.
    var readTable = ClientTestUtils.getWithRetryOnException(() -> readerBqClient.getTable(table.getTableId()));
    assertEquals(table, readTable);
    logger.info("Read table {} as workspace reader", tableName);
    // Workspace reader cannot modify tables
    Table readerUpdatedTable = table.toBuilder().setDescription("A new table description").build();
    assertThrows(BigQueryException.class, () -> readerBqClient.update(readerUpdatedTable), "Workspace reader was able to modify table metadata");
    logger.info("Workspace reader could not modify table {} metadata as expected", tableName);
    // Workspace reader cannot write data to tables
    assertThrows(BigQueryException.class, () -> insertValueIntoTable(readerBqClient, "some value"), "Workspace reader was able to insert data into a table");
    logger.info("Workspace reader could not modify table {} contents as expected", tableName);
    // Workspace writer can also read the table
    // This is the writer's first use of cloud APIs after being added to the workspace, so we
    // retry this operation until cloud IAM has properly synced.
    var writerReadTable = ClientTestUtils.getWithRetryOnException(() -> writerBqClient.getTable(table.getTableId()));
    assertEquals(table, writerReadTable);
    logger.info("Read table {} as workspace writer", tableName);
    // In contrast, a workspace writer can write data to tables
    String columnValue = "this value lives in a table";
    insertValueIntoTable(writerBqClient, columnValue);
    logger.info("Workspace writer wrote a row to table {}", tableName);
    // Create a dataset to hold query results in the destination project.
    ControlledGcpResourceApi readerResourceApi = ClientTestUtils.getControlledGcpResourceClient(getWorkspaceReader(), server);
    String resultDatasetId = "temporary_result_dataset";
    GcpBigQueryDatasetResource temporaryResultDataset = BqDatasetUtils.makeControlledBigQueryDatasetUserShared(readerResourceApi, getDestinationWorkspaceId(), "temporary_result_resource", resultDatasetId, CloningInstructionsEnum.NOTHING);
    // The table does not exist yet, but will be created to hold query results.
    TableId resultTableId = TableId.of(getDestinationProjectId(), resultDatasetId, BqDatasetUtils.BQ_RESULT_TABLE_NAME);
    // Workspace reader can now read the row inserted above
    assertEquals(columnValue, readValueFromTable(readerBqClient, resultTableId));
    logger.info("Workspace reader read that row from table {}", tableName);
    // Workspace writer can update the table metadata
    String newDescription = "Another new table description";
    Table writerUpdatedTable = table.toBuilder().setDescription(newDescription).build();
    Table updatedTable = writerBqClient.update(writerUpdatedTable);
    assertEquals(newDescription, updatedTable.getDescription());
    logger.info("Workspace writer modified table {} metadata", tableName);
    // Workspace owner can update the dataset resource through WSM
    String resourceDescription = "a description for WSM";
    Integer defaultTableLifetimeSec = 5400;
    var updateDatasetRequest = new UpdateControlledGcpBigQueryDatasetRequestBody().description(resourceDescription).updateParameters(new GcpBigQueryDatasetUpdateParameters().defaultTableLifetime(defaultTableLifetimeSec));
    ownerResourceApi.updateBigQueryDataset(updateDatasetRequest, getWorkspaceId(), resourceId);
    var datasetAfterUpdate = ownerResourceApi.getBigQueryDataset(getWorkspaceId(), resourceId);
    assertEquals(datasetAfterUpdate.getMetadata().getDescription(), resourceDescription);
    logger.info("Workspace owner updated resource {}", resourceId);
    // However, invalid updates are rejected.
    String invalidName = "!!!invalid_name!!!";
    var invalidUpdateDatasetRequest = new UpdateControlledGcpBigQueryDatasetRequestBody().name(invalidName);
    ApiException invalidUpdateEx = assertThrows(ApiException.class, () -> ownerResourceApi.updateBigQueryDataset(invalidUpdateDatasetRequest, getWorkspaceId(), resourceId));
    assertEquals(HttpStatusCodes.STATUS_CODE_BAD_REQUEST, invalidUpdateEx.getCode());
    // Cloud metadata matches the updated values
    Dataset cloudDataset = ownerBqClient.getDataset(DatasetId.of(getSourceProjectId(), DATASET_RESOURCE_NAME));
    assertEquals(defaultTableLifetimeSec * 1000L, cloudDataset.getDefaultTableLifetime());
    assertNull(cloudDataset.getDefaultPartitionExpirationMs());
    // Workspace writer can delete the table we created earlier
    logger.info("Deleting table {} from dataset {}", table.getTableId().getTable(), DATASET_RESOURCE_NAME);
    assertTrue(writerBqClient.delete(TableId.of(getSourceProjectId(), DATASET_RESOURCE_NAME, table.getTableId().getTable())));
    // Workspace reader can clean up the results table and dataset before cloning
    readerResourceApi.deleteBigQueryDataset(getDestinationWorkspaceId(), temporaryResultDataset.getMetadata().getResourceId());
    // Populate dataset with additional tables to verify cloning behavior
    BqDatasetUtils.populateBigQueryDataset(createdDataset, testUser, getSourceProjectId());
    // Verify workspace reader is able to clone the resource they can read
    testCloneBigQueryDataset(createdDataset, getWorkspaceReader(), readerResourceApi);
    // The reader should be able to enumerate the dataset.
    ResourceApi readerApi = ClientTestUtils.getResourceClient(getWorkspaceReader(), server);
    ResourceList datasetList = readerApi.enumerateResources(getWorkspaceId(), 0, 5, ResourceType.BIG_QUERY_DATASET, StewardshipType.CONTROLLED);
    assertEquals(1, datasetList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.BIG_QUERY_DATASET, datasetList);
    // Workspace writer cannot delete the dataset directly
    var writerCannotDeleteException = assertThrows(BigQueryException.class, () -> writerBqClient.delete(DATASET_RESOURCE_NAME));
    assertEquals(HttpStatusCodes.STATUS_CODE_FORBIDDEN, writerCannotDeleteException.getCode());
    // Workspace owner cannot delete the dataset directly
    var ownerCannotDeleteException = assertThrows(BigQueryException.class, () -> ownerBqClient.delete(DATASET_RESOURCE_NAME));
    assertEquals(HttpStatusCodes.STATUS_CODE_FORBIDDEN, ownerCannotDeleteException.getCode());
    // Workspace owner can delete the dataset through WSM
    ownerResourceApi.deleteBigQueryDataset(getWorkspaceId(), resourceId);
}
Also used : TableId(com.google.cloud.bigquery.TableId) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) BigQuery(com.google.cloud.bigquery.BigQuery) Table(com.google.cloud.bigquery.Table) ClonedControlledGcpBigQueryDataset(bio.terra.workspace.model.ClonedControlledGcpBigQueryDataset) Dataset(com.google.cloud.bigquery.Dataset) GcpBigQueryDatasetUpdateParameters(bio.terra.workspace.model.GcpBigQueryDatasetUpdateParameters) GcpBigQueryDatasetResource(bio.terra.workspace.model.GcpBigQueryDatasetResource) UpdateControlledGcpBigQueryDatasetRequestBody(bio.terra.workspace.model.UpdateControlledGcpBigQueryDatasetRequestBody) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) UUID(java.util.UUID) ApiException(bio.terra.workspace.client.ApiException)

Aggregations

GrantRoleRequestBody (bio.terra.workspace.model.GrantRoleRequestBody)14 ResourceApi (bio.terra.workspace.api.ResourceApi)9 ResourceList (bio.terra.workspace.model.ResourceList)9 ControlledGcpResourceApi (bio.terra.workspace.api.ControlledGcpResourceApi)8 ReferencedGcpResourceApi (bio.terra.workspace.api.ReferencedGcpResourceApi)5 ApiException (bio.terra.workspace.client.ApiException)5 TestUserSpecification (bio.terra.testrunner.runner.config.TestUserSpecification)4 UUID (java.util.UUID)4 WorkspaceApi (bio.terra.workspace.api.WorkspaceApi)3 ApiClient (bio.terra.workspace.client.ApiClient)3 WorkspaceApplicationApi (bio.terra.workspace.api.WorkspaceApplicationApi)2 CreatedControlledGcpGcsBucket (bio.terra.workspace.model.CreatedControlledGcpGcsBucket)2 GcpBigQueryDatasetResource (bio.terra.workspace.model.GcpBigQueryDatasetResource)2 GcpGcsBucketResource (bio.terra.workspace.model.GcpGcsBucketResource)2 WorkspaceApplicationDescription (bio.terra.workspace.model.WorkspaceApplicationDescription)2 GcsBucketAccessTester (scripts.utils.GcsBucketAccessTester)2 ClonedControlledGcpBigQueryDataset (bio.terra.workspace.model.ClonedControlledGcpBigQueryDataset)1 ControlledResourceMetadata (bio.terra.workspace.model.ControlledResourceMetadata)1 CreatedControlledGcpAiNotebookInstanceResult (bio.terra.workspace.model.CreatedControlledGcpAiNotebookInstanceResult)1 DataRepoSnapshotResource (bio.terra.workspace.model.DataRepoSnapshotResource)1