package software.amazon.fms.policy; import org.apache.commons.lang3.StringUtils; import software.amazon.awssdk.services.fms.FmsClient; import software.amazon.awssdk.services.fms.model.GetPolicyRequest; import software.amazon.awssdk.services.fms.model.GetPolicyResponse; import software.amazon.awssdk.services.fms.model.ListTagsForResourceRequest; import software.amazon.awssdk.services.fms.model.ListTagsForResourceResponse; import software.amazon.awssdk.services.fms.model.PutPolicyRequest; import software.amazon.awssdk.services.fms.model.PutPolicyResponse; import software.amazon.awssdk.services.fms.model.ResourceNotFoundException; import software.amazon.awssdk.services.fms.model.Tag; import software.amazon.awssdk.services.fms.model.TagResourceRequest; import software.amazon.awssdk.services.fms.model.TagResourceResponse; import software.amazon.awssdk.services.fms.model.UntagResourceRequest; import software.amazon.awssdk.services.fms.model.UntagResourceResponse; import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy; import software.amazon.cloudformation.proxy.Logger; import software.amazon.cloudformation.proxy.ProgressEvent; import software.amazon.cloudformation.proxy.ResourceHandlerRequest; import software.amazon.fms.policy.helpers.CfnHelper; import software.amazon.fms.policy.helpers.FmsHelper; import java.util.List; public class UpdateHandler extends PolicyHandler<PutPolicyResponse> { UpdateHandler() { super(); } UpdateHandler(final FmsClient client) { super(client); } @Override protected PutPolicyResponse makeRequest( final AmazonWebServicesClientProxy proxy, final ResourceHandlerRequest<ResourceModel> request, final Logger logger) { // make a read request to retrieve an up-to-date PolicyUpdateToken logger.log("Retrieving existing policy"); if (StringUtils.isBlank(request.getDesiredResourceState().getId())) { throw ResourceNotFoundException.builder() .message("Firewall manager policy with the provided reference ID does not exist").build(); } final GetPolicyRequest getPolicyRequest = GetPolicyRequest.builder() .policyId(request.getDesiredResourceState().getId()) .build(); final GetPolicyResponse getPolicyResponse = proxy.injectCredentialsAndInvokeV2( getPolicyRequest, client::getPolicy); logger.log("Policy retrieved successfully"); logRequest(getPolicyResponse, logger); // make the update request logger.log("Updating existing policy"); final PutPolicyRequest putPolicyRequest = PutPolicyRequest.builder() .policy(FmsHelper.convertCFNResourceModelToFMSPolicy( request.getDesiredResourceState(), getPolicyResponse.policy().policyUpdateToken())) .build(); final PutPolicyResponse putPolicyResponse = proxy.injectCredentialsAndInvokeV2( putPolicyRequest, client::putPolicy); logger.log("Policy updated successfully"); logRequest(putPolicyResponse, logger); // make a list request to get the current tags on the policy logger.log("Retrieving policy tags"); final ListTagsForResourceRequest listTagsForResourceRequest = ListTagsForResourceRequest.builder() .resourceArn(getPolicyResponse.policyArn()) .build(); final ListTagsForResourceResponse listTagsForResourceResponse = proxy.injectCredentialsAndInvokeV2( listTagsForResourceRequest, client::listTagsForResource); logger.log("Policy tags retrieved successfully"); logRequest(listTagsForResourceResponse, logger); // determine tags to remove and add final List<String> removeTags = FmsHelper.tagsToRemove( listTagsForResourceResponse.tagList(), request.getDesiredResourceTags()); final List<Tag> addTags = FmsHelper.tagsToAdd( listTagsForResourceResponse.tagList(), request.getDesiredResourceTags()); // make an untag request if (!removeTags.isEmpty()) { logger.log(String.format("Removing %d tag/s", removeTags.size())); final UntagResourceRequest untagResourceRequest = UntagResourceRequest.builder() .resourceArn(getPolicyResponse.policyArn()) .tagKeys(removeTags) .build(); final UntagResourceResponse untagResourceResponse = proxy.injectCredentialsAndInvokeV2( untagResourceRequest, client::untagResource); logger.log("Tags removed successfully"); logRequest(untagResourceResponse, logger); } else { logger.log("No tags to remove"); } // make a tag request if (!addTags.isEmpty()) { logger.log(String.format("Adding %d tag/s", addTags.size())); final TagResourceRequest tagResourceRequest = TagResourceRequest.builder() .resourceArn(getPolicyResponse.policyArn()) .tagList(addTags) .build(); final TagResourceResponse tagResourceResponse = proxy.injectCredentialsAndInvokeV2( tagResourceRequest, client::tagResource); logger.log("Tags added successfully"); logRequest(tagResourceResponse, logger); } else { logger.log("No tags to add"); } // return the status of the policy update return putPolicyResponse; } @Override protected ProgressEvent<ResourceModel, CallbackContext> constructSuccessProgressEvent( final PutPolicyResponse response, final ResourceHandlerRequest<ResourceModel> request, final AmazonWebServicesClientProxy proxy) { return ProgressEvent.defaultSuccessHandler(constructSuccessResourceModel(response, request, proxy)); } private ResourceModel constructSuccessResourceModel( final PutPolicyResponse response, final ResourceHandlerRequest<ResourceModel> request, final AmazonWebServicesClientProxy proxy) { // convert the update request response to a resource model return CfnHelper.convertFMSPolicyToCFNResourceModel( response.policy(), response.policyArn(), FmsHelper.convertCFNTagMapToFMSTagSet(request.getDesiredResourceTags())); } }