Search in sources :

Example 1 with WorkbenchConfig

use of org.pmiops.workbench.config.WorkbenchConfig in project workbench by all-of-us.

the class ProfileController method createFirecloudUserAndBillingProject.

private String createFirecloudUserAndBillingProject(User user) {
    try {
        // If the user is already registered, their profile will get updated.
        fireCloudService.registerUser(user.getContactEmail(), user.getGivenName(), user.getFamilyName());
    } catch (ApiException e) {
        log.log(Level.SEVERE, String.format("Error registering user: %s", e.getResponseBody()), e);
        // We don't expect this to happen.
        throw new ServerErrorException("Error registering user", e);
    }
    WorkbenchConfig workbenchConfig = workbenchConfigProvider.get();
    long suffix;
    if (workbenchEnvironment.isDevelopment()) {
        // For local development, make one billing project per account based on a hash of the account
        // email, and reuse it across database resets. (Assume we won't have any collisions;
        // if we discover that somebody starts using our namespace, change it up.)
        suffix = user.getEmail().hashCode();
    } else {
        // In other environments, create a suffix based on the user ID from the database. We will
        // add a suffix if that billing project is already taken. (If the database is reset, we
        // should consider switching the prefix.)
        suffix = user.getUserId();
    }
    // GCP billing project names must be <= 30 characters. The per-user hash, an integer,
    // is <= 10 chars.
    String billingProjectNamePrefix = workbenchConfig.firecloud.billingProjectPrefix + suffix;
    String billingProjectName = billingProjectNamePrefix;
    int numAttempts = 0;
    while (numAttempts < MAX_BILLING_PROJECT_CREATION_ATTEMPTS) {
        try {
            fireCloudService.createAllOfUsBillingProject(billingProjectName);
            break;
        } catch (ApiException e) {
            if (e.getCode() == HttpStatus.CONFLICT.value()) {
                if (workbenchEnvironment.isDevelopment()) {
                    // In local development, just re-use existing projects for the account. (We don't
                    // want to create a new billing project every time the database is reset.)
                    log.log(Level.WARNING, String.format("Project with name '%s' already exists; using it.", billingProjectName));
                    break;
                } else {
                    numAttempts++;
                    // In cloud environments, keep trying billing project names until we find one
                    // that hasn't been used before, or we hit MAX_BILLING_PROJECT_CREATION_ATTEMPTS.
                    billingProjectName = billingProjectNamePrefix + "-" + numAttempts;
                }
            } else {
                log.log(Level.SEVERE, String.format("Error creating billing project: %s", e.getResponseBody()), e);
                throw new ServerErrorException("Error creating billing project", e);
            }
        }
    }
    if (numAttempts == MAX_BILLING_PROJECT_CREATION_ATTEMPTS) {
        throw new ServerErrorException(String.format("Encountered %d billing project name " + "collisions; giving up", MAX_BILLING_PROJECT_CREATION_ATTEMPTS));
    }
    try {
        // If the user is already a member of the billing project, this will have no effect.
        fireCloudService.addUserToBillingProject(user.getEmail(), billingProjectName);
    } catch (ApiException e) {
        if (e.getCode() == HttpStatus.FORBIDDEN.value()) {
            // AofU is not the owner of the billing project. This should only happen in local
            // environments (and hopefully never, given the prefix we're using.) If it happens,
            // we may need to pick a different prefix.
            log.log(Level.SEVERE, String.format("Unable to add user to billing project %s: %s; " + "consider changing billing project prefix", billingProjectName, e.getResponseBody()), e);
            throw new ServerErrorException("Unable to add user to billing project", e);
        } else {
            log.log(Level.SEVERE, String.format("Error adding user to billing project: %s", e.getResponseBody()), e);
            throw new ServerErrorException("Error adding user to billing project", e);
        }
    }
    return billingProjectName;
}
Also used : WorkbenchConfig(org.pmiops.workbench.config.WorkbenchConfig) ServerErrorException(org.pmiops.workbench.exceptions.ServerErrorException) ApiException(org.pmiops.workbench.firecloud.ApiException)

Example 2 with WorkbenchConfig

use of org.pmiops.workbench.config.WorkbenchConfig in project workbench by all-of-us.

the class BlockscoreServiceImplIntegrationTest method createConfig.

private static WorkbenchConfig createConfig() {
    WorkbenchConfig config = new WorkbenchConfig();
    config.googleCloudStorageService = new WorkbenchConfig.GoogleCloudStorageServiceConfig();
    config.googleCloudStorageService.credentialsBucketName = "all-of-us-workbench-test-credentials";
    return config;
}
Also used : WorkbenchConfig(org.pmiops.workbench.config.WorkbenchConfig)

Example 3 with WorkbenchConfig

use of org.pmiops.workbench.config.WorkbenchConfig in project workbench by all-of-us.

