Search in sources :

Example 36 with Account

use of com.github.ambry.account.Account in project ambry by linkedin.

the class FrontendTestUrlSigningServiceFactory method validateSecurePathTest.

/**
 * Test that the secure path is validated if required by {@link Container}.
 * @throws Exception
 */
@Test
public void validateSecurePathTest() throws Exception {
    short refAccountId = Utils.getRandomShort(TestUtils.RANDOM);
    String refAccountName = TestUtils.getRandomString(10);
    short[] refContainerIds = new short[] { 2, 3 };
    String[] refContainerNames = new String[] { "SecurePathValidation", "NoValidation" };
    Container signedPathRequiredContainer = new ContainerBuilder(refContainerIds[0], refContainerNames[0], Container.ContainerStatus.ACTIVE, "validate secure path", refAccountId).setSecurePathRequired(true).build();
    Container noValidationContainer = new ContainerBuilder(refContainerIds[1], refContainerNames[1], Container.ContainerStatus.ACTIVE, "no validation on secure path", refAccountId).setSecurePathRequired(false).build();
    Account account = new AccountBuilder(refAccountId, refAccountName, Account.AccountStatus.ACTIVE).addOrUpdateContainer(signedPathRequiredContainer).addOrUpdateContainer(noValidationContainer).build();
    accountService.updateAccounts(Collections.singletonList(account));
    ByteBuffer content = ByteBuffer.wrap(TestUtils.getRandomBytes(CONTENT_LENGTH));
    String contentType = "application/octet-stream";
    String ownerId = "SecurePathValidationTest";
    JSONObject headers = new JSONObject();
    setAmbryHeadersForPut(headers, TTL_SECS, false, refAccountName, contentType, ownerId, refAccountName, refContainerNames[0], null);
    Map<String, String> userMetadata = new HashMap<>();
    userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key1", "value1");
    RestUtilsTest.setUserMetadataHeaders(headers, userMetadata);
    String blobId = postBlobAndVerify(headers, content, account, signedPathRequiredContainer);
    headers.put(RestUtils.Headers.BLOB_SIZE, (long) CONTENT_LENGTH);
    // test that secure path validation succeeded
    String testUri = "/" + frontendConfig.securePathPrefix + blobId;
    getBlobAndVerify(testUri, null, null, headers, content, account, signedPathRequiredContainer);
    // test that no secure path should fail (return AccessDenied)
    try {
        getBlobAndVerify(blobId, null, null, headers, content, account, signedPathRequiredContainer);
        fail("get blob should fail because secure path is missing");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.AccessDenied, e.getErrorCode());
    }
    // test that secure path equals other prefix should fail (return AccessDenied)
    try {
        getBlobAndVerify("/media" + blobId, null, null, headers, content, account, signedPathRequiredContainer);
        fail("get blob should fail because secure path equals other prefix and doesn't match expected one");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.AccessDenied, e.getErrorCode());
    }
    // test that incorrect path should fail (return BadRequest)
    try {
        getBlobAndVerify("/incorrect-path" + blobId, null, null, headers, content, account, signedPathRequiredContainer);
        fail("get blob should fail because secure path is incorrect");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.BadRequest, e.getErrorCode());
    }
    // test container with no validation
    setAmbryHeadersForPut(headers, TTL_SECS, false, refAccountName, contentType, ownerId, refAccountName, refContainerNames[1], null);
    content = ByteBuffer.wrap(TestUtils.getRandomBytes(CONTENT_LENGTH));
    blobId = postBlobAndVerify(headers, content, account, noValidationContainer);
    // test container with no validation should fail if there is invalid path in URI
    try {
        getBlobAndVerify("/incorrect-path" + blobId, null, null, headers, content, account, noValidationContainer);
        fail("get blob should fail because there is invalid path in uri");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.BadRequest, e.getErrorCode());
    }
    // test container with no validation should succeed if URI is correct
    getBlobAndVerify(blobId, null, null, headers, content, account, noValidationContainer);
}
Also used : Account(com.github.ambry.account.Account) HashMap(java.util.HashMap) ByteBuffer(java.nio.ByteBuffer) RestServiceException(com.github.ambry.rest.RestServiceException) Container(com.github.ambry.account.Container) ContainerBuilder(com.github.ambry.account.ContainerBuilder) JSONObject(org.json.JSONObject) AccountBuilder(com.github.ambry.account.AccountBuilder) Test(org.junit.Test) RestUtilsTest(com.github.ambry.rest.RestUtilsTest) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Example 37 with Account

use of com.github.ambry.account.Account in project ambry by linkedin.

the class FrontendTestUrlSigningServiceFactory method getAccountsTest.

/**
 * Tests the handling of {@link Operations#ACCOUNTS} get requests.
 * @throws Exception
 */
