From 62cbde41deb06d026952f32a8664556dfda7fcda Mon Sep 17 00:00:00 2001 From: pzl Date: Wed, 25 Jan 2023 08:38:30 -0500 Subject: [PATCH 1/3] add openapi docs for File Upload routes --- model/openapi.yml | 188 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) diff --git a/model/openapi.yml b/model/openapi.yml index be9b49164..38fdf638f 100644 --- a/model/openapi.yml +++ b/model/openapi.yml @@ -475,6 +475,95 @@ components: type: array items: $ref: '#/components/schemas/ackResponseItem' + uploadBeginRequest: + title: "Upload Operation Start request body" + type: object + required: + - file + - action_id + - agent_id + - src + properties: + file: + type: object + properties: + Compression: + description: "The algorithm used to compress the file. Valid values: br,gzip,deflate,none" + type: string + example: deflate + hash: + title: Hash + description: Checksums on the file contents + type: object + properties: + sha256: + description: SHA256 of the contents + type: string + example: 04f81394bababa0fb31e6ad2d703c875eb46dc254527e39ff316564c0dc339e2 + name: + description: Name of the file including the extension, without the directory + type: string + example: yankees-stats.zip + mime_type: + description: MIME type of the file + type: string + example: application/zip + size: + description: Size of the file contents, in bytes + type: integer + example: 8276748 + required: + - name + - size + - mime_type + action_id: + description: ID of the action that requested this file + type: string + format: uuid + example: 2f440d31-2ea4-42f8-b0f2-4b6e98e8dc5e + agent_id: + description: Identifier of the agent uploading. Matches the ID usually found in agent.id + type: string + format: uuid + example: 9347e918-5e00-48b0-b302-a09f9258a46d + src: + description: The source integration sending this file + type: string + enum: + - endpoint + - agent + uploadBeginResponse: + description: Response to initiating a file upload + type: object + required: + - upload_id + - chunk_size + properties: + upload_id: + description: A unique identifier for the ensuing upload operation + type: string + format: uuid + example: fbc8e23c-055d-461e-87f7-b0d1b57f14b4 + chunk_size: + description: The required size (in bytes) that the file must be segmented into for each chunk + type: integer + example: 4194304 + uploadCompleteRequest: + description: Request to verify and finish an uploaded file + type: object + required: + - transithash + properties: + transithash: + description: the transithash (sha256 of the concatenation of each in-order chunk hash) of the entire file contents + type: object + required: + - sha256 + properties: + sha256: + description: SHA256 hash + type: string + example: 83810fdc61c44290778c212d7829d0c3f0232e81bd551d3943998a920025d14f parameters: requestId: name: X-Request-ID @@ -831,6 +920,8 @@ paths: security: - agentApiKey: [] requestBody: + required: true + description: Information about the file to be uploaded. Minimum required fields are marked as required. Additional fields may be specified and are allowed. For information about the file itself, ECS.file paths are recommended. For archived files, information about the archive should be placed in `file`. Information about the archive members may be placed in a `contents` array. content: application/json: schema: @@ -911,4 +1002,99 @@ paths: $ref: '#/components/responses/throttle' '503': $ref: '#/components/responses/unavailable' -# TODO: Include the file-upload endpoints? + /api/fleet/uploads: + post: + summary: Initiate a file upload process + description: "" + security: + - agentApiKey: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/uploadBeginRequest' + responses: + '200': + description: Information about the upload procedure + content: + application/json: + schema: + $ref: '#/components/schemas/uploadBeginResponse' + '400': + $ref: '#/components/responses/badRequest' + /api/fleet/uploads/{id}/{chunkNum}: + put: + summary: Upload a section of file data + description: "Upload portions of the intended file in a piecewise fashion. This route is idempotent in that any successive calls will overwrite previous ones for the same URL parameters. Chunks may be uploaded in any order, and may be uploaded in parallel. The body is the raw contents of the file at the given position matching the chunk number. The body must be the exact chunk size returned from the upload initiation response. All chunks must be this size except for the final one, which is naturally the file remainder." + security: + - agentApiKey: [] + parameters: + - name: id + in: path + description: The upload_id as returned in the Upload initiation response + required: true + schema: + type: string + format: uuid + example: ecb30383-6dd1-4b1d-bed0-2386b4e5df51 + - name: chunkNum + in: path + description: the positional index of the chunk within the file. The first chunk is 0, the next 1, etc. + required: true + schema: + type: integer + example: 3 + - name: X-Chunk-SHA2 + in: header + required: true + description: the SHA256 hash of the body contents for this request + schema: + type: string + example: 0c4a81b85a6b7ff00bde6c32e1e8be33b4b793b3b7b5cb03db93f77f7c9374d1 + requestBody: + description: The chunk contents as bytes + required: true + content: + "*/*": + schema: + type: string + format: binary + responses: + '200': + description: Successful chunk upload + '400': + $ref: '#/components/responses/badRequest' + /api/fleet/uploads/{id}: + post: + summary: Complete a file upload process + description: "" + security: + - agentApiKey: [] + requestBody: + required: true + contents: + application/json: + schema: + $ref: '#/components/schemas/uploadCompleteRequest' + parameters: + - name: id + in: path + description: The upload_id as returned in the Upload initiation response + required: true + schema: + type: string + format: uuid + example: ecb30383-6dd1-4b1d-bed0-2386b4e5df51 + responses: + '200': + description: success response + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: "ok" + '400': + $ref: '#/components/responses/badRequest' \ No newline at end of file From 628b83390e04edb0750701a0ff95ca5abbed633b Mon Sep 17 00:00:00 2001 From: pzl Date: Wed, 25 Jan 2023 08:42:41 -0500 Subject: [PATCH 2/3] quick fixes --- model/openapi.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model/openapi.yml b/model/openapi.yml index 38fdf638f..7536dac4d 100644 --- a/model/openapi.yml +++ b/model/openapi.yml @@ -1072,7 +1072,7 @@ paths: - agentApiKey: [] requestBody: required: true - contents: + content: application/json: schema: $ref: '#/components/schemas/uploadCompleteRequest' @@ -1097,4 +1097,4 @@ paths: type: string example: "ok" '400': - $ref: '#/components/responses/badRequest' \ No newline at end of file + $ref: '#/components/responses/badRequest' From cb877a47541ab4a5349acffaa31d936f481b2924 Mon Sep 17 00:00:00 2001 From: pzl Date: Wed, 25 Jan 2023 21:00:27 -0500 Subject: [PATCH 3/3] fixups --- model/openapi.yml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/model/openapi.yml b/model/openapi.yml index 7536dac4d..7576c7f43 100644 --- a/model/openapi.yml +++ b/model/openapi.yml @@ -511,6 +511,7 @@ components: size: description: Size of the file contents, in bytes type: integer + format: int64 example: 8276748 required: - name @@ -547,6 +548,7 @@ components: chunk_size: description: The required size (in bytes) that the file must be segmented into for each chunk type: integer + format: int64 example: 4194304 uploadCompleteRequest: description: Request to verify and finish an uploaded file @@ -920,8 +922,6 @@ paths: security: - agentApiKey: [] requestBody: - required: true - description: Information about the file to be uploaded. Minimum required fields are marked as required. Additional fields may be specified and are allowed. For information about the file itself, ECS.file paths are recommended. For archived files, information about the archive should be placed in `file`. Information about the archive members may be placed in a `contents` array. content: application/json: schema: @@ -1008,7 +1008,11 @@ paths: description: "" security: - agentApiKey: [] + parameters: + - $ref: '#/components/parameters/requestId' requestBody: + required: true + description: Information about the file to be uploaded. Minimum required fields are marked as required. Additional fields may be specified and are allowed. For information about the file itself, ECS.file paths are recommended. For archived files, information about the archive should be placed in `file`. Information about the archive members may be placed in a `contents` array. content: application/json: schema: @@ -1022,6 +1026,12 @@ paths: $ref: '#/components/schemas/uploadBeginResponse' '400': $ref: '#/components/responses/badRequest' + '401': + $ref: '#/components/responses/keyNotEnabled' + '408': + $ref: '#/components/responses/deadline' + '503': + $ref: '#/components/responses/unavailable' /api/fleet/uploads/{id}/{chunkNum}: put: summary: Upload a section of file data @@ -1051,6 +1061,7 @@ paths: schema: type: string example: 0c4a81b85a6b7ff00bde6c32e1e8be33b4b793b3b7b5cb03db93f77f7c9374d1 + - $ref: '#/components/parameters/requestId' requestBody: description: The chunk contents as bytes required: true @@ -1064,6 +1075,12 @@ paths: description: Successful chunk upload '400': $ref: '#/components/responses/badRequest' + '401': + $ref: '#/components/responses/keyNotEnabled' + '408': + $ref: '#/components/responses/deadline' + '503': + $ref: '#/components/responses/unavailable' /api/fleet/uploads/{id}: post: summary: Complete a file upload process @@ -1085,6 +1102,7 @@ paths: type: string format: uuid example: ecb30383-6dd1-4b1d-bed0-2386b4e5df51 + - $ref: '#/components/parameters/requestId' responses: '200': description: success response @@ -1098,3 +1116,9 @@ paths: example: "ok" '400': $ref: '#/components/responses/badRequest' + '401': + $ref: '#/components/responses/keyNotEnabled' + '408': + $ref: '#/components/responses/deadline' + '503': + $ref: '#/components/responses/unavailable'