Search in sources :

Example 21 with ControlledResource

use of bio.terra.workspace.service.resource.controlled.model.ControlledResource in project terra-workspace-manager by DataBiosphere.

the class ResourceDao method storeResource.

private void storeResource(WsmResource resource) {
    // TODO: add resource locking to fix this
    // We create resources in flights, so we have steps that call resource creation that may
    // get run more than once. The safe solution is to "lock" the resource by writing the flight id
    // into the row at creation. Then it is possible on a re-insert to know whether the error is
    // because this flight step is re-running or because some other flight used the same resource
    // id. The small risk we have here is that a duplicate resource id of will appear to be
    // successfully created, but in fact will be silently rejected.
    final String countSql = "SELECT COUNT(*) FROM resource WHERE resource_id = :resource_id";
    MapSqlParameterSource countParams = new MapSqlParameterSource().addValue("resource_id", resource.getResourceId().toString());
    Integer count = jdbcTemplate.queryForObject(countSql, countParams, Integer.class);
    if (count != null && count == 1) {
        return;
    }
    final String sql = "INSERT INTO resource (workspace_id, cloud_platform, resource_id, name, description, stewardship_type," + " exact_resource_type, resource_type, cloning_instructions, attributes," + " access_scope, managed_by, associated_app, assigned_user, private_resource_state)" + " VALUES (:workspace_id, :cloud_platform, :resource_id, :name, :description, :stewardship_type," + " :exact_resource_type, :resource_type, :cloning_instructions, cast(:attributes AS jsonb)," + " :access_scope, :managed_by, :associated_app, :assigned_user, :private_resource_state)";
    final var params = new MapSqlParameterSource().addValue("workspace_id", resource.getWorkspaceId().toString()).addValue("cloud_platform", resource.getResourceType().getCloudPlatform().toString()).addValue("resource_id", resource.getResourceId().toString()).addValue("name", resource.getName()).addValue("description", resource.getDescription()).addValue("stewardship_type", resource.getStewardshipType().toSql()).addValue("exact_resource_type", resource.getResourceType().toSql()).addValue("resource_type", resource.getResourceFamily().toSql()).addValue("cloning_instructions", resource.getCloningInstructions().toSql()).addValue("attributes", resource.attributesToJson());
    if (resource.getStewardshipType().equals(CONTROLLED)) {
        ControlledResource controlledResource = resource.castToControlledResource();
        // noinspection deprecation
        params.addValue("access_scope", controlledResource.getAccessScope().toSql()).addValue("managed_by", controlledResource.getManagedBy().toSql()).addValue("associated_app", controlledResource.getApplicationId()).addValue("assigned_user", controlledResource.getAssignedUser().orElse(null)).addValue("private_resource_state", controlledResource.getPrivateResourceState().map(PrivateResourceState::toSql).orElse(null));
    } else {
        params.addValue("access_scope", null).addValue("managed_by", null).addValue("associated_app", null).addValue("assigned_user", null).addValue("private_resource_state", null);
    }
    try {
        jdbcTemplate.update(sql, params);
        logger.info("Inserted record for resource {} for workspace {}", resource.getResourceId(), resource.getWorkspaceId());
    } catch (DuplicateKeyException e) {
        throw new DuplicateResourceException(String.format("A resource already exists in the workspace that has the same name (%s) or the same id (%s)", resource.getName(), resource.getResourceId().toString()));
    }
}
Also used : MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) ControlledResource(bio.terra.workspace.service.resource.controlled.model.ControlledResource) DuplicateKeyException(org.springframework.dao.DuplicateKeyException) DuplicateResourceException(bio.terra.workspace.service.resource.exception.DuplicateResourceException) PrivateResourceState(bio.terra.workspace.service.resource.controlled.model.PrivateResourceState)

Example 22 with ControlledResource

use of bio.terra.workspace.service.resource.controlled.model.ControlledResource in project terra-workspace-manager by DataBiosphere.

the class SamServiceTest method duplicateResourceDeleteIgnored.

