fix: Append list error for permission validation (#48)

* fix: Append list error for permission validation

Instead of returning the error right away, append the error when `ListObject` is successful but the key expected if not found. Set the `Read` permission state as `Unknown` if the response from the list calls does not find the expected key.

This can be caused if the credentials do not have `s3:PutObject` but have `s3:ListBucket`. Without `s3:PutObject`, the object will not be written to S3 so other calls to find the object will not be successful even if they have valid permissions.

This prevents us from returning a `write` error on Boundary because the list call will always fail. Without this, the  Permissions are not wrapped and the SBC states are all set to `unknown` even though we know certain permission failed.
This commit is contained in:
Elim Tsiagbey authored and GitHub committed 2024-07-24 11:48:14 -04:00
1 parent 5add0a1b53
commit c2e7c94f9c
2 files changed
+39 -1

No files matched your search

+2 -1
View File
@@ -820,7 +820,8 @@ func dryRunValidation(ctx context.Context, state *awsStoragePersistedState, attr
st, permissions.Read = errors.ParseAWSError(err, "failed to list object")
errs = multierror.Append(errs, st.Err())
} else if res == nil || len(res.Contents) != 1 || *res.Contents[0].Key != objectKey {
return status.New(codes.Aborted, fmt.Sprintf("list response did not contain the expected key: %+v", res))
permissions.Read = &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, CheckedAt: timestamppb.Now()}
errs = multierror.Append(errs, status.New(codes.Aborted, fmt.Sprintf("list response did not contain the expected key: %+v", res)).Err())
}
if _, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{
+37
View File
@@ -2666,6 +2666,43 @@ func TestStoragePlugin_ValidatePermissions(t *testing.T) {
),
},
},
{
name: "dryRunValidation failed putObject with missing list expected key",
req: validRequest(),
credOpts: validSTSMock(),
storageOpts: []awsStoragePersistedStateOption{
withTestS3APIFunc(newTestMockS3(
nil,
testMockS3WithPutObjectError(TestAwsS3Error("AccessDenied", "PutObject", "not authorized")),
testMockS3WithGetObjectOutput(&s3.GetObjectOutput{}),
testMockS3WithHeadObjectOutput(&s3.HeadObjectOutput{}),
testMockS3WithListObjectsV2OutputFunc(func(i *s3.ListObjectsV2Input) *s3.ListObjectsV2Output {
return &s3.ListObjectsV2Output{
Contents: []s3types.Object{},
}
}),
)),
},
expectedErrContains: "aws service s3: invalid credentials error: failed to put object",
expectedErrCode: codes.FailedPrecondition,
expectedDetails: &pb.StorageBucketCredentialState{
State: &pb.Permissions{
Read: &pb.Permission{
State: pb.StateType_STATE_TYPE_UNKNOWN,
CheckedAt: timestamppb.Now(),
},
Write: &pb.Permission{
State: pb.StateType_STATE_TYPE_ERROR,
ErrorDetails: "not authorized",
CheckedAt: timestamppb.Now(),
},
Delete: &pb.Permission{
State: pb.StateType_STATE_TYPE_OK,
CheckedAt: timestamppb.Now(),
},
},
},
},
}
for _, tc := range cases {