@Test
public void getAccountsTest() throws Exception {
    RestRequest restRequest = createRestRequest(RestMethod.GET, Operations.ACCOUNTS, null, null);
    MockRestResponseChannel restResponseChannel = new MockRestResponseChannel();
    doOperation(restRequest, restResponseChannel);
    Set<Account> expected = new HashSet<>(accountService.getAllAccounts());
    Set<Account> actual = new HashSet<>(AccountCollectionSerde.accountsFromInputStreamInJson(new ByteArrayInputStream(restResponseChannel.getResponseBody())));
    assertEquals("Unexpected GET /accounts response", expected, actual);
    // test an account not found case to ensure that it goes through the exception path
    restRequest = createRestRequest(RestMethod.GET, Operations.ACCOUNTS, new JSONObject().put(RestUtils.Headers.TARGET_ACCOUNT_ID, accountService.generateRandomAccount().getId()), null);
    try {
        doOperation(restRequest, new MockRestResponseChannel());
        fail("Operation should have failed");
    } catch (RestServiceException e) {
        assertEquals("Error code not as expected", RestServiceErrorCode.NotFound, e.getErrorCode());
    }
}
Also used : RestServiceException(com.github.ambry.rest.RestServiceException) Account(com.github.ambry.account.Account) MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) JSONObject(org.json.JSONObject) ByteArrayInputStream(java.io.ByteArrayInputStream) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) HashSet(java.util.HashSet) Test(org.junit.Test) RestUtilsTest(com.github.ambry.rest.RestUtilsTest) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Example 38 with Account

use of com.github.ambry.account.Account in project ambry by linkedin.

the class GetAccountsHandlerTest method getSingleContainerSuccessTest.

/**
 * Test success case of getting single container.
 * @throws Exception
 */
@Test
public void getSingleContainerSuccessTest() throws Exception {
    Account existingAccount = accountService.createAndAddRandomAccount();
    Container existingContainer = existingAccount.getAllContainers().iterator().next();
    ThrowingBiConsumer<RestRequest, Container> testAction = (request, expectedContainer) -> {
        RestResponseChannel restResponseChannel = new MockRestResponseChannel();
        ReadableStreamChannel channel = sendRequestGetResponse(request, restResponseChannel);
        assertNotNull("There should be a response", channel);
        Assert.assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
        assertEquals("Content-type is not as expected", RestUtils.JSON_CONTENT_TYPE, restResponseChannel.getHeader(RestUtils.Headers.CONTENT_TYPE));
        assertEquals("Content-length is not as expected", channel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
        RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) channel.getSize());
        channel.readInto(asyncWritableChannel, null).get();
        assertEquals("Container does not match", Collections.singletonList(expectedContainer), AccountCollectionSerde.containersFromInputStreamInJson(asyncWritableChannel.consumeContentAsInputStream(), existingAccount.getId()));
    };
    testAction.accept(createRestRequest(existingAccount.getName(), null, existingContainer.getName(), Operations.ACCOUNTS_CONTAINERS), existingContainer);
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) FutureResult(com.github.ambry.router.FutureResult) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) AccountCollectionSerde(com.github.ambry.account.AccountCollectionSerde) RequestPath(com.github.ambry.rest.RequestPath) HashSet(java.util.HashSet) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) Container(com.github.ambry.account.Container) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) MetricRegistry(com.codahale.metrics.MetricRegistry) RestMethod(com.github.ambry.rest.RestMethod) Collection(java.util.Collection) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Test(org.junit.Test) ThrowingBiConsumer(com.github.ambry.utils.ThrowingBiConsumer) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) RestServiceException(com.github.ambry.rest.RestServiceException) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) InMemAccountService(com.github.ambry.account.InMemAccountService) Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Test(org.junit.Test)

Example 39 with Account

use of com.github.ambry.account.Account in project ambry by linkedin.

the class MySqlNamedBlobDbIntegrationTest method testPutGetListDeleteSequence.

/**
 * Tests sequences of puts, gets, lists, and deletes across multiple containers.
 * @throws Exception
 */
