Search in sources :

Example 1 with ResourceType

use of org.bf2.srs.fleetmanager.spi.common.model.ResourceType in project kafka-admin-api by bf2fc6cc711aee1a0c2a.

the class AccessControlListIT method testGetAclsOrderByProperies.

@ParameterizedTest
@CsvSource({ Types.AclBinding.PROP_PERMISSION + "," + SORT_ASC, Types.AclBinding.PROP_PERMISSION + "," + SORT_DESC, Types.AclBinding.PROP_RESOURCE_TYPE + "," + SORT_ASC, Types.AclBinding.PROP_RESOURCE_TYPE + "," + SORT_DESC, Types.AclBinding.PROP_PATTERN_TYPE + "," + SORT_ASC, Types.AclBinding.PROP_PATTERN_TYPE + "," + SORT_DESC, Types.AclBinding.PROP_OPERATION + "," + SORT_ASC, Types.AclBinding.PROP_OPERATION + "," + SORT_DESC, Types.AclBinding.PROP_PRINCIPAL + "," + SORT_ASC, Types.AclBinding.PROP_PRINCIPAL + "," + SORT_DESC, Types.AclBinding.PROP_RESOURCE_NAME + "," + SORT_ASC, Types.AclBinding.PROP_RESOURCE_NAME + "," + SORT_DESC })
void testGetAclsOrderByProperies(String orderKey, String order) throws Exception {
    JsonObject allowedResourceOperations = Json.createReader(new StringReader(validResourceOperations)).readObject();
    List<JsonObject> newBindings = Stream.of(Json.createObjectBuilder().build()).flatMap(binding -> join(binding, Types.AclBinding.PROP_PERMISSION, AclPermissionType.ALLOW, AclPermissionType.DENY)).flatMap(binding -> join(binding, Types.AclBinding.PROP_RESOURCE_TYPE, ResourceType.TOPIC, ResourceType.GROUP, ResourceType.CLUSTER, ResourceType.TRANSACTIONAL_ID)).flatMap(binding -> join(binding, Types.AclBinding.PROP_PATTERN_TYPE, PatternType.LITERAL, PatternType.PREFIXED)).flatMap(binding -> join(binding, Types.AclBinding.PROP_OPERATION, AclOperation.READ, AclOperation.ALL, AclOperation.ALTER, AclOperation.DELETE, AclOperation.CREATE, AclOperation.ALTER_CONFIGS, AclOperation.DESCRIBE, AclOperation.DESCRIBE_CONFIGS, AclOperation.WRITE)).flatMap(binding -> join(binding, Types.AclBinding.PROP_PRINCIPAL, "User:{uuid}")).flatMap(binding -> join(binding, Types.AclBinding.PROP_RESOURCE_NAME, "resource-{uuid}")).filter(binding -> {
        String resourceType = binding.getString(Types.AclBinding.PROP_RESOURCE_TYPE).toLowerCase(Locale.US);
        String operation = binding.getString(Types.AclBinding.PROP_OPERATION).toLowerCase(Locale.US);
        return allowedResourceOperations.getJsonArray(resourceType).stream().filter(value -> value.getValueType() == ValueType.STRING).map(JsonString.class::cast).map(JsonString::getString).anyMatch(operation::equals);
    }).map(binding -> {
        if (ResourceType.CLUSTER.name().equals(binding.getString(Types.AclBinding.PROP_RESOURCE_TYPE))) {
            // Only value allowed is "kafka-cluster"
            binding = Json.createObjectBuilder(binding).add(Types.AclBinding.PROP_RESOURCE_NAME, "kafka-cluster").build();
        }
        return binding;
    }).distinct().collect(Collectors.toList());
    List<String> sortKeys = new LinkedList<>(AccessControlOperations.SORT_KEYS.keySet());
    // Remove the primary sort key, handled as a special case
    sortKeys.remove(orderKey);
    List<JsonObject> expectedValues = newBindings.stream().map(JsonObject.class::cast).sorted((j1, j2) -> {
        int result;
        if ((result = j1.getString(orderKey).compareTo(j2.getString(orderKey))) != 0) {
            return SORT_DESC.equals(order) ? (result * -1) : result;
        }
        for (String key : sortKeys) {
            if ((result = j1.getString(key).compareTo(j2.getString(key))) != 0) {
                return result;
            }
        }
        return 0;
    }).collect(Collectors.toList());
    final int expectedTotal = newBindings.size();
    final int pageSize = expectedTotal + 1;
    final var queryParams = Map.of("page", "1", "size", String.valueOf(pageSize), "orderKey", orderKey, "order", order);
    Properties adminConfig = ClientsConfig.getAdminConfigOauth(config, tokenUtils.getToken(UserType.OWNER.getUsername()));
    /*
         * Due to the number of ACLs created for this case (> 200), using the
         * bulk API directly is necessary.
         */
    try (Admin admin = Admin.create(adminConfig)) {
        admin.createAcls(newBindings.stream().map(Types.AclBinding::fromJsonObject).map(Types.AclBinding::toKafkaBinding).collect(Collectors.toList())).all().whenComplete((result, error) -> {
            if (error != null) {
                fail(error);
            } else {
                var response = getAcls(UserType.OWNER, queryParams).body("total", equalTo(expectedTotal)).body("size", equalTo(pageSize)).body("page", equalTo(1)).body("items", hasSize(expectedTotal));
                JsonObject responseBody = Json.createReader(response.extract().asInputStream()).readObject();
                List<JsonObject> responseValues = responseBody.getJsonArray("items").stream().map(JsonObject.class::cast).collect(Collectors.toList());
                assertEquals(expectedValues, responseValues, "Unexpected response order");
            }
        }).toCompletionStage().toCompletableFuture().get(30, TimeUnit.SECONDS);
    }
}
Also used : IntStream(java.util.stream.IntStream) Assertions.fail(org.junit.jupiter.api.Assertions.fail) BeforeEach(org.junit.jupiter.api.BeforeEach) CsvSource(org.junit.jupiter.params.provider.CsvSource) ValidatableResponse(io.restassured.response.ValidatableResponse) AclPermissionType(org.apache.kafka.common.acl.AclPermissionType) UserType(org.bf2.admin.kafka.systemtest.deployment.DeploymentManager.UserType) PatternType(org.apache.kafka.common.resource.PatternType) QuarkusTest(io.quarkus.test.junit.QuarkusTest) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) ClientsConfig(org.bf2.admin.kafka.systemtest.utils.ClientsConfig) Locale(java.util.Locale) Map(java.util.Map) Admin(org.apache.kafka.clients.admin.Admin) Json(javax.json.Json) Matchers.hasSize(org.hamcrest.Matchers.hasSize) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) LinkedList(java.util.LinkedList) TestOAuthProfile(org.bf2.admin.kafka.systemtest.TestOAuthProfile) Status(javax.ws.rs.core.Response.Status) JsonObject(javax.json.JsonObject) Properties(java.util.Properties) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) KafkaAdminConfigRetriever(org.bf2.admin.kafka.admin.KafkaAdminConfigRetriever) TestProfile(io.quarkus.test.junit.TestProfile) AclOperation(org.apache.kafka.common.acl.AclOperation) Config(org.eclipse.microprofile.config.Config) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) JsonString(javax.json.JsonString) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) ValueType(javax.json.JsonValue.ValueType) TokenUtils(org.bf2.admin.kafka.systemtest.utils.TokenUtils) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) List(java.util.List) Stream(java.util.stream.Stream) ResourceType(org.apache.kafka.common.resource.ResourceType) StringReader(java.io.StringReader) AccessControlOperations(org.bf2.admin.kafka.admin.AccessControlOperations) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Method(io.restassured.http.Method) RestAssured.given(io.restassured.RestAssured.given) Types(org.bf2.admin.kafka.admin.model.Types) JsonObjectBuilder(javax.json.JsonObjectBuilder) Types(org.bf2.admin.kafka.admin.model.Types) JsonObject(javax.json.JsonObject) JsonString(javax.json.JsonString) Properties(java.util.Properties) Admin(org.apache.kafka.clients.admin.Admin) LinkedList(java.util.LinkedList) StringReader(java.io.StringReader) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) JsonString(javax.json.JsonString) CsvSource(org.junit.jupiter.params.provider.CsvSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 2 with ResourceType

use of org.bf2.srs.fleetmanager.spi.common.model.ResourceType in project srs-fleet-manager by bf2fc6cc711aee1a0c2a.

the class AccountManagementServiceImpl method createResource.

@Timed(value = Constants.AMS_CREATE_TIMER, description = Constants.AMS_TIMER_DESCRIPTION)
@Audited(extractResult = KEY_AMS_SUBSCRIPTION_ID)
// but AMS still performs the reservation.
@Override
public String createResource(AccountInfo accountInfo, ResourceType resourceType) throws TermsRequiredException, ResourceLimitReachedException, AccountManagementServiceException {
    try {
        boolean termsAccepted = false;
        String siteCode = amsProperties.termsSiteCode;
        List<String> eventCodes = amsProperties.termsEventCode;
        for (String eventCode : eventCodes) {
            final TermsReview termsReview = new TermsReview();
            termsReview.setAccountUsername(accountInfo.getAccountUsername());
            termsReview.setSiteCode(siteCode);
            termsReview.setEventCode(eventCode);
            // Check if the user has accepted the Terms & Conditions
            final ResponseTermsReview responseTermsReview = restClient.termsReview(termsReview);
            boolean accepted = !responseTermsReview.getTermsRequired();
            // Terms are accepted if *any* of the T&C checks come back as "accepted"
            termsAccepted = termsAccepted || accepted;
        }
        if (!termsAccepted) {
            throw new TermsRequiredException(accountInfo.getAccountUsername());
        }
        // TODO Workaround: Remove this once we have RHOSRTrial working.
        if (resourceType == ResourceType.REGISTRY_INSTANCE_EVAL) {
            log.debug("Creating an eval instance for '{}' in org '{}' without calling AMS.", accountInfo.getAccountUsername(), accountInfo.getOrganizationId());
            return null;
        }
        // Set the productId and resourceName based on if it's an Eval or Standard instance
        String productId = amsProperties.standardProductId;
        String resourceName = amsProperties.standardResourceName;
        if (resourceType == ResourceType.REGISTRY_INSTANCE_EVAL) {
            productId = amsProperties.evalProductId;
            resourceName = amsProperties.evalResourceName;
        }
        // Build a quota resource ID to pass to AMS
        final var quotaResource = ReservedResource.builder().resourceType(amsProperties.resourceType).byoc(false).resourceName(resourceName).billingModel("marketplace").availabilityZone("single").count(1).build();
        // Create the cluster authorization REST operation input
        final ClusterAuthorization clusterAuthorization = ClusterAuthorization.builder().accountUsername(accountInfo.getAccountUsername()).productId(productId).managed(true).byoc(false).cloudProviderId("aws").reserve(true).availabilityZone("single").clusterId(UUID.randomUUID().toString()).resources(Collections.singletonList(quotaResource)).build();
        // Consume quota from AMS via the AMS REST API
        final ClusterAuthorizationResponse clusterAuthorizationResponse = restClient.clusterAuthorization(clusterAuthorization);
        if (clusterAuthorizationResponse.getAllowed()) {
            return clusterAuthorizationResponse.getSubscription().getId();
        } else {
            // User not allowed to create resource
            throw new ResourceLimitReachedException();
        }
    } catch (AccountManagementSystemClientException ex) {
        ExceptionConvert.convert(ex);
        // Never returns
        return null;
    }
}
Also used : ResponseTermsReview(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.ResponseTermsReview) TermsReview(org.bf2.srs.fleetmanager.spi.ams.impl.model.request.TermsReview) ClusterAuthorization(org.bf2.srs.fleetmanager.spi.ams.impl.model.request.ClusterAuthorization) ClusterAuthorizationResponse(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.ClusterAuthorizationResponse) TermsRequiredException(org.bf2.srs.fleetmanager.spi.ams.TermsRequiredException) AccountManagementSystemClientException(org.bf2.srs.fleetmanager.spi.ams.impl.exception.AccountManagementSystemClientException) ResourceLimitReachedException(org.bf2.srs.fleetmanager.spi.ams.ResourceLimitReachedException) ResponseTermsReview(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.ResponseTermsReview) Audited(org.bf2.srs.fleetmanager.common.operation.auditing.Audited) Timed(io.micrometer.core.annotation.Timed)

Example 3 with ResourceType

use of org.bf2.srs.fleetmanager.spi.common.model.ResourceType in project srs-fleet-manager by bf2fc6cc711aee1a0c2a.

the class AccountManagementServiceImpl method determineAllowedResourceType.

@Timed(value = Constants.AMS_DETERMINE_ALLOWED_INSTANCE_TIMER, description = Constants.AMS_TIMER_DESCRIPTION)
@Audited
@Timeout(FaultToleranceConstants.TIMEOUT_MS)
@RetryUnwrap
// 3 retries, 200ms jitter
@Retry(retryOn = { RetryWrapperException.class })
@RetryWrap
@Override
public ResourceType determineAllowedResourceType(AccountInfo accountInfo) throws AccountManagementServiceException {
    try {
        Organization organization = restClient.getOrganizationByExternalId(accountInfo.getOrganizationId());
        String orgId = organization.getId();
        // Check QuotaCostList for a RHOSR entry with "allowed" quota > 0.  If found, then
        // return "Standard" as the resource type to create.
        QuotaCostList quotaCostList = restClient.getQuotaCostList(orgId, true);
        if (quotaCostList.getSize() > 0) {
            for (QuotaCost quotaCost : quotaCostList.getItems()) {
                // We only care about QuotaCost with "allowed" > 0 and with at least one related resource.
                if (quotaCost.getAllowed() != null && quotaCost.getAllowed() > 0 && quotaCost.getRelated_resources() != null && !quotaCost.getRelated_resources().isEmpty() && isRhosrStandardQuota(quotaCost)) {
                    return ResourceType.REGISTRY_INSTANCE_STANDARD;
                }
            }
        }
        // Default to only allow eval.
        return ResourceType.REGISTRY_INSTANCE_EVAL;
    } catch (AccountManagementSystemClientException ex) {
        ExceptionConvert.convert(ex);
        // Never returns
        return null;
    }
}
Also used : Organization(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.Organization) QuotaCostList(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.QuotaCostList) QuotaCost(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.QuotaCost) AccountManagementSystemClientException(org.bf2.srs.fleetmanager.spi.ams.impl.exception.AccountManagementSystemClientException) Audited(org.bf2.srs.fleetmanager.common.operation.auditing.Audited) Timed(io.micrometer.core.annotation.Timed) Timeout(org.eclipse.microprofile.faulttolerance.Timeout) Retry(org.eclipse.microprofile.faulttolerance.Retry) RetryUnwrap(org.bf2.srs.fleetmanager.common.operation.faulttolerance.RetryUnwrap) RetryWrap(org.bf2.srs.fleetmanager.common.operation.faulttolerance.RetryWrap)

Example 4 with ResourceType

use of org.bf2.srs.fleetmanager.spi.common.model.ResourceType in project srs-fleet-manager by bf2fc6cc711aee1a0c2a.

the class AccountManagementSystemRestClientTest method clusterAuthorization.

@Test
public void clusterAuthorization() {
    final ClusterAuthorization clusterAuthorization = ClusterAuthorization.builder().accountUsername("testUser.openshift").productId("rhosr").managed(true).byoc(false).clusterId("foobar").cloudProviderId("aws").reserve(true).availabilityZone("single").resources(Collections.singletonList(ReservedResource.builder().resourceType("cluster.aws").resourceName("rhosr").count(1).build())).build();
    final ClusterAuthorizationResponse clusterAuthorizationResponse = accountManagementSystemRestClient.clusterAuthorization(clusterAuthorization);
    Assertions.assertNotNull(clusterAuthorizationResponse);
    Assertions.assertTrue(clusterAuthorizationResponse.getAllowed());
    Assertions.assertNotNull(clusterAuthorizationResponse.getSubscription().getId());
}
Also used : ClusterAuthorization(org.bf2.srs.fleetmanager.spi.ams.impl.model.request.ClusterAuthorization) ClusterAuthorizationResponse(org.bf2.srs.fleetmanager.spi.ams.impl.model.response.ClusterAuthorizationResponse) Test(org.junit.jupiter.api.Test)

Example 5 with ResourceType

use of org.bf2.srs.fleetmanager.spi.common.model.ResourceType in project srs-fleet-manager by bf2fc6cc711aee1a0c2a.

the class RegistryServiceImpl method createRegistry.

@Audited
@Override
public RegistryDto createRegistry(RegistryCreateDto registryCreate) throws RegistryStorageConflictException, TermsRequiredException, ResourceLimitReachedException, EvalInstancesNotAllowedException, TooManyEvalInstancesForUserException, TooManyInstancesException, AccountManagementServiceException {
    final AccountInfo accountInfo = authService.extractAccountInfo();
    // Make sure we have more instances available (max capacity not yet reached).
    long instanceCount = storage.getRegistryCountTotal();
    if (instanceCount >= maxInstances) {
        throw new TooManyInstancesException();
    }
    // Figure out if we are going to create a standard or eval instance.
    ResourceType resourceType = evalInstancesOnlyEnabled ? ResourceType.REGISTRY_INSTANCE_EVAL : accountManagementService.determineAllowedResourceType(accountInfo);
    if (resourceType == ResourceType.REGISTRY_INSTANCE_EVAL) {
        // Are eval instances allowed?
        if (!evalInstancesEnabled) {
            throw new EvalInstancesNotAllowedException();
        }
        // Limit the # of eval instances per user.  Need to check storage for list of eval registry instances.
        List<RegistryData> registriesByOwner = storage.getRegistriesByOwner(accountInfo.getAccountUsername());
        int evalInstanceCount = 0;
        for (RegistryData registryData : registriesByOwner) {
            // TODO Perform a dedicated query
            if (RegistryInstanceTypeValueDto.EVAL.value().equals(registryData.getInstanceType())) {
                evalInstanceCount++;
            }
        }
        if (evalInstanceCount >= maxEvalInstancesPerUser) {
            throw new TooManyEvalInstancesForUserException();
        }
    }
    // Try to consume some quota from AMS for the appropriate resource type (standard or eval).  If successful
    // we'll get back a subscriptionId - if not we'll throw an exception.
    String subscriptionId = accountManagementService.createResource(accountInfo, resourceType);
    // Convert to registry data and persist it in the DB.
    RegistryInstanceTypeValueDto instanceType = resourceTypeToInstanceType(resourceType);
    RegistryData registryData = convertRegistry.convert(registryCreate, subscriptionId, accountInfo.getAccountUsername(), accountInfo.getOrganizationId(), accountInfo.getAccountId(), instanceType);
    // Generate the ID
    registryData.setId(UUID.randomUUID().toString());
    storage.createOrUpdateRegistry(registryData);
    tasks.submit(ScheduleRegistryTask.builder().registryId(registryData.getId()).build());
    return convertRegistry.convert(registryData);
}
Also used : TooManyInstancesException(org.bf2.srs.fleetmanager.spi.common.TooManyInstancesException) EvalInstancesNotAllowedException(org.bf2.srs.fleetmanager.spi.common.EvalInstancesNotAllowedException) ResourceType(org.bf2.srs.fleetmanager.spi.common.model.ResourceType) TooManyEvalInstancesForUserException(org.bf2.srs.fleetmanager.spi.common.TooManyEvalInstancesForUserException) RegistryData(org.bf2.srs.fleetmanager.storage.sqlPanacheImpl.model.RegistryData) RegistryInstanceTypeValueDto(org.bf2.srs.fleetmanager.rest.service.model.RegistryInstanceTypeValueDto) AccountInfo(org.bf2.srs.fleetmanager.spi.common.model.AccountInfo) Audited(org.bf2.srs.fleetmanager.common.operation.auditing.Audited)

Aggregations

Audited (org.bf2.srs.fleetmanager.common.operation.auditing.Audited)3 Timed (io.micrometer.core.annotation.Timed)2 AccountManagementSystemClientException (org.bf2.srs.fleetmanager.spi.ams.impl.exception.AccountManagementSystemClientException)2 QuarkusTest (io.quarkus.test.junit.QuarkusTest)1 TestProfile (io.quarkus.test.junit.TestProfile)1 RestAssured.given (io.restassured.RestAssured.given)1 Method (io.restassured.http.Method)1 ValidatableResponse (io.restassured.response.ValidatableResponse)1 StringReader (java.io.StringReader)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Locale (java.util.Locale)1 Map (java.util.Map)1 Properties (java.util.Properties)1 UUID (java.util.UUID)1 TimeUnit (java.util.concurrent.TimeUnit)1 Collectors (java.util.stream.Collectors)1 IntStream (java.util.stream.IntStream)1 Stream (java.util.stream.Stream)1