Skip to content

Commit

Permalink
HDDS-10200. CodecBuffer leak in TestMultiTenantVolume
Browse files Browse the repository at this point in the history
  • Loading branch information
adoroszlai committed Jan 24, 2024
1 parent 74fea96 commit d04291c
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,9 @@ public void put(String id, S3SecretValue secretValue) {
@Override
public void invalidate(String id) {
S3SecretValue secret = cache.getIfPresent(id);
if (secret == null) {
return;
if (secret != null) {
cache.put(id, secret.deleted());
}
secret.setDeleted(true);
secret.setAwsSecret(null);
cache.put(id, secret);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,33 @@ public static Codec<S3SecretValue> getCodec() {
}

// TODO: This field should be renamed to accessId for generalization.
private String kerberosID;
private String awsSecret;
private boolean isDeleted;
private long transactionLogIndex;
private final String kerberosID;
private final String awsSecret;
private final boolean isDeleted;
private final long transactionLogIndex;

public static S3SecretValue of(String kerberosID, String awsSecret) {
return of(kerberosID, awsSecret, 0);
}

public static S3SecretValue of(String kerberosID, String awsSecret, long transactionLogIndex) {
return new S3SecretValue(
Objects.requireNonNull(kerberosID),
Objects.requireNonNull(awsSecret),
false,
transactionLogIndex
);
}

public S3SecretValue(String kerberosID, String awsSecret) {
this(kerberosID, awsSecret, false, 0L);
}

public S3SecretValue(String kerberosID, String awsSecret, boolean isDeleted,
public S3SecretValue deleted() {
return new S3SecretValue(kerberosID, awsSecret, true, transactionLogIndex);
}

private S3SecretValue(String kerberosID, String awsSecret, boolean isDeleted,
long transactionLogIndex) {
this.kerberosID = kerberosID;
this.awsSecret = awsSecret;
Expand All @@ -59,26 +76,14 @@ public String getKerberosID() {
return kerberosID;
}

public void setKerberosID(String kerberosID) {
this.kerberosID = kerberosID;
}

public String getAwsSecret() {
return awsSecret;
}

public void setAwsSecret(String awsSecret) {
this.awsSecret = awsSecret;
}

public boolean isDeleted() {
return isDeleted;
}

public void setDeleted(boolean status) {
this.isDeleted = status;
}

public String getAwsAccessKey() {
return kerberosID;
}
Expand All @@ -87,12 +92,8 @@ public long getTransactionLogIndex() {
return transactionLogIndex;
}

public void setTransactionLogIndex(long transactionLogIndex) {
this.transactionLogIndex = transactionLogIndex;
}

public static S3SecretValue fromProtobuf(S3Secret s3Secret) {
return new S3SecretValue(s3Secret.getKerberosID(), s3Secret.getAwsSecret());
return S3SecretValue.of(s3Secret.getKerberosID(), s3Secret.getAwsSecret());
}

public S3Secret getProtobuf() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public void testS3Auth() throws Exception {

// Add secret to S3Secret table.
s3SecretManager.storeSecret(accessKey,
new S3SecretValue(accessKey, secret));
S3SecretValue.of(accessKey, secret));

OMRequest writeRequest = OMRequest.newBuilder()
.setCmdType(OzoneManagerProtocolProtos.Type.CreateVolume)
Expand Down Expand Up @@ -313,7 +313,7 @@ public void testS3Auth() throws Exception {

// Override secret to S3Secret store with some dummy value
s3SecretManager
.storeSecret(accessKey, new S3SecretValue(accessKey, "dummy"));
.storeSecret(accessKey, S3SecretValue.of(accessKey, "dummy"));

// Write request with invalid credentials.
omResponse = cluster.getOzoneManager().getOmServerProtocol()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void testCodecWithCorrectData() throws Exception {
final Codec<S3SecretValue> codec = getCodec();

S3SecretValue s3SecretValue =
new S3SecretValue(UUID.randomUUID().toString(),
S3SecretValue.of(UUID.randomUUID().toString(),
UUID.randomUUID().toString());

byte[] data = codec.toPersistedFormat(s3SecretValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ public S3SecretValue getSecret(String kerberosID) throws IOException {
// purposely deleted the secret. Hence, we do not have to check the DB.
return null;
}
return new S3SecretValue(cacheValue.getKerberosID(),
cacheValue.getAwsSecret());
return cacheValue;
}
S3SecretValue result = s3SecretStore.getSecret(kerberosID);
if (result != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,26 +113,23 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, TermIn
try {
omClientResponse = ozoneManager.getS3SecretManager()
.doUnderLock(accessId, s3SecretManager -> {
// Intentionally set to final so they can only be set once.
final S3SecretValue newS3SecretValue;

// Update legacy S3SecretTable, if the accessId entry exists
if (s3SecretManager.hasS3Secret(accessId)) {
// accessId found in S3SecretTable. Update S3SecretTable
LOG.debug("Updating S3SecretTable cache entry");
// Update S3SecretTable cache entry in this case
newS3SecretValue = new S3SecretValue(accessId, secretKey);
// Set the transactionLogIndex to be used for updating.
newS3SecretValue.setTransactionLogIndex(termIndex.getIndex());
s3SecretManager
.updateCache(accessId, newS3SecretValue);
} else {
if (!s3SecretManager.hasS3Secret(accessId)) {
// If S3SecretTable is not updated,
// throw ACCESS_ID_NOT_FOUND exception.
throw new OMException("accessId '" + accessId + "' not found.",
OMException.ResultCodes.ACCESS_ID_NOT_FOUND);
}

// accessId found in S3SecretTable. Update S3SecretTable
LOG.debug("Updating S3SecretTable cache entry");

// Update S3SecretTable cache entry in this case
// Set the transactionLogIndex to be used for updating.
final S3SecretValue newS3SecretValue = S3SecretValue.of(accessId, secretKey, termIndex.getIndex());
s3SecretManager.updateCache(accessId, newS3SecretValue);

// Compose response
final SetS3SecretResponse.Builder setSecretResponse =
SetS3SecretResponse.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,21 +150,16 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, TermIn
try {
omClientResponse = ozoneManager.getS3SecretManager()
.doUnderLock(accessId, s3SecretManager -> {
S3SecretValue assignS3SecretValue;
S3SecretValue s3SecretValue =
s3SecretManager.getSecret(accessId);
final S3SecretValue assignS3SecretValue;
S3SecretValue s3SecretValue = s3SecretManager.getSecret(accessId);

if (s3SecretValue == null) {
// Not found in S3SecretTable.
if (createIfNotExist) {
// Add new entry in this case
assignS3SecretValue =
new S3SecretValue(accessId, awsSecret.get());
// Set the transactionLogIndex to be used for updating.
assignS3SecretValue.setTransactionLogIndex(termIndex.getIndex());
assignS3SecretValue = S3SecretValue.of(accessId, awsSecret.get(), termIndex.getIndex());
// Add cache entry first.
s3SecretManager.updateCache(accessId,
assignS3SecretValue);
s3SecretManager.updateCache(accessId, assignS3SecretValue);
} else {
assignS3SecretValue = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, TermIn
}
}

final S3SecretValue s3SecretValue =
new S3SecretValue(accessId, awsSecret);
// Set the transactionLogIndex to be used for updating.
s3SecretValue.setTransactionLogIndex(transactionLogIndex);
final S3SecretValue s3SecretValue = S3SecretValue.of(accessId, awsSecret, transactionLogIndex);

// Add to tenantAccessIdTable
final OmDBAccessIdInfo omDBAccessIdInfo = new OmDBAccessIdInfo.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ public void setUp() throws Exception {
serviceRpcAdd = new Text("localhost");
final Map<String, S3SecretValue> s3Secrets = new HashMap<>();
s3Secrets.put("testuser1",
new S3SecretValue("testuser1", "dbaksbzljandlkandlsd"));
S3SecretValue.of("testuser1", "dbaksbzljandlkandlsd"));
s3Secrets.put("abc",
new S3SecretValue("abc", "djakjahkd"));
S3SecretValue.of("abc", "djakjahkd"));
om = mock(OzoneManager.class);
OMMetadataManager metadataManager = new OmMetadataManagerImpl(conf, om);
when(om.getMetadataManager()).thenReturn(metadataManager);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public S3SecretValue getSecret(String kerberosID) throws IOException {
return null;
}

return new S3SecretValue(kerberosID, s3Secret);
return S3SecretValue.of(kerberosID, s3Secret);
} catch (VaultException e) {
LOG.error("Failed to read secret", e);
throw new IOException("Failed to read secret", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public void clean() {
@Test
public void testReadWrite() throws IOException {
SUCCESS_OPERATION_LIMIT.set(2);
S3SecretValue secret = new S3SecretValue("id", "value");
S3SecretValue secret = S3SecretValue.of("id", "value");
s3SecretStore.storeSecret(
"id",
secret);
Expand All @@ -101,7 +101,7 @@ public void testReadWrite() throws IOException {
public void testReAuth() throws IOException {
SUCCESS_OPERATION_LIMIT.set(1);
AUTH_OPERATION_PROVIDER.set(1);
S3SecretValue secret = new S3SecretValue("id", "value");
S3SecretValue secret = S3SecretValue.of("id", "value");
s3SecretStore.storeSecret("id", secret);

assertEquals(secret, s3SecretStore.getSecret("id"));
Expand All @@ -112,7 +112,7 @@ public void testReAuth() throws IOException {
@Test
public void testAuthFail() throws IOException {
SUCCESS_OPERATION_LIMIT.set(1);
S3SecretValue secret = new S3SecretValue("id", "value");
S3SecretValue secret = S3SecretValue.of("id", "value");
s3SecretStore.storeSecret("id", secret);

assertThrows(IOException.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ public void cancelDelegationToken(Token<OzoneTokenIdentifier> token)
@Override
@Nonnull
public S3SecretValue getS3Secret(String kerberosID) throws IOException {
return new S3SecretValue(STUB_KERBEROS_ID, STUB_SECRET);
return S3SecretValue.of(STUB_KERBEROS_ID, STUB_SECRET);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@

import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.when;

/**
* Test for S3 secret generate endpoint.
*/
@ExtendWith(MockitoExtension.class)
public class TestSecretGenerate {
class TestSecretGenerate {
private static final String USER_NAME = "test";
private static final String OTHER_USER_NAME = "test2";
private static final String USER_SECRET = "test_secret";
Expand All @@ -69,12 +69,11 @@ public class TestSecretGenerate {

private static S3SecretValue getS3SecretValue(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
return new S3SecretValue((String) args[0], USER_SECRET);
return S3SecretValue.of((String) args[0], USER_SECRET);
}

@BeforeEach
void setUp() throws IOException {
when(proxy.getS3Secret(any())).then(TestSecretGenerate::getS3SecretValue);
void setUp() {
OzoneConfiguration conf = new OzoneConfiguration();
OzoneClient client = new OzoneClientStub(new ObjectStoreStub(conf, proxy));

Expand All @@ -89,23 +88,20 @@ void setUp() throws IOException {

@Test
void testSecretGenerate() throws IOException {
when(principal.getName()).thenReturn(USER_NAME);
when(securityContext.getUserPrincipal()).thenReturn(principal);
when(context.getSecurityContext()).thenReturn(securityContext);
setupSecurityContext();
hasNoSecretYet();

S3SecretResponse response =
(S3SecretResponse) endpoint.generate().getEntity();

assertEquals(USER_SECRET, response.getAwsSecret());
assertEquals(USER_NAME, response.getAwsAccessKey());
}

@Test
void testIfSecretAlreadyExists() throws IOException {
when(principal.getName()).thenReturn(USER_NAME);
when(securityContext.getUserPrincipal()).thenReturn(principal);
when(context.getSecurityContext()).thenReturn(securityContext);
when(proxy.getS3Secret(any())).thenThrow(new OMException("Secret already exists",
OMException.ResultCodes.S3_SECRET_ALREADY_EXISTS));
setupSecurityContext();
hasSecretAlready();

Response response = endpoint.generate();

Expand All @@ -116,9 +112,27 @@ void testIfSecretAlreadyExists() throws IOException {

@Test
void testSecretGenerateWithUsername() throws IOException {
hasNoSecretYet();

S3SecretResponse response =
(S3SecretResponse) endpoint.generate(OTHER_USER_NAME).getEntity();
assertEquals(USER_SECRET, response.getAwsSecret());
assertEquals(OTHER_USER_NAME, response.getAwsAccessKey());
}

private void setupSecurityContext() {
when(principal.getName()).thenReturn(USER_NAME);
when(securityContext.getUserPrincipal()).thenReturn(principal);
when(context.getSecurityContext()).thenReturn(securityContext);
}

private void hasNoSecretYet() throws IOException {
when(proxy.getS3Secret(notNull()))
.then(TestSecretGenerate::getS3SecretValue);
}

private void hasSecretAlready() throws IOException {
when(proxy.getS3Secret(notNull()))
.thenThrow(new OMException("Secret already exists", OMException.ResultCodes.S3_SECRET_ALREADY_EXISTS));
}
}

0 comments on commit d04291c

Please sign in to comment.