diff --git a/internal/daemon/controller/handlers/credentials/credential_service.go b/internal/daemon/controller/handlers/credentials/credential_service.go index fd5d8702e0..239fde8c55 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service.go +++ b/internal/daemon/controller/handlers/credentials/credential_service.go @@ -848,15 +848,18 @@ func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error { case credential.JsonSubtype: object := req.GetItem().GetJsonAttributes().GetObject() if object != nil { - objectBytes, err := json.Marshal(object.AsMap()) + _, err := json.Marshal(object.AsMap()) if err != nil { badFields[objectField] = "Unable to parse given json value" } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), objectField) && len(objectBytes) <= 0 { + if !handlers.MaskContainsPrefix(req.GetUpdateMask().GetPaths(), objectField) { + badFields[objectField] = "This is a required field and cannot be set to empty." + } + if len(object.AsMap()) == 0 { badFields[objectField] = "This is a required field and cannot be set to empty." } } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), objectField) && object == nil { + if handlers.MaskContainsPrefix(req.GetUpdateMask().GetPaths(), objectField) && object == nil { badFields[objectField] = "This is a required field and cannot be set to empty." } diff --git a/internal/daemon/controller/handlers/credentials/credential_service_test.go b/internal/daemon/controller/handlers/credentials/credential_service_test.go index 56670133ef..18c1e31f3d 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service_test.go +++ b/internal/daemon/controller/handlers/credentials/credential_service_test.go @@ -1150,6 +1150,48 @@ func TestUpdate(t *testing.T) { return out }, }, + { + name: "update-empty-json", + req: &pbs.UpdateCredentialRequest{ + UpdateMask: fieldmask(), + Item: &pb.Credential{ + Attrs: &pb.Credential_JsonAttributes{ + JsonAttributes: &pb.JsonAttributes{ + Object: &structpb.Struct{}, + }, + }, + }, + }, + expErrorContains: "This is a required field and cannot be set to empty", + }, + { + name: "update-empty-object-json", + req: &pbs.UpdateCredentialRequest{ + UpdateMask: fieldmask("attributes.object.password"), + Item: &pb.Credential{ + Attrs: &pb.Credential_JsonAttributes{ + JsonAttributes: &pb.JsonAttributes{ + Object: &structpb.Struct{}, + }, + }, + }, + }, + expErrorContains: "This is a required field and cannot be set to empty", + }, + { + name: "update-empty-mask-json", + req: &pbs.UpdateCredentialRequest{ + UpdateMask: fieldmask(), + Item: &pb.Credential{ + Attrs: &pb.Credential_JsonAttributes{ + JsonAttributes: &pb.JsonAttributes{ + Object: secondSecret, + }, + }, + }, + }, + expErrorContains: "This is a required field and cannot be set to empty", + }, { name: "update-spk-with-bad-passphrase", req: &pbs.UpdateCredentialRequest{ diff --git a/internal/daemon/controller/handlers/mask_manager.go b/internal/daemon/controller/handlers/mask_manager.go index f19cf25a31..36be77d700 100644 --- a/internal/daemon/controller/handlers/mask_manager.go +++ b/internal/daemon/controller/handlers/mask_manager.go @@ -120,3 +120,12 @@ func MaskContains(paths []string, s string) bool { } return false } + +func MaskContainsPrefix(paths []string, s string) bool { + for _, p := range paths { + if strings.Contains(p, s) { + return true + } + } + return false +}