@Test
void duplicateResourceDeleteIgnored() throws Exception {
    ControlledResource bucketResource = ControlledResourceFixtures.makeDefaultControlledGcsBucketBuilder(workspaceId).build();
    samService.createControlledResource(bucketResource, null, null, defaultUserRequest());
    samService.deleteControlledResource(bucketResource, defaultUserRequest());
    samService.deleteControlledResource(bucketResource, defaultUserRequest());
}
Also used : ControlledResource(bio.terra.workspace.service.resource.controlled.model.ControlledResource) BaseConnectedTest(bio.terra.workspace.common.BaseConnectedTest) Test(org.junit.jupiter.api.Test)

Example 23 with ControlledResource

use of bio.terra.workspace.service.resource.controlled.model.ControlledResource in project terra-workspace-manager by DataBiosphere.

the class SamServiceTest method duplicateResourceCreateIgnored.

@Test
void duplicateResourceCreateIgnored() throws Exception {
    ControlledResource bucketResource = ControlledResourceFixtures.makeDefaultControlledGcsBucketBuilder(workspaceId).build();
    samService.createControlledResource(bucketResource, null, null, defaultUserRequest());
    // This duplicate call should complete without throwing.
    samService.createControlledResource(bucketResource, null, null, defaultUserRequest());
    // Delete the bucket so we can clean up the workspace.
    samService.deleteControlledResource(bucketResource, defaultUserRequest());
}
Also used : ControlledResource(bio.terra.workspace.service.resource.controlled.model.ControlledResource) BaseConnectedTest(bio.terra.workspace.common.BaseConnectedTest) Test(org.junit.jupiter.api.Test)

Example 24 with ControlledResource

use of bio.terra.workspace.service.resource.controlled.model.ControlledResource in project terra-workspace-manager by DataBiosphere.

the class PrivateResourceCleanupServiceTest method cleanupResourcesSuppressExceptions_cleansApplicationPrivateResource_succeeds.

