Skip to content

Commit

Permalink
Silent fail when list tags permission is missing
Browse files Browse the repository at this point in the history
  • Loading branch information
gruebel committed Dec 9, 2020
1 parent b79f187 commit e8b0238
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package software.amazon.logs.loggroup;

import software.amazon.awssdk.services.cloudwatchlogs.model.CloudWatchLogsException;
import software.amazon.awssdk.services.cloudwatchlogs.model.ListTagsLogGroupResponse;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.Logger;
Expand All @@ -12,6 +13,8 @@

public class ReadHandler extends BaseHandler<CallbackContext> {

private static final String ACCESS_DENIED_ERROR_CODE = "AccessDeniedException";

@Override
public ProgressEvent<ResourceModel, CallbackContext> handleRequest(
final AmazonWebServicesClientProxy proxy,
Expand All @@ -30,8 +33,17 @@ public ProgressEvent<ResourceModel, CallbackContext> handleRequest(
try {
response = proxy.injectCredentialsAndInvokeV2(Translator.translateToReadRequest(model),
ClientBuilder.getClient()::describeLogGroups);
tagsResponse = proxy.injectCredentialsAndInvokeV2(Translator.translateToListTagsLogGroupRequest(model.getLogGroupName()),
ClientBuilder.getClient()::listTagsLogGroup);
try {
tagsResponse = proxy.injectCredentialsAndInvokeV2(Translator.translateToListTagsLogGroupRequest(model.getLogGroupName()),
ClientBuilder.getClient()::listTagsLogGroup);
} catch (final CloudWatchLogsException e) {
if (ACCESS_DENIED_ERROR_CODE.equals(e.awsErrorDetails().errorCode())) {
// fail silently, if there is no permission to list tags
logger.log(e.getMessage());
} else {
throw e;
}
}
} catch (final ResourceNotFoundException e) {
throwNotFoundException(model);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ static ResourceModel translateForRead(final DescribeLogGroupsResponse response,
.filter(Objects::nonNull)
.findAny()
.orElse(null);
final Set<Tag> tags = translateSdkToTags(tagsResponse.tags());
final Set<Tag> tags = translateSdkToTags(Optional.ofNullable(tagsResponse)
.map(ListTagsLogGroupResponse::tags)
.orElse(null));
return ResourceModel.builder()
.arn(logGroupArn)
.logGroupName(logGroupName)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package software.amazon.logs.loggroup;

import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.services.cloudwatchlogs.model.CloudWatchLogsException;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogGroupsRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.ListTagsLogGroupRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.ListTagsLogGroupResponse;
import software.amazon.cloudformation.exceptions.ResourceNotFoundException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
Expand All @@ -22,6 +27,7 @@
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
Expand Down Expand Up @@ -167,4 +173,99 @@ public void handleRequest_FailureNotFound_NullModel() {
assertThrows(ResourceNotFoundException.class,
() -> handler.handleRequest(proxy, request, null, logger));
}

@Test
public void handleRequest_FailureListTagsAccessDenied_NoException() {
final LogGroup logGroup = LogGroup.builder()
.logGroupName("LogGroup")
.retentionInDays(1)
.kmsKeyId("arn:aws:kms:us-east-1:$123456789012:key/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
.build();
final DescribeLogGroupsResponse describeResponse = DescribeLogGroupsResponse.builder()
.logGroups(Collections.singletonList(logGroup))
.build();

doReturn(describeResponse)
.when(proxy)
.injectCredentialsAndInvokeV2(
ArgumentMatchers.isA(DescribeLogGroupsRequest.class),
ArgumentMatchers.any()
);
final AwsServiceException exception = CloudWatchLogsException.builder()
.awsErrorDetails(AwsErrorDetails.builder()
.errorCode("AccessDeniedException")
.build())
.build();
doThrow(exception)
.when(proxy)
.injectCredentialsAndInvokeV2(
ArgumentMatchers.isA(ListTagsLogGroupRequest.class),
ArgumentMatchers.any()
);

final ResourceModel model = ResourceModel.builder()
.logGroupName("LogGroup")
.retentionInDays(1)
.kmsKeyId("arn:aws:kms:us-east-1:$123456789012:key/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
.build();

final ResourceHandlerRequest<ResourceModel> request = ResourceHandlerRequest.<ResourceModel>builder()
.desiredResourceState(model)
.build();

final ProgressEvent<ResourceModel, CallbackContext> response = handler.handleRequest(proxy, request, null, logger);

assertThat(response).isNotNull();
assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
assertThat(response.getCallbackContext()).isNull();
assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
assertThat(response.getResourceModels()).isNull();
assertThat(response.getResourceModel()).isEqualToComparingOnlyGivenFields(logGroup);
assertThat(response.getResourceModel().getTags()).isNull();
assertThat(response.getMessage()).isNull();
assertThat(response.getErrorCode()).isNull();
}

@Test
public void handleRequest_FailureListTags_WithException() {
final LogGroup logGroup = LogGroup.builder()
.logGroupName("LogGroup")
.retentionInDays(1)
.kmsKeyId("arn:aws:kms:us-east-1:$123456789012:key/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
.build();
final DescribeLogGroupsResponse describeResponse = DescribeLogGroupsResponse.builder()
.logGroups(Collections.singletonList(logGroup))
.build();

doReturn(describeResponse)
.when(proxy)
.injectCredentialsAndInvokeV2(
ArgumentMatchers.isA(DescribeLogGroupsRequest.class),
ArgumentMatchers.any()
);
final AwsServiceException exception = CloudWatchLogsException.builder()
.awsErrorDetails(AwsErrorDetails.builder()
.errorCode("InternalFailure")
.build())
.build();
doThrow(exception)
.when(proxy)
.injectCredentialsAndInvokeV2(
ArgumentMatchers.isA(ListTagsLogGroupRequest.class),
ArgumentMatchers.any()
);

final ResourceModel model = ResourceModel.builder()
.logGroupName("LogGroup")
.retentionInDays(1)
.kmsKeyId("arn:aws:kms:us-east-1:$123456789012:key/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
.build();

final ResourceHandlerRequest<ResourceModel> request = ResourceHandlerRequest.<ResourceModel>builder()
.desiredResourceState(model)
.build();

assertThrows(AwsServiceException.class,
() -> handler.handleRequest(proxy, request, null, logger));
}
}

0 comments on commit e8b0238

Please sign in to comment.