driftctl/pkg/remote/resource_enumeration_error_...

116 lines
3.6 KiB
Go
Raw Normal View History

package remote
import (
2021-02-11 11:21:49 +00:00
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
2021-12-06 13:29:39 +00:00
"github.com/snyk/driftctl/pkg/alerter"
"github.com/snyk/driftctl/pkg/remote/alerts"
"github.com/snyk/driftctl/pkg/remote/common"
remoteerror "github.com/snyk/driftctl/pkg/remote/error"
2021-08-04 15:17:27 +00:00
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
2021-06-28 09:00:59 +00:00
func HandleResourceEnumerationError(err error, alerter alerter.AlerterInterface) error {
listError, ok := err.(*remoteerror.ResourceScanningError)
if !ok {
return err
}
rootCause := listError.RootCause()
2021-08-04 15:17:27 +00:00
// We cannot use the status.FromError() method because AWS errors are not well-formed.
// Indeed, they compose the error interface without implementing the Error() method and thus triggering a nil panic
// when returning an unknown error from status.FromError()
// As a workaround we duplicated the logic from status.FromError here
if _, ok := rootCause.(interface{ GRPCStatus() *status.Status }); ok {
return handleGoogleEnumerationError(alerter, listError, status.Convert(rootCause))
}
2021-09-15 18:36:04 +00:00
// at least for storage api google sdk does not return grpc error so we parse the error message.
if shouldHandleGoogleForbiddenError(listError) {
alerts.SendEnumerationAlert(common.RemoteGoogleTerraform, alerter, listError)
return nil
}
reqerr, ok := rootCause.(awserr.RequestFailure)
if ok {
return handleAWSError(alerter, listError, reqerr)
}
// This handles access denied errors like the following:
// aws_s3_bucket_policy: AccessDenied: Error listing bucket policy <policy_name>
if strings.Contains(rootCause.Error(), "AccessDenied") {
2021-08-03 10:34:36 +00:00
alerts.SendEnumerationAlert(common.RemoteAWSTerraform, alerter, listError)
return nil
}
if strings.HasPrefix(
rootCause.Error(),
"Your token has not been granted the required scopes to execute this query.",
) {
2021-08-03 10:34:36 +00:00
alerts.SendEnumerationAlert(common.RemoteGithubTerraform, alerter, listError)
return nil
}
return err
}
func HandleResourceDetailsFetchingError(err error, alerter alerter.AlerterInterface) error {
listError, ok := err.(*remoteerror.ResourceScanningError)
if !ok {
return err
}
rootCause := listError.RootCause()
2021-09-15 18:36:04 +00:00
if shouldHandleGoogleForbiddenError(listError) {
2021-08-04 15:17:27 +00:00
alerts.SendDetailsFetchingAlert(common.RemoteGoogleTerraform, alerter, listError)
return nil
}
// This handles access denied errors like the following:
// iam_role_policy: error reading IAM Role Policy (<policy>): AccessDenied: User: <role_arn> ...
2021-08-02 12:17:27 +00:00
if strings.HasPrefix(rootCause.Error(), "AccessDeniedException") ||
strings.Contains(rootCause.Error(), "AccessDenied") ||
strings.Contains(rootCause.Error(), "AuthorizationError") {
2021-08-03 10:34:36 +00:00
alerts.SendDetailsFetchingAlert(common.RemoteAWSTerraform, alerter, listError)
return nil
}
return err
}
func handleAWSError(alerter alerter.AlerterInterface, listError *remoteerror.ResourceScanningError, reqerr awserr.RequestFailure) error {
if reqerr.StatusCode() == 403 || (reqerr.StatusCode() == 400 && strings.Contains(reqerr.Code(), "AccessDenied")) {
2021-08-03 10:34:36 +00:00
alerts.SendEnumerationAlert(common.RemoteAWSTerraform, alerter, listError)
return nil
}
return reqerr
}
2021-08-04 15:17:27 +00:00
func handleGoogleEnumerationError(alerter alerter.AlerterInterface, err *remoteerror.ResourceScanningError, st *status.Status) error {
if st.Code() == codes.PermissionDenied {
alerts.SendEnumerationAlert(common.RemoteGoogleTerraform, alerter, err)
return nil
}
return err
}
2021-09-15 18:36:04 +00:00
func shouldHandleGoogleForbiddenError(err *remoteerror.ResourceScanningError) bool {
2021-08-04 15:17:27 +00:00
errMsg := err.RootCause().Error()
// Check if this is a Google related error
if !strings.Contains(errMsg, "googleapi") {
return false
}
if strings.Contains(errMsg, "Error 403") {
return true
}
return false
}