@Test
@DisabledIfEnvironmentVariable(named = "TEST_ENV", matches = BUFFER_SERVICE_DISABLED_ENVS_REG_EX)
void cleanupResourcesSuppressExceptions_cleansApplicationPrivateResource_succeeds() {
    // Default user owns the workspace and group. Secondary user has workspace membership via group.
    // Add second user to group
    addUserToGroup(groupName, userAccessUtils.getSecondUserEmail(), ownerGroupApi);
    // Add group to workspace as writer
    SamRethrow.onInterrupted(() -> samService.grantWorkspaceRole(workspace.getWorkspaceId(), userAccessUtils.defaultUserAuthRequest(), WsmIamRole.WRITER, groupEmail), "grantWorkspaceRole");
    // Enable the WSM test app in this workspace. This has a test user as the "service account" so
    // we can delegate credentials normally.
    App appConfig = getAppBySa(applicationAccessUtils.getApplicationSaEmail());
    UUID appId = UUID.fromString(appConfig.getIdentifier());
    AuthenticatedUserRequest appRequest = applicationAccessUtils.applicationSaAuthenticatedUserRequest();
    wsmApplicationService.enableWorkspaceApplication(userAccessUtils.defaultUserAuthRequest(), workspace.getWorkspaceId(), appId);
    // Create application private bucket assigned to second user.
    ControlledResourceFields commonFields = ControlledResourceFixtures.makeDefaultControlledResourceFieldsBuilder().workspaceId(workspace.getWorkspaceId()).accessScope(AccessScopeType.ACCESS_SCOPE_PRIVATE).managedBy(ManagedByType.MANAGED_BY_APPLICATION).applicationId(appId).assignedUser(userAccessUtils.getSecondUserEmail()).build();
    ControlledGcsBucketResource resource = ControlledGcsBucketResource.builder().common(commonFields).bucketName(ControlledResourceFixtures.uniqueBucketName()).build();
    ApiGcpGcsBucketCreationParameters creationParameters = new ApiGcpGcsBucketCreationParameters().location("us-central1");
    // Create resource as application.
    controlledResourceService.createControlledResourceSync(resource, ControlledResourceIamRole.WRITER, appRequest, creationParameters);
    // Verify second user can read the private resource in Sam.
    SamRethrow.onInterrupted(() -> samService.checkAuthz(userAccessUtils.secondUserAuthRequest(), resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth");
    // Remove second user from workspace via group.
    removeUserFromGroup(groupName, userAccessUtils.getSecondUserEmail(), ownerGroupApi);
    // Verify second user is no longer in workspace, but still has resource access because cleanup
    // hasn't run yet.
    assertFalse(SamRethrow.onInterrupted(() -> samService.isAuthorized(userAccessUtils.secondUserAuthRequest(), SamResource.WORKSPACE, resource.getWorkspaceId().toString(), SamWorkspaceAction.READ), "checkResourceAuth"));
    assertTrue(SamRethrow.onInterrupted(() -> samService.isAuthorized(userAccessUtils.secondUserAuthRequest(), resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth"));
    // Manually enable and run cleanup.
    privateResourceCleanupConfiguration.setEnabled(true);
    // Calling "cleanupResources" manually lets us skip waiting for the cronjob to trigger.
    privateResourceCleanupService.cleanupResourcesSuppressExceptions();
    // Verify second user can no longer read the resource.
    assertFalse(SamRethrow.onInterrupted(() -> samService.isAuthorized(userAccessUtils.secondUserAuthRequest(), resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth"));
    // Verify resource is marked "abandoned"
    ControlledResource dbResource = resourceDao.getResource(resource.getWorkspaceId(), resource.getResourceId()).castToControlledResource();
    assertEquals(PrivateResourceState.ABANDONED, dbResource.getPrivateResourceState().get());
    // Application can still read the resource, because applications have EDITOR role on their
    // application-private resources.
    assertTrue(SamRethrow.onInterrupted(() -> samService.isAuthorized(appRequest, resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth"));
}
Also used : App(bio.terra.workspace.app.configuration.external.WsmApplicationConfiguration.App) ControlledResource(bio.terra.workspace.service.resource.controlled.model.ControlledResource) AuthenticatedUserRequest(bio.terra.workspace.service.iam.AuthenticatedUserRequest) UUID(java.util.UUID) ControlledResourceFields(bio.terra.workspace.service.resource.controlled.model.ControlledResourceFields) ApiGcpGcsBucketCreationParameters(bio.terra.workspace.generated.model.ApiGcpGcsBucketCreationParameters) ControlledGcsBucketResource(bio.terra.workspace.service.resource.controlled.cloud.gcp.gcsbucket.ControlledGcsBucketResource) BaseConnectedTest(bio.terra.workspace.common.BaseConnectedTest) Test(org.junit.jupiter.api.Test) DisabledIfEnvironmentVariable(org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable)

Example 25 with ControlledResource

use of bio.terra.workspace.service.resource.controlled.model.ControlledResource in project terra-workspace-manager by DataBiosphere.

the class PrivateResourceCleanupServiceTest method cleanupResourcesSuppressExceptions_cleansUserPrivateResource_succeeds.

@Test
@DisabledIfEnvironmentVariable(named = "TEST_ENV", matches = BUFFER_SERVICE_DISABLED_ENVS_REG_EX)
void cleanupResourcesSuppressExceptions_cleansUserPrivateResource_succeeds() {
    // Default user owns the workspace and group. Secondary user has workspace membership via group.
    // Add second user to group
    addUserToGroup(groupName, userAccessUtils.getSecondUserEmail(), ownerGroupApi);
    // Add group to workspace as writer
    SamRethrow.onInterrupted(() -> samService.grantWorkspaceRole(workspace.getWorkspaceId(), userAccessUtils.defaultUserAuthRequest(), WsmIamRole.WRITER, groupEmail), "grantWorkspaceRole");
    // Create private bucket as second user.
    ControlledResourceFields commonFields = ControlledResourceFixtures.makeDefaultControlledResourceFieldsBuilder().workspaceId(workspace.getWorkspaceId()).accessScope(AccessScopeType.ACCESS_SCOPE_PRIVATE).managedBy(ManagedByType.MANAGED_BY_USER).assignedUser(userAccessUtils.getSecondUserEmail()).build();
    ControlledGcsBucketResource resource = ControlledGcsBucketResource.builder().common(commonFields).bucketName(ControlledResourceFixtures.uniqueBucketName()).build();
    ApiGcpGcsBucketCreationParameters creationParameters = new ApiGcpGcsBucketCreationParameters().location("us-central1");
    controlledResourceService.createControlledResourceSync(resource, ControlledResourceIamRole.EDITOR, userAccessUtils.defaultUserAuthRequest(), creationParameters);
    // Verify second user can read the private resource in Sam.
    SamRethrow.onInterrupted(() -> samService.checkAuthz(userAccessUtils.secondUserAuthRequest(), resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth");
    // Remove second user from workspace via group
    removeUserFromGroup(groupName, userAccessUtils.getSecondUserEmail(), ownerGroupApi);
    // Verify second user is no longer in workspace, but still has resource access because cleanup
    // hasn't run yet.
    assertFalse(SamRethrow.onInterrupted(() -> samService.isAuthorized(userAccessUtils.secondUserAuthRequest(), SamResource.WORKSPACE, resource.getWorkspaceId().toString(), SamWorkspaceAction.READ), "checkResourceAuth"));
    assertTrue(SamRethrow.onInterrupted(() -> samService.isAuthorized(userAccessUtils.secondUserAuthRequest(), resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth"));
    // Manually enable and run cleanup.
    privateResourceCleanupConfiguration.setEnabled(true);
    // Calling "cleanupResources" manually lets us skip waiting for the cronjob to trigger.
    privateResourceCleanupService.cleanupResourcesSuppressExceptions();
    // Verify second user can no longer read the resource.
    assertFalse(SamRethrow.onInterrupted(() -> samService.isAuthorized(userAccessUtils.secondUserAuthRequest(), resource.getCategory().getSamResourceName(), resource.getResourceId().toString(), SamControlledResourceActions.READ_ACTION), "checkResourceAuth"));
    // Verify resource is marked "abandoned"
    ControlledResource dbResource = resourceDao.getResource(resource.getWorkspaceId(), resource.getResourceId()).castToControlledResource();
    assertEquals(PrivateResourceState.ABANDONED, dbResource.getPrivateResourceState().get());
}
Also used : ControlledResource(bio.terra.workspace.service.resource.controlled.model.ControlledResource) ControlledResourceFields(bio.terra.workspace.service.resource.controlled.model.ControlledResourceFields) ApiGcpGcsBucketCreationParameters(bio.terra.workspace.generated.model.ApiGcpGcsBucketCreationParameters) ControlledGcsBucketResource(bio.terra.workspace.service.resource.controlled.cloud.gcp.gcsbucket.ControlledGcsBucketResource) BaseConnectedTest(bio.terra.workspace.common.BaseConnectedTest) Test(org.junit.jupiter.api.Test) DisabledIfEnvironmentVariable(org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable)

Aggregations

ControlledResource (bio.terra.workspace.service.resource.controlled.model.ControlledResource)27 Test (org.junit.jupiter.api.Test)13 UUID (java.util.UUID)9 AuthenticatedUserRequest (bio.terra.workspace.service.iam.AuthenticatedUserRequest)8 BaseConnectedTest (bio.terra.workspace.common.BaseConnectedTest)6 FlightMap (bio.terra.stairway.FlightMap)5 FlightState (bio.terra.stairway.FlightState)5 BaseAzureTest (bio.terra.workspace.common.BaseAzureTest)5 ManagementException (com.azure.core.management.exception.ManagementException)5 ControlledGcsBucketResource (bio.terra.workspace.service.resource.controlled.cloud.gcp.gcsbucket.ControlledGcsBucketResource)4 ControlledResourceFields (bio.terra.workspace.service.resource.controlled.model.ControlledResourceFields)4 WsmResource (bio.terra.workspace.service.resource.model.WsmResource)3 BaseUnitTest (bio.terra.workspace.common.BaseUnitTest)2 ApiGcpGcsBucketCreationParameters (bio.terra.workspace.generated.model.ApiGcpGcsBucketCreationParameters)2 ControlledResourceIamRole (bio.terra.workspace.service.iam.model.ControlledResourceIamRole)2 JobBuilder (bio.terra.workspace.service.job.JobBuilder)2 ControlledAzureDiskResource (bio.terra.workspace.service.resource.controlled.cloud.azure.disk.ControlledAzureDiskResource)2 ControlledAzureIpResource (bio.terra.workspace.service.resource.controlled.cloud.azure.ip.ControlledAzureIpResource)2 ControlledAzureNetworkResource (bio.terra.workspace.service.resource.controlled.cloud.azure.network.ControlledAzureNetworkResource)2 ControlledBigQueryDatasetResource (bio.terra.workspace.service.resource.controlled.cloud.gcp.bqdataset.ControlledBigQueryDatasetResource)2