the class CloudStorageServiceImplIntegrationTest method createConfig.

private static WorkbenchConfig createConfig() {
    WorkbenchConfig config = new WorkbenchConfig();
    config.googleCloudStorageService = new WorkbenchConfig.GoogleCloudStorageServiceConfig();
    config.googleCloudStorageService.credentialsBucketName = "all-of-us-workbench-test-credentials";
    return config;
}
Also used : WorkbenchConfig(org.pmiops.workbench.config.WorkbenchConfig)

Example 4 with WorkbenchConfig

use of org.pmiops.workbench.config.WorkbenchConfig in project workbench by all-of-us.

the class ProfileControllerTest method setUp.

@Before
public void setUp() {
    WorkbenchConfig config = new WorkbenchConfig();
    config.firecloud = new FireCloudConfig();
    config.firecloud.billingProjectPrefix = BILLING_PROJECT_PREFIX;
    WorkbenchEnvironment environment = new WorkbenchEnvironment(true, "appId");
    WorkbenchEnvironment cloudEnvironment = new WorkbenchEnvironment(false, "appId");
    createAccountRequest = new CreateAccountRequest();
    invitationVerificationRequest = new InvitationVerificationRequest();
    Profile profile = new Profile();
    profile.setContactEmail(CONTACT_EMAIL);
    profile.setFamilyName(FAMILY_NAME);
    profile.setGivenName(GIVEN_NAME);
    profile.setUsername(USERNAME);
    createAccountRequest.setProfile(profile);
    createAccountRequest.setInvitationKey(INVITATION_KEY);
    createAccountRequest.setPassword(PASSWORD);
    invitationVerificationRequest.setInvitationKey(INVITATION_KEY);
    googleUser = new com.google.api.services.admin.directory.model.User();
    googleUser.setPrimaryEmail(PRIMARY_EMAIL);
    clock = new FakeClock(NOW);
    idVerificationRequest = new IdVerificationRequest();
    idVerificationRequest.setFirstName("Bob");
    UserService userService = new UserService(userProvider, userDao, adminActionHistoryDao, clock, fireCloudService, configProvider);
    ProfileService profileService = new ProfileService(fireCloudService, mailChimpService, userDao);
    this.profileController = new ProfileController(profileService, userProvider, userAuthenticationProvider, userDao, clock, userService, fireCloudService, directoryService, cloudStorageService, blockscoreService, mailChimpService, Providers.of(config), environment);
    this.cloudProfileController = new ProfileController(profileService, userProvider, userAuthenticationProvider, userDao, clock, userService, fireCloudService, directoryService, cloudStorageService, blockscoreService, mailChimpService, Providers.of(config), cloudEnvironment);
}
Also used : WorkbenchConfig(org.pmiops.workbench.config.WorkbenchConfig) FireCloudConfig(org.pmiops.workbench.config.WorkbenchConfig.FireCloudConfig) UserService(org.pmiops.workbench.db.dao.UserService) FakeClock(org.pmiops.workbench.test.FakeClock) InvitationVerificationRequest(org.pmiops.workbench.model.InvitationVerificationRequest) Profile(org.pmiops.workbench.model.Profile) CreateAccountRequest(org.pmiops.workbench.model.CreateAccountRequest) ProfileService(org.pmiops.workbench.auth.ProfileService) IdVerificationRequest(org.pmiops.workbench.model.IdVerificationRequest) WorkbenchEnvironment(org.pmiops.workbench.config.WorkbenchEnvironment) Before(org.junit.Before)

Example 5 with WorkbenchConfig

use of org.pmiops.workbench.config.WorkbenchConfig in project workbench by all-of-us.

the class AuthInterceptor method preHandle.

