Added Last-Modified HTTP header for agent downloads, #3281

Ylian Saint-Hilaire committed Nov 18, 2021 at 18:43 UTC a95341b171d2352f0832a7252e046b5abd2c19a2
5 files changed +43 -56
agents/hashagents.bat
+1 -2
@@ -1,2 +1 @@
1 -MeshService-signed.exe hashagents.js > hashagents.json
2 -pause
\ No newline at end of file
1 +MeshService-signed.exe hashagents.js > hashagents.json
\ No newline at end of file
agents/hashagents.js
+3 -3
@@ -27,10 +27,10 @@ var agents = {
27 'meshagent_osx-universal-64': 10005
28 }
29
30 -var agentinfo = [];
30 +var agentinfo = {};
31 for (var i in agents) {
32 var info = getAgentInfo(i, agents[i]);
33 - if (info != null) { agentinfo.push(info); }
33 + if (info != null) { agentinfo[agents[i]] = info; }
34 }
35 console.log(JSON.stringify(agentinfo, null, 2));
36 process.exit();
@@ -38,5 +38,5 @@ process.exit();
38 function getAgentInfo(filename, id) {
39 if (fs.existsSync(filename) != true) return null;
40 var stats = fs.statSync(filename);
41 - return { id: id, filename: filename, hash: getSHA384FileHash(filename).toString('hex'), size: stats.size, mtime: stats.mtime };
41 + return { filename: filename, hash: getSHA384FileHash(filename).toString('hex'), size: stats.size, mtime: stats.mtime };
42 }
agents/hashagents.json
+29 -51
@@ -1,156 +1,134 @@
1 -[
2 - {
3 - "id": 3,
1 +{
2 + "3": {
3 "filename": "MeshService-signed.exe",
4 "hash": "2CDC48B46AB3580DF2B184CEA7A77F6DA61DC8B7F0A8D46076A3CB1AFB394D6302E7ACE9918B67754F48578C26967929",
5 "size": 3423040,
6 "mtime": "2021-08-30T21:06:32Z"
7 },
9 - {
10 - "id": 4,
8 + "4": {
9 "filename": "MeshService64-signed.exe",
10 "hash": "80645B8D669A2A74B9E53CE2A19CEAA73E0F7F45808B1EBDA4007A85740A64871F0CB8D6FEF12ED25F6352A3C9ED6468",
11 "size": 3037504,
12 "mtime": "2021-08-30T21:06:35Z"
13 },
16 - {
17 - "id": 5,
14 + "5": {
15 "filename": "meshagent_x86",
16 "hash": "AF99F40A4BBF394CB15E6196D2AC58B605DCE855297240687131CB91947DC2B35556C2F7E11D2BCB9B10D3D023006D29",
17 "size": 3592672,
18 "mtime": "2021-09-10T07:19:52Z"
19 },
23 - {
24 - "id": 6,
20 + "6": {
21 "filename": "meshagent_x86-64",
22 "hash": "9EF3E973A6363C13C5311699494F6C52574408805DFD848589B59000BDE3E8A414884BB8FCAA912689E051A57503E977",
23 "size": 3667280,
24 "mtime": "2021-09-10T07:20:01Z"
25 },
30 - {
31 - "id": 9,
32 - "filename": "meshagent_arm",
33 - "hash": "67191C284B94F8A491224128A7FCA46934D71AB40E85C3A711E93693D544BB42C9A29A936DAC70FD0FA3C6EA5444EB60",
34 - "size": 3082440,
35 - "mtime": "2021-09-10T07:20:18Z"
36 - },
37 - {
38 - "id": 7,
26 + "7": {
27 "filename": "meshagent_mips",
28 "hash": "CBF5734FA56F446B2638409520B05BA4F3FB0B21ECC7F4A449FD4E05F782C4D15E1B1B183C3D61E7B4F9957F42D4CDE5",
29 "size": 4459048,
30 "mtime": "2021-09-10T07:20:09Z"
31 },
44 - {
45 - "id": 13,
32 + "9": {
33 + "filename": "meshagent_arm",
34 + "hash": "67191C284B94F8A491224128A7FCA46934D71AB40E85C3A711E93693D544BB42C9A29A936DAC70FD0FA3C6EA5444EB60",
35 + "size": 3082440,
36 + "mtime": "2021-09-10T07:20:18Z"
37 + },
38 + "13": {
39 "filename": "meshagent_pogo",
40 "hash": "8149F61A680EB7F423D2238C464F3D4B129CC7D8BE535EA90AC85AA4953090980AC76A950EE0FBD733D7F56C04A85C0F",
41 "size": 3090672,
42 "mtime": "2021-09-10T07:20:28Z"
43 },
51 - {
52 - "id": 15,
44 + "15": {
45 "filename": "meshagent_poky",
46 "hash": "E105402B8E8FD16D0FF167F05B5A5D31AA00A59138BD59DA71FAC598CB1FD7DEF0DB678C890C4BCEED3D154D17D0D48C",
47 "size": 3722776,
48 "mtime": "2021-09-10T07:20:38Z"
49 },
58 - {
59 - "id": 16,
50 + "16": {
51 "filename": "meshagent_osx-x86-64",
52 "hash": "87A62A4A2973CED1ECAA0B9041C146C021ADF629654DAA88D3F91291423610155E02B6520F64F00D460EF2994B9AEE20",
53 "size": 4602880,
54 "mtime": "2021-08-30T22:13:56Z"
55 },
65 - {
66 - "id": 18,
56 + "18": {
57 "filename": "meshagent_poky64",
58 "hash": "DA5A4D60ECF4F9E8209B75A6DECFD0E441069992817AFAB35C2B7C15E23F1AC282112834C98C40F6E191C1AB1707CCC9",
59 "size": 3421528,
60 "mtime": "2021-09-10T07:20:49Z"
61 },
72 - {
73 - "id": 19,
62 + "19": {
63 "filename": "meshagent_x86_nokvm",
64 "hash": "C442B07E3B8AE297637F4CD8FAC0265E933B1CFBAB32CF853FA820D7A5C458D8F1EABA6357930063CCA1535431858F75",
65 "size": 3311940,
66 "mtime": "2021-09-10T07:20:58Z"
67 },
79 - {
80 - "id": 20,
68 + "20": {
69 "filename": "meshagent_x86-64_nokvm",
70 "hash": "D636882449476750999C1A74A302D97ECBD90E018F8D2708CA0AF64C6708A62D64A84AD6A543D50776DA888FC11AA5A0",
71 "size": 3372336,
72 "mtime": "2021-09-10T07:21:06Z"
73 },
86 - {
87 - "id": 24,
74 + "24": {
75 "filename": "meshagent_arm-linaro",
76 "hash": "68FEC6927EEDC000FC768A47685B9240D72A625F11A69DE2198AD125096DAA93699C2BDAC130A4C8E060946FBF64F910",
77 "size": 2149632,
78 "mtime": "2021-09-10T07:21:19Z"
79 },
93 - {
94 - "id": 25,
80 + "25": {
81 "filename": "meshagent_armhf",
82 "hash": "327956E768DCCF7B02DD1AE1E024169E2FCA1D7B605703CC8AE948E7FF94C8572BC561794C5667C0E51C3844DACFD4E1",
83 "size": 3109428,
84 "mtime": "2021-09-10T00:59:44Z"
85 },
100 - {
101 - "id": 27,
86 + "27": {
87 "filename": "meshagent_armhf2",
88 "hash": "0AE840520D3B677B9767EA097F3AA5A1E24212529E688200F43935DB1541AB9FB441EC2C7BA8002D45299B04695FD037",
89 "size": 2837724,
90 "mtime": "2021-08-30T21:10:03Z"
91 },
107 - {
108 - "id": 28,
92 + "28": {
93 "filename": "meshagent_mips24kc",
94 "hash": "E78A135132AD6E8C7CBAD0576FCC61FAE97D3AB0C29FCEFB704AA664B179AE296E2B562B84A7A0D717CB6C12A680289A",
95 "size": 4105420,
96 "mtime": "2021-08-30T22:02:32Z"
97 },
114 - {
115 - "id": 29,
98 + "29": {
99 "filename": "meshagent_osx-arm-64",
100 "hash": "6B65D0949B5505A61552AD14DA6F59A8B98E922186F0027925BC64979D2D84EF76169ABCFF08A67515AE7368F63D0C87",
101 "size": 3843944,
102 "mtime": "2021-08-30T22:13:56Z"
103 },
121 - {
122 - "id": 30,
104 + "30": {
105 "filename": "meshagent_freebsd_x86-64",
106 "hash": "D65C1F4180C03387F438F9051A7830C7F56DBFD618A951FB2142F7871AD998D5B61182FB693DDDDB2F31B3000D59E52D",
107 "size": 4599672,
108 "mtime": "2021-09-10T01:07:08Z"
109 },
128 - {
129 - "id": 32,
110 + "32": {
111 "filename": "meshagent_aarch64",
112 "hash": "49216370F497A7C0DA531FA2DFC478582865E7C547FD54E44E84BA12A271CD7AC529F7B7A8F2C8F531726E625631A941",
113 "size": 3170528,
114 "mtime": "2021-09-10T00:59:00Z"
115 },
135 - {
136 - "id": 40,
116 + "40": {
117 "filename": "meshagent_mipsel24kc",
118 "hash": "A94FE82E0265B1265B1C373722C448631035486E819132B037733BA205730DD71D8C8C16B1057B36B5569AEB4411ADB1",
119 "size": 4101068,
120 "mtime": "2021-08-30T22:03:12Z"
121 },
142 - {
143 - "id": 41,
122 + "41": {
123 "filename": "meshagent_aarch64-cortex-a53",
124 "hash": "B481A87A8EB803E09118B6F55B9344403926EA9324B3C669D2BA37014DDB79655678BC7D8D7843AD19FFADBB130D0203",
125 "size": 3002552,
126 "mtime": "2021-08-30T22:03:50Z"
127 },
149 - {
150 - "id": 10005,
128 + "10005": {
129 "filename": "meshagent_osx-universal-64",
130 "hash": "52EB0C2321108E57A113AB3115E0DE74EA4B07F4B7D80E4FB146DE275D63B1354869071AE7F56097B0D6271205B1FDAD",
131 "size": 8464232,
132 "mtime": "2021-08-30T22:13:56Z"
133 }
156 -]
134 +}
meshcentral.js
+5
@@ -2716,6 +2716,10 @@ function CreateMeshCentralServer(config, args) {
2716
2717 // Update the list of available mesh agents
2718 obj.updateMeshAgentsTable = function (func) {
2719 + // Load agent information file. This includes the data & time of the agent.
2720 + var agentInfo = [];
2721 + try { agentInfo = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'hashagents.json'), 'utf8')); } catch (ex) { }
2722 +
2723 var archcount = 0;
2724 for (var archid in obj.meshAgentsArchitectureNumbers) {
2725 var agentpath = obj.path.join(__dirname, 'agents', obj.meshAgentsArchitectureNumbers[archid].localname);
@@ -2730,6 +2734,7 @@ function CreateMeshCentralServer(config, args) {
2734 obj.meshAgentBinaries[archid].path = agentpath;
2735 obj.meshAgentBinaries[archid].url = 'http://' + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?id=' + archid;
2736 obj.meshAgentBinaries[archid].size = stats.size;
2737 + if ((agentInfo[archid] != null) && (agentInfo[archid].mtime != null)) { obj.meshAgentBinaries[archid].mtime = new Date(agentInfo[archid].mtime); } // Set agent time if available
2738
2739 // If this is a windows binary, pull binary information
2740 if (obj.meshAgentsArchitectureNumbers[archid].platform == 'win32') {
webserver.js
+5
@@ -4770,6 +4770,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4770 if ((domain.agentcustomization != null) && (typeof domain.agentcustomization.filename == 'string')) { meshagentFilename = domain.agentcustomization.filename; }
4771
4772 setContentDispositionHeader(res, 'application/octet-stream', meshagentFilename, null, 'meshagent');
4773 + if (argentInfo.mtime != null) { res.setHeader('Last-Modified', argentInfo.mtime.toUTCString()); }
4774 res.statusCode = 200;
4775 obj.parent.exeHandler.streamExeWithJavaScript({ platform: argentInfo.platform, sourceFileName: argentInfo.path, destinationStream: res, js: Buffer.from(js, 'utf8'), peinfo: argentInfo.pe });
4776 } else if (req.query.id != null) {
@@ -4785,11 +4786,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4786 if ((user != null) && ((user.siteadmin == 0xFFFFFFFF) || ((Array.isArray(obj.parent.config.settings.agentcoredumpusers)) && (obj.parent.config.settings.agentcoredumpusers.indexOf(user._id) >= 0)))) {
4787 if (argentInfo.id == 3) {
4788 setContentDispositionHeader(res, 'application/octet-stream', 'MeshService.pdb', null, 'MeshService.pdb');
4789 + if (argentInfo.mtime != null) { res.setHeader('Last-Modified', argentInfo.mtime.toUTCString()); }
4790 try { res.sendFile(argentInfo.path.split('MeshService-signed.exe').join('MeshService.pdb')); } catch (ex) { }
4791 return;
4792 }
4793 if (argentInfo.id == 4) {
4794 setContentDispositionHeader(res, 'application/octet-stream', 'MeshService64.pdb', null, 'MeshService64.pdb');
4795 + if (argentInfo.mtime != null) { res.setHeader('Last-Modified', argentInfo.mtime.toUTCString()); }
4796 try { res.sendFile(argentInfo.path.split('MeshService64-signed.exe').join('MeshService64.pdb')); } catch (ex) { }
4797 return;
4798 }
@@ -4802,6 +4805,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4805 // Get the agent filename
4806 var meshagentFilename = argentInfo.rname;
4807 if ((domain.agentcustomization != null) && (typeof domain.agentcustomization.filename == 'string')) { meshagentFilename = domain.agentcustomization.filename; }
4808 + if (argentInfo.mtime != null) { res.setHeader('Last-Modified', argentInfo.mtime.toUTCString()); }
4809 if (req.query.zip == 1) { if (argentInfo.zdata != null) { setContentDispositionHeader(res, 'application/octet-stream', meshagentFilename + '.zip', null, 'meshagent.zip'); res.send(argentInfo.zdata); } else { try { res.sendStatus(404); } catch (ex) { } } return; } // Send compressed agent
4810 setContentDispositionHeader(res, 'application/octet-stream', meshagentFilename, null, 'meshagent');
4811 if (argentInfo.data == null) { res.sendFile(argentInfo.path); } else { res.send(argentInfo.data); }
@@ -4883,6 +4887,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4887 if (parent.agentTranslations != null) { meshsettings += 'translation=' + parent.agentTranslations + '\r\n'; } // Translation strings, not for MeshCentral Assistant
4888 }
4889 setContentDispositionHeader(res, 'application/octet-stream', meshfilename, null, argentInfo.rname);
4890 + if (argentInfo.mtime != null) { res.setHeader('Last-Modified', argentInfo.mtime.toUTCString()); }
4891 obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe });
4892 return;
4893 }