Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1262,30 +1262,44 @@ public AnonymousUser getAnonymousUser() {
* @return the credentials
*/
public Credentials getCredentials(String accountID) {
Credentials credentials = null;
try {
AssumeRoleRequest assumeRoleRequest = ScalityModelConverter.getAssumeRoleRequestForAccount(accountID,
appEnv.getAssumeRoleName());
logger.debug("[Vault] Assume Role request:{}", assumeRoleRequest);
credentials = vaultAdmin.getTempAccountCredentials(assumeRoleRequest);
logger.debug("[Vault] Assume Role response received with access key:{}, expiration:{}",
credentials.getAccessKeyId(), credentials.getExpiration());
return assumeRole(accountID);
} catch (VaultServiceException e) {
if (!isAccessDenied(e)) {
throw e;
}
// if access denied, the osis role is not provisioned yet: set it up and retry once
logger.error(e.getReason() + ". Recreating the role");
// Call get Account with Account ID to retrieve account name
AccountData account = vaultAdmin.getAccount(ScalityModelConverter.toGetAccountRequestWithID(accountID));
asyncScalityOsisService.setupAssumeRole(accountID, account.getName());

if (!StringUtils.isNullOrEmpty(e.getErrorCode()) &&
ACCESS_DENIED.equals(e.getErrorCode())) {
// if access denied, invoke setupAssumeRole
logger.error(e.getReason() + ". Recreating the role");
// Call get Account with Account ID to retrieve account name
AccountData account = vaultAdmin.getAccount(ScalityModelConverter.toGetAccountRequestWithID(accountID));
asyncScalityOsisService.setupAssumeRole(accountID, account.getName());
return getCredentials(accountID);
try {
return assumeRole(accountID);
} catch (VaultServiceException retryError) {
if (isAccessDenied(retryError)) {
logger.error("Assume role still access-denied for account {} after recreating the role; "
+ "giving up to avoid unbounded retries", accountID);
}
throw retryError;
}
throw e;
}
}

private Credentials assumeRole(String accountID) {
AssumeRoleRequest assumeRoleRequest = ScalityModelConverter.getAssumeRoleRequestForAccount(accountID,
appEnv.getAssumeRoleName());
logger.debug("[Vault] Assume Role request:{}", assumeRoleRequest);
Credentials credentials = vaultAdmin.getTempAccountCredentials(assumeRoleRequest);
logger.debug("[Vault] Assume Role response received with access key:{}, expiration:{}",
credentials.getAccessKeyId(), credentials.getExpiration());
return credentials;
}

private boolean isAccessDenied(VaultServiceException e) {
return !StringUtils.isNullOrEmpty(e.getErrorCode()) && ACCESS_DENIED.equals(e.getErrorCode());
}

/**
* Create osis credential osis s 3 credential.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import java.util.List;
import java.util.Optional;

import static com.scality.osis.utils.ScalityConstants.IAM_PREFIX;
import static com.scality.osis.utils.ScalityConstants.*;
import static com.scality.osis.utils.ScalityTestUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -471,6 +471,25 @@ void testGetCredentials400() {
// Verify the results
}

@Test
void testGetCredentialsStopsRetryingWhenAccessDeniedPersists() {
// Setup: every assume-role attempt returns access-denied (persistent Vault misconfiguration)
when(vaultAdminMock.getTempAccountCredentials(any(AssumeRoleRequest.class)))
.thenThrow(new VaultServiceException(HttpStatus.FORBIDDEN, ACCESS_DENIED,
"User: backbeat is not allowed to assume role"));

// Run the test: persistent access-denied must surface as a VaultServiceException, not recurse forever
final VaultServiceException error = assertThrows(VaultServiceException.class,
() -> scalityOsisServiceUnderTest.getCredentials(TEST_TENANT_ID));

// Verify the results
assertEquals(ACCESS_DENIED, error.getErrorCode(), "Invalid Error Code");
// recovery routine (setupAssumeRole) is reached exactly once: it looks up the account name once
verify(vaultAdminMock, times(1)).getAccount(any(GetAccountRequestDTO.class));
// exactly one recovery means one original attempt plus one retry, no unbounded recursion
verify(vaultAdminMock, times(2)).getTempAccountCredentials(any(AssumeRoleRequest.class));
}

@Test
void testSetupAssumeRoleAsync() {

Expand Down
Loading