/**
 * Returns true iff the request is auth'd and should proceed. Publishes authenticated user info
 * using Spring's SecurityContext.
 * @param handler The Swagger-generated ApiController. It contains our handler as a private
 *     delegate.
 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // OPTIONS methods requests don't need authorization.
    if (request.getMethod().equals(HttpMethods.OPTIONS)) {
        return true;
    }
    HandlerMethod method = (HandlerMethod) handler;
    boolean isAuthRequired = false;
    ApiOperation apiOp = AnnotationUtils.findAnnotation(method.getMethod(), ApiOperation.class);
    if (apiOp != null) {
        for (Authorization auth : apiOp.authorizations()) {
            if (auth.value().equals(authName)) {
                isAuthRequired = true;
                break;
            }
        }
    }
    if (!isAuthRequired) {
        return true;
    }
    String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
    if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
        log.warning("No bearer token found in request");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }
    String token = authorizationHeader.substring("Bearer".length()).trim();
    Userinfoplus userInfo;
    try {
        userInfo = userInfoService.getUserInfo(token);
    } catch (HttpResponseException e) {
        log.log(Level.WARNING, "{0} response getting user info for bearer token {1}: {2}", new Object[] { e.getStatusCode(), token, e.getStatusMessage() });
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }
    // TODO: check Google group membership to ensure user is in registered user group
    String userEmail = userInfo.getEmail();
    WorkbenchConfig workbenchConfig = workbenchConfigProvider.get();
    if (workbenchConfig.auth.serviceAccountApiUsers.contains(userEmail)) {
        // Whitelisted service accounts are able to make API calls, too.
        // TODO: stop treating service accounts as normal users, have a separate table for them,
        // administrators.
        User user = userDao.findUserByEmail(userEmail);
        if (user == null) {
            user = userService.createServiceAccountUser(userEmail);
        }
        SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user, userInfo, token, UserType.SERVICE_ACCOUNT));
        log.log(Level.INFO, "{0} service account in use", userInfo.getEmail());
        return true;
    }
    String gsuiteDomainSuffix = "@" + workbenchConfig.googleDirectoryService.gSuiteDomain;
    if (!userEmail.endsWith(gsuiteDomainSuffix)) {
        try {
            // If the email isn't in our GSuite domain, try FireCloud; we could be dealing with a
            // pet service account. In both AofU and FireCloud, the pet SA is treated as if it were
            // the user it was created for.
            userEmail = fireCloudService.getMe().getUserInfo().getUserEmail();
        } catch (ApiException e) {
            log.log(Level.INFO, "FireCloud lookup for {0} failed, can't access the workbench: {1}", new Object[] { userInfo.getEmail(), e.getMessage() });
            response.sendError(e.getCode());
            return false;
        }
        if (!userEmail.endsWith(gsuiteDomainSuffix)) {
            log.log(Level.INFO, "User {0} isn't in domain {1}, can't access the workbench", new Object[] { userEmail, gsuiteDomainSuffix });
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return false;
        }
    }
    User user = userDao.findUserByEmail(userEmail);
    if (user == null) {
        // TODO(danrodney): start populating contact email in Google account, use it here.
        user = userService.createUser(userInfo.getGivenName(), userInfo.getFamilyName(), userInfo.getEmail(), null);
    } else {
        if (user.getDisabled()) {
            throw new ForbiddenException(ExceptionUtils.errorResponse(ErrorCode.USER_DISABLED, "This user account has been disabled."));
        }
    }
    SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user, userInfo, token, UserType.RESEARCHER));
    // TODO: setup this in the context, get rid of log statement
    log.log(Level.INFO, "{0} logged in", userInfo.getEmail());
    if (!hasRequiredAuthority(method, user)) {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
        return false;
    }
    return true;
}
Also used : Userinfoplus(com.google.api.services.oauth2.model.Userinfoplus) WorkbenchConfig(org.pmiops.workbench.config.WorkbenchConfig) ForbiddenException(org.pmiops.workbench.exceptions.ForbiddenException) User(org.pmiops.workbench.db.model.User) HttpResponseException(com.google.api.client.http.HttpResponseException) UserAuthentication(org.pmiops.workbench.auth.UserAuthentication) HandlerMethod(org.springframework.web.method.HandlerMethod) Authorization(io.swagger.annotations.Authorization) ApiOperation(io.swagger.annotations.ApiOperation) ApiException(org.pmiops.workbench.firecloud.ApiException)

Aggregations

WorkbenchConfig (org.pmiops.workbench.config.WorkbenchConfig)8 Before (org.junit.Before)2 FireCloudConfig (org.pmiops.workbench.config.WorkbenchConfig.FireCloudConfig)2 User (org.pmiops.workbench.db.model.User)2 ApiException (org.pmiops.workbench.firecloud.ApiException)2 Profile (org.pmiops.workbench.model.Profile)2 Address (com.blockscore.models.Address)1 HttpResponseException (com.google.api.client.http.HttpResponseException)1 Userinfoplus (com.google.api.services.oauth2.model.Userinfoplus)1 ApiOperation (io.swagger.annotations.ApiOperation)1 Authorization (io.swagger.annotations.Authorization)1 Test (org.junit.Test)1 ProfileService (org.pmiops.workbench.auth.ProfileService)1 UserAuthentication (org.pmiops.workbench.auth.UserAuthentication)1 AuthConfig (org.pmiops.workbench.config.WorkbenchConfig.AuthConfig)1 GoogleDirectoryServiceConfig (org.pmiops.workbench.config.WorkbenchConfig.GoogleDirectoryServiceConfig)1 WorkbenchEnvironment (org.pmiops.workbench.config.WorkbenchEnvironment)1 UserService (org.pmiops.workbench.db.dao.UserService)1 ForbiddenException (org.pmiops.workbench.exceptions.ForbiddenException)1 ServerErrorException (org.pmiops.workbench.exceptions.ServerErrorException)1