-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch-cve-log4j.iscript.js
142 lines (122 loc) · 5.48 KB
/
patch-cve-log4j.iscript.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
var logger = require('logger');
var f5 = require('devmgr/f5');
var files = require('devmgr/files');
var device = require('devmgr/device');
// Name of the hosted content object containing the iRule.
var FILE_OBJECT_NAME = 'irule-apache-log4j.irule';
// Entrypoint for the script execution.
function execute(env) {
// Make sure the iRule file exists as hosted content object.
var meta = files.getMeta(FILE_OBJECT_NAME);
if (meta === null) {
logger.error('[patch-cve-log4j] invalid irule file');
return;
}
// This script expects a variable named "target" to be passed by the caller.
// The target can be either the name of the device or a tag, so that all
// devices having this tag will be patched at once.
var deviceList = device.resolveTag(env.target);
if (deviceList == null || deviceList.length === 0) {
deviceList = [env.target];
}
logger.notice('[patch-cve-log4j] devices list: ' + JSON.stringify(deviceList));
for (var i = 0; i < deviceList.length; i++) {
deployIrule(deviceList[i]);
}
}
// deployIrule takes name of a managed device and publishes the iRule on this
// device.
function deployIrule(device) {
logger.notice('[patch-cve-log4j] processing device ' + device);
// Validate argument.
if (!device) {
logger.error('[patch-cve-log4j] invalid device name');
return;
}
// Retrieve active F5 API client from the connection pool.
var deviceConn = new f5.Client(device);
if (!deviceConn) {
logger.error('[patch-cve-log4j] ' + device + ' is not a valid device');
return;
}
logger.notice('[patch-cve-log4j] connection to device ' + device + ' is OK');
// Get the list of all LTM VS from the source device.
var res = deviceConn.restCall('GET', '/mgmt/tm/ltm/rule?$select=fullPath,name');
if (res instanceof Error) {
logger.error('[patch-cve-log4j] List irule error => ' + res.message);
return;
}
// Create or update the content of the iRule on the BIG-IP device.
if (JSON.stringify(res).indexOf("irule-CVE-2021-44228") !== -1 ) {
var data = { apiAnonymous: files.readAsText(FILE_OBJECT_NAME) }
var res = deviceConn.restCall('PUT', '/mgmt/tm/ltm/rule/irule-CVE-2021-44228', data);
if (res instanceof Error) {
logger.error('[patch-cve-log4j] update irule error on device ' + device + ': ' + res.message);
return;
}
if (res.status !== 200) {
logger.error('[patch-cve-log4j] cannot create iRule on device ' + deviceName + ': [' + res.status + '] => ' + res.body);
return;
}
logger.notice('[patch-cve-log4j] irule updated on device ' + device);
} else {
var data = { name: 'irule-CVE-2021-44228', apiAnonymous: files.readAsText(FILE_OBJECT_NAME) };
var res = deviceConn.restCall('POST', '/mgmt/tm/ltm/rule', data);
if (res instanceof Error) {
logger.error('[patch-cve-log4j] create irule error => ' + res.message);
return;
}
if (res.status !== 200) {
logger.error('[patch-cve-log4j] cannot update iRule on device ' + deviceName + ': [' + res.status + '] => ' + res.body);
return;
}
logger.notice('[patch-cve-log4j] irule created on device ' + device);
}
// Retrieve the list of virtual servers on the BIG-IP.
var resp = deviceConn.restCall('GET', '/mgmt/tm/ltm/virtual');
if (resp.status !== 200) {
logger.error('[patch-cve-log4j] cannot fetch VS list on device ' + device + ': [' + resp.status + '] => ' + resp.body);
return;
}
var vsList = JSON.parse(resp.body);
// Create a new list of virtual server names containing only the virtual
// servers having a http profile attached to.
var vsNames = [];
for (var i = 0; i < vsList.items.length; i++) {
var vs = vsList.items[i];
if (vs.name === "telemetry_local") {
continue;
}
if (isHttpVirtualServer(deviceConn, device, vs.fullPath)) {
vsNames.push(vs.fullPath);
}
}
logger.notice('[patch-cve-log4j] virtual servers on device ' + device + ': ' + vsNames.join(', '));
// Attach the iRule to the virtual servers.
for (var i = 0; i < vsNames.length; i++) {
var vs = vsNames[i];
logger.notice('[patch-cve-log4j] virtual servers: ' + vs.split('/').join('~'));
var resp = deviceConn.restCall('PATCH', '/mgmt/tm/ltm/virtual/' + vs.replace(/\//g, '~') , '{"rules":["/Common/irule-CVE-2021-44228"]}');
if (resp.status !== 200) {
logger.error('[patch-cve-log4j] cannot PATCH irules VS list for ' + vs + ': [' + resp.status + '] => ' + resp.body);
return;
}
}
}
// isHttpVirtualServer reports whether the provider virtual server has an http
// profile attached to.
function isHttpVirtualServer(deviceConn, deviceName, fullPath) {
var resp = deviceConn.restCall('GET', '/mgmt/tm/ltm/virtual/' + fullPath.replace(/\//g, '~') + '/profiles');
if (resp.status !== 200) {
logger.error('[patch-cve-log4j] cannot fetch profiles list for ' + fullPath + ' on device ' + deviceName + ': [' + resp.status + '] => ' + resp.body);
return false;
}
var profiles = JSON.parse(resp.body);
for (var i = 0; i < profiles.items.length; i++) {
var profile = profiles.items[i];
if (profile.name.indexOf('http') !== -1) {
return true;
}
}
return false;
}