Implement Field Level Redaction
The $redact
pipeline operator restricts the contents of thedocuments based on information stored in the documents themselves.
To store the access criteria data, add a field to the documents andembedded documents. To allow for multiple combinations of access levels forthe same data, consider setting the access field to an array of arrays.Each array element contains a required set that allows a user with thatset to access the data.
Then, include the $redact
stage in thedb.collection.aggregate()
operation to restrict contents ofthe result set based on the access required to view the data.
For more information on the $redact
pipeline operator,including its syntax and associated system variables as well asadditional examples, see $redact
.
Procedure
For example, a forecasts
collection contains documents of thefollowing form where the tags
field determines the access levelsrequired to view the data:
- {
- _id: 1,
- title: "123 Department Report",
- tags: [ [ "G" ], [ "FDW" ] ],
- year: 2014,
- subsections: [
- {
- subtitle: "Section 1: Overview",
- tags: [ [ "SI", "G" ], [ "FDW" ] ],
- content: "Section 1: This is the content of section 1."
- },
- {
- subtitle: "Section 2: Analysis",
- tags: [ [ "STLW" ] ],
- content: "Section 2: This is the content of section 2."
- },
- {
- subtitle: "Section 3: Budgeting",
- tags: [ [ "TK" ], [ "FDW", "TGE" ] ],
- content: {
- text: "Section 3: This is the content of section3.",
- tags: [ [ "HCS"], [ "FDW", "TGE", "BX" ] ]
- }
- }
- ]
- }
For each document, the tags
field contains various access groupingsnecessary to view the data. For example, the value [ [ "G" ], ["FDW", "TGE" ] ]
can specify that a user requires either access level["G"]
or both [ "FDW", "TGE" ]
to view the data.
Consider a user who only has access to view information tagged witheither "FDW"
or "TGE"
. To run a query on all documents withyear 2014
for this user, include a $redact
stage as inthe following:
- var userAccess = [ "FDW", "TGE" ];
- db.forecasts.aggregate(
- [
- { $match: { year: 2014 } },
- { $redact:
- {
- $cond: {
- if: { $anyElementTrue:
- {
- $map: {
- input: "$tags" ,
- as: "fieldTag",
- in: { $setIsSubset: [ "$$fieldTag", userAccess ] }
- }
- }
- },
- then: "$$DESCEND",
- else: "$$PRUNE"
- }
- }
- }
- ]
- )
The aggregation operation returns the following “redacted” document for the user:
- { "_id" : 1,
- "title" : "123 Department Report",
- "tags" : [ [ "G" ], [ "FDW" ] ],
- "year" : 2014,
- "subsections" :
- [
- {
- "subtitle" : "Section 1: Overview",
- "tags" : [ [ "SI", "G" ], [ "FDW" ] ],
- "content" : "Section 1: This is the content of section 1."
- },
- {
- "subtitle" : "Section 3: Budgeting",
- "tags" : [ [ "TK" ], [ "FDW", "TGE" ] ]
- }
- ]
- }
See also