@Test
public void testPutGetListDeleteSequence() throws Exception {
    int blobsPerContainer = 5;
    List<NamedBlobRecord> records = new ArrayList<>();
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            for (int i = 0; i < blobsPerContainer; i++) {
                String blobId = getBlobId(account, container);
                String blobName = "name/" + i + "/more path segments--";
                long expirationTime = i % 2 == 0 ? Utils.Infinite_Time : System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1);
                NamedBlobRecord record = new NamedBlobRecord(account.getName(), container.getName(), blobName, blobId, expirationTime);
                namedBlobDb.put(record).get();
                records.add(record);
            }
        }
    }
    // get records just inserted
    for (NamedBlobRecord record : records) {
        NamedBlobRecord recordFromStore = namedBlobDb.get(record.getAccountName(), record.getContainerName(), record.getBlobName()).get();
        assertEquals("Record does not match expectations.", record, recordFromStore);
    }
    // list records in each container
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            Page<NamedBlobRecord> page = namedBlobDb.list(account.getName(), container.getName(), "name", null).get();
            assertNull("No continuation token expected", page.getNextPageToken());
            assertEquals("Unexpected number of blobs in container", blobsPerContainer, page.getEntries().size());
        }
    }
    // check that puts to the same keys fail.
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            for (int i = 0; i < blobsPerContainer; i++) {
                String blobId = getBlobId(account, container);
                String blobName = "name/" + i + "/more path segments--";
                NamedBlobRecord record = new NamedBlobRecord(account.getName(), container.getName(), blobName, blobId, Utils.Infinite_Time);
                checkErrorCode(() -> namedBlobDb.put(record), RestServiceErrorCode.Conflict);
            }
        }
    }
    // delete the records and check that they cannot be fetched with a get call.
    for (NamedBlobRecord record : records) {
        DeleteResult deleteResult = namedBlobDb.delete(record.getAccountName(), record.getContainerName(), record.getBlobName()).get();
        assertEquals("Unexpected deleted ID", record.getBlobId(), deleteResult.getBlobId());
        assertFalse("Unexpected alreadyDeleted value", deleteResult.isAlreadyDeleted());
        checkErrorCode(() -> namedBlobDb.get(record.getAccountName(), record.getContainerName(), record.getBlobName()), RestServiceErrorCode.Deleted);
    }
    // deletes should be idempotent and additional delete calls should succeed
    for (NamedBlobRecord record : records) {
        DeleteResult deleteResult = namedBlobDb.delete(record.getAccountName(), record.getContainerName(), record.getBlobName()).get();
        assertEquals("Unexpected deleted ID", record.getBlobId(), deleteResult.getBlobId());
        assertTrue("Unexpected alreadyDeleted value", deleteResult.isAlreadyDeleted());
    }
    // delete and get for non existent blobs should return not found.
    for (NamedBlobRecord record : records) {
        String nonExistentName = record.getBlobName() + "-other";
        checkErrorCode(() -> namedBlobDb.get(record.getAccountName(), record.getContainerName(), nonExistentName), RestServiceErrorCode.NotFound);
        checkErrorCode(() -> namedBlobDb.delete(record.getAccountName(), record.getContainerName(), nonExistentName), RestServiceErrorCode.NotFound);
    }
    records.clear();
    // should be able to put new records again after deletion
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            for (int i = 0; i < blobsPerContainer; i++) {
                String blobId = getBlobId(account, container);
                String blobName = "name/" + i + "/more path segments--";
                long expirationTime = i % 2 == 1 ? Utils.Infinite_Time : System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1);
                NamedBlobRecord record = new NamedBlobRecord(account.getName(), container.getName(), blobName, blobId, expirationTime);
                namedBlobDb.put(record).get();
                records.add(record);
            }
        }
    }
}
Also used : Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 40 with Account

use of com.github.ambry.account.Account in project ambry by linkedin.

the class AmbryCUQuotaSourceTest method testChargeForValidResource.

@Test
public void testChargeForValidResource() throws Exception {
    Account account = inMemAccountService.getAccountById((short) 102);
    Container container = new ArrayList<>(account.getAllContainers()).get(0);
    ambryCUQuotaSource.chargeUsage(QuotaResource.fromContainer(container), QuotaName.READ_CAPACITY_UNIT, 102400000);
    Assert.assertEquals(10.0, ambryCUQuotaSource.getUsage(QuotaResource.fromContainer(container), QuotaName.READ_CAPACITY_UNIT), 0.01);
    Assert.assertEquals(0, ambryCUQuotaSource.getUsage(QuotaResource.fromContainer(container), QuotaName.WRITE_CAPACITY_UNIT), 0.01);
    ambryCUQuotaSource.chargeUsage(QuotaResource.fromContainer(container), QuotaName.WRITE_CAPACITY_UNIT, 102400000);
    Assert.assertEquals(10.0, ambryCUQuotaSource.getUsage(QuotaResource.fromContainer(container), QuotaName.READ_CAPACITY_UNIT), 0.01);
    Assert.assertEquals(10.0, ambryCUQuotaSource.getUsage(QuotaResource.fromContainer(container), QuotaName.WRITE_CAPACITY_UNIT), 0.01);
}
Also used : Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) Test(org.junit.Test)

Aggregations

Account (com.github.ambry.account.Account)114 Container (com.github.ambry.account.Container)87 Test (org.junit.Test)67 RestServiceException (com.github.ambry.rest.RestServiceException)24 ArrayList (java.util.ArrayList)22 RestRequest (com.github.ambry.rest.RestRequest)18 JSONObject (org.json.JSONObject)18 MockRestRequest (com.github.ambry.rest.MockRestRequest)17 VerifiableProperties (com.github.ambry.config.VerifiableProperties)16 HashMap (java.util.HashMap)15 HashSet (java.util.HashSet)15 AccountBuilder (com.github.ambry.account.AccountBuilder)14 MockRestResponseChannel (com.github.ambry.rest.MockRestResponseChannel)14 ContainerBuilder (com.github.ambry.account.ContainerBuilder)13 Properties (java.util.Properties)13 MetricRegistry (com.codahale.metrics.MetricRegistry)12 InMemAccountService (com.github.ambry.account.InMemAccountService)12 ByteBuffer (java.nio.ByteBuffer)12 RestMethod (com.github.ambry.rest.RestMethod)11 Map (java.util.Map)11