-
Notifications
You must be signed in to change notification settings - Fork 8
Fix: Non-draft support and MTLS Support for Multitenant S3 Access #232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 18 commits
4a58656
3afd564
06d8027
286aca4
68110b0
7125317
b3b80fd
4797bd3
29f8896
ae6ed4d
ba26b50
d0a019c
0d6c9d2
3b853c0
6a20230
861699a
23ac419
478d77e
9b4ea32
95b9d8d
0def121
a6c8392
0a1644c
57aaacb
19a9761
2ff1f7d
d540f3d
63dc013
4ca8b96
10949a2
18eb037
ec7949c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ const DEBUG = cds.debug('attachments') | |
const { SELECT } = cds.ql; | ||
|
||
async function scanRequest(Attachments, key, req) { | ||
DEBUG?.(`Malware Scanning: Scanning content to entity ${key}`); | ||
const scanEnabled = cds.env.requires?.attachments?.scan ?? true | ||
const AttachmentsSrv = await cds.connect.to("attachments") | ||
|
||
|
@@ -14,6 +15,8 @@ async function scanRequest(Attachments, key, req) { | |
activeEntity = Attachments | ||
} | ||
|
||
DEBUG?.(`Malware Scanning: Scanning content to entity ${key} - activeEntity = ${activeEntity}`); | ||
|
||
let currEntity = draftEntity == undefined ? activeEntity : draftEntity | ||
|
||
if (!scanEnabled) { | ||
|
@@ -30,13 +33,20 @@ async function scanRequest(Attachments, key, req) { | |
} | ||
} | ||
|
||
DEBUG?.(`Malware Scanning: Scanning content to entity ${key} - setting status to "Scanning"`); | ||
|
||
await updateStatus(AttachmentsSrv, key, "Scanning", currEntity, draftEntity, activeEntity) | ||
|
||
const credentials = getCredentials() | ||
DEBUG?.(`Malware Scanning: Scanning content to entity ${key} - credentials = ${JSON.stringify(credentials)}`); | ||
const contentStream = await AttachmentsSrv.get(currEntity, key) | ||
|
||
DEBUG?.(`Malware Scanning: Scanning content to entity ${key} - contentStream = ${contentStream}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we logging contentStream binary ? What purpose does it serve? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above - just checking if every step is being complete, since in BTP is not possible to debug with breakpoints. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll move this to a separate PR. |
||
|
||
let fileContent | ||
try { | ||
fileContent = await streamToString(contentStream) | ||
fileContent = await streamToString(contentStream); | ||
|
||
} catch (err) { | ||
DEBUG?.("Malware Scanning: Cannot read file content", err) | ||
await updateStatus(AttachmentsSrv, key, "Failed", currEntity, draftEntity, activeEntity) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,8 +40,7 @@ cds.once("served", async function registerPluginHandlers () { | |
if (elementName === "SiblingEntity") continue // REVISIT: Why do we have this? | ||
const element = entity.elements[elementName], target = element._target | ||
|
||
if (!target?.["@_is_media_data"]) continue; | ||
|
||
if (!isAttachmentAnnotated(target)) continue; | ||
const isDraft = !!target?.drafts; | ||
const targets = isDraft ? [target, target.drafts] : [target]; | ||
|
||
|
@@ -51,32 +50,32 @@ cds.once("served", async function registerPluginHandlers () { | |
|
||
srv.after("READ", targets, readAttachment) | ||
|
||
const putTarget = isDraft ? target.drafts : target; | ||
srv.before("PUT", putTarget, (req) => validateAttachmentSize(req)) | ||
|
||
const op = isDraft ? "NEW" : "CREATE"; | ||
srv.before(op, putTarget, (req) => { | ||
req.data.url = cds.utils.uuid() | ||
const isMultitenacyEnabled = !!cds.env.requires.multitenancy; | ||
const objectStoreKind = cds.env.requires?.attachments?.objectStore?.kind; | ||
if (isMultitenacyEnabled && objectStoreKind === "shared") { | ||
req.data.url = `${req.tenant}_${req.data.url}`; | ||
} | ||
req.data.ID = cds.utils.uuid() | ||
let ext = extname(req.data.filename).toLowerCase().slice(1) | ||
req.data.mimeType = Ext2MimeTyes[ext] || "application/octet-stream" | ||
}); | ||
|
||
if (isDraft) { | ||
AttachmentsSrv.registerUpdateHandlers(srv, entity, target) | ||
srv.before("PUT", target.drafts, (req) => validateAttachmentSize(req)) | ||
srv.before("NEW", target.drafts, (req) => onPrepareAttachment(req)); | ||
AttachmentsSrv.registerDraftUpdateHandlers(srv, entity, target) | ||
} else { | ||
srv.after("PUT", target, (req) => nonDraftUpload(req, target)) | ||
srv.before("PUT", target, (req) => validateAttachmentSize(req)) | ||
srv.before("CREATE", target, (req) => onPrepareAttachment(req)); | ||
AttachmentsSrv.registerUpdateHandlers(srv, entity, target); | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
function onPrepareAttachment (req) { | ||
req.data.url = cds.utils.uuid() | ||
const isMultitenacyEnabled = !!cds.env.requires.multitenancy; | ||
const objectStoreKind = cds.env.requires?.attachments?.objectStore?.kind; | ||
if (isMultitenacyEnabled && objectStoreKind === "shared") { | ||
req.data.url = `${req.tenant}_${req.data.url}`; | ||
} | ||
req.data.ID = cds.utils.uuid() | ||
let ext = extname(req.data.filename).toLowerCase().slice(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any chance the user sends the request with a file without extension? Will this code break if extension is not there for file ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like that if nothing is found at the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, The code will not break if there’s no file extension. It will simply assign mimeType = "application/octet-stream". |
||
req.data.mimeType = Ext2MimeTyes[ext] || "application/octet-stream"; | ||
} | ||
|
||
async function validateAttachment (req) { | ||
|
||
/* removing case condition for mediaType annotation as in our case binary value and metadata is stored in different database */ | ||
|
@@ -105,13 +104,7 @@ cds.once("served", async function registerPluginHandlers () { | |
attachment.content = await AttachmentsSrv.get(target, keys, req) //Dependency -> sending req object for usage in SDM plugin | ||
} | ||
|
||
async function nonDraftUpload(req, target) { | ||
if (req?.content?.url?.endsWith("/content")) { | ||
const attachmentID = req.content.url.match(attachmentIDRegex)[1]; | ||
AttachmentsSrv.nonDraftHandler(target, { ID: attachmentID, content: req.content }); | ||
} | ||
} | ||
}) | ||
}); | ||
|
||
function validateAttachmentSize (req) { | ||
const contentLengthHeader = req.headers["content-length"] | ||
|
@@ -128,6 +121,10 @@ function validateAttachmentSize (req) { | |
} | ||
} | ||
|
||
function isAttachmentAnnotated (target) { | ||
RoshniNaveenaS marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return !!target?.["@_is_media_data"] | ||
} | ||
|
||
module.exports = { validateAttachmentSize } | ||
|
||
const Ext2MimeTyes = { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not log credentials in any log output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This log was added just for debug options. I was having several problem with credentials checking, thought it would be useful. May be removed if you find insecure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll move this to a separate PR.