zabbix_export: version: '6.0' date: '2024-08-12T08:52:07Z' groups: - uuid: a571c0d144b14fd4a87a9d9b2aa9fcd6 name: Templates/Applications - uuid: c2c162144c2d4c5491c8801193af4945 name: Templates/Cloud - uuid: 748ad4d098d447d492bb935c907f652f name: Templates/Databases - uuid: 137f19e6e2dc4219b33553b812627bc2 name: 'Virtual machines' templates: - uuid: c60e5929ab474f67bbe67dc6b04e709d template: 'AWS by HTTP' name: 'AWS by HTTP' description: | Get AWS EC2, RDS and S3 instances, AWS ECS clusters, AWS Elastic Load Balancing. Don't forget to read the README.md for the correct setup of the template. You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback Generated by official Zabbix template tool "Templator" groups: - name: Templates/Cloud discovery_rules: - uuid: c651911bad9244ad9c8d2dad5b0d70e4 name: 'EC2 instances discovery' type: SCRIPT key: aws.ec2.discovery delay: 12h params: | var AWS = { params: {}, metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials', getField: function (data, path) { var steps = path.split('.'); for (var i = 0; i < steps.length; i++) { var step = steps[i]; if (typeof data !== 'object' || typeof data[step] === 'undefined') { throw 'Required field was not found: ' + path; } data = data[step]; } return data; }, setParams: function (params) { AWS.params['proxy'] = params.proxy; switch (AWS.getField(params, 'auth_type')) { case 'role_base': AWS.params['auth_type'] = 'role_base'; var request = new HttpRequest(); if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } var IamRoleName = request.get(AWS.metadata); if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') { throw 'Error getting security credentials from instance metadata. Role not found.'; } credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName)); if (request.getStatus() !== 200 || credentials === null || credentials === '') { throw 'Error getting security credentials from instance metadata.'; } try { credentials = JSON.parse(credentials); } catch (error) { throw 'Failed to parse response received from instance metadata. Check debug log for more information.'; } ['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; case 'assume_role': AWS.params['auth_type'] = 'assume_role'; ['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); role_arn_regex = /role\/(.+)$/; var payload = { 'Action': 'AssumeRole', 'Version': '2011-06-15', 'RoleArn': AWS.params.role_arn, 'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[1] + 'Session', }; credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials'); ['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; default: AWS.params['auth_type'] = 'access_key'; ['AccessKeyId', 'SecretAccessKey'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); } ['describe_region', 'region_match', 'region_not_match'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); }, sign: function (key, message) { var hex = hmac('sha256', key, message); if ((hex.length % 2) === 1) { throw 'Invalid length of a hex string!'; } var result = new Int8Array(hex.length / 2); for (var i = 0, b = 0; i < hex.length; i += 2, b++) { result[b] = parseInt(hex.substring(i, i + 2), 16); } return result; }, prepareParams: function (params) { var result = []; Object.keys(params).sort().forEach(function (key) { if (typeof params[key] !== 'object') { result.push(key + '=' + encodeURIComponent(params[key])); } else { result.push(prepareObject(key, params[key])); } }); return result.join('&'); }, request: function (method, region, service, params, data) { if (typeof data === 'undefined' || data === null) { data = ''; } var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''), date = amzdate.replace(/T\d+Z/, ''), canonical_uri = '/', host = service + '.' + region + '.amazonaws.com', canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n', signed_headers = 'content-encoding;host;x-amz-date', canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data), credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request', request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request), key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date), key = AWS.sign(key, region), key = AWS.sign(key, service), key = AWS.sign(key, 'aws4_request'), request = new HttpRequest(), url = 'https://' + host + canonical_uri + '?' + params; if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } request.addHeader('x-amz-date: ' + amzdate); request.addHeader('x-amz-content-sha256:' + sha256(data)); request.addHeader('Accept: application/json'); request.addHeader('Content-Type: application/json'); request.addHeader('Content-Encoding: amz-1.0'); request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string)); if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken)); } Zabbix.log(4, '[ AWS EC2 ] Sending request: ' + url); response = request.get(url); Zabbix.log(4, '[ AWS EC2 ] Received response with status code ' + request.getStatus() + ': ' + response); if (request.getStatus() !== 200) { throw 'Request failed with status code ' + request.getStatus() + ': ' + response; } try { response = JSON.parse(response); } catch (error) { try { response = JSON.parse(XML.toJson(response)); } catch (error) { throw 'Failed to parse response received from AWS API. Check debug log for more information.'; } } return response; }, tagToNameInstances: function (instance) { try { var tags = AWS.getField(instance, 'tagSet.item'), instanceName = AWS.getField(instance, 'instanceId'); if (!Array.isArray(tags)) tags = [tags] tags.forEach( function (tag) { if (String(AWS.getField(tag, 'key')) === 'Name') { instanceName = AWS.getField(tag, 'value'); } } ); return instanceName; } catch (error) { return AWS.getField(instance, 'instanceId'); } }, listRegions: function () { var payload = { 'Action': 'DescribeRegions', 'Version': '2016-11-15' }; regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item'); if (!Array.isArray(regions)) regions = [regions] return regions }, listInstances: function () { var lld_array = [], regions = AWS.listRegions(), payload = { 'Action': 'DescribeInstances', 'Version': '2016-11-15' }; regions.forEach(function (region) { var region_name = AWS.getField(region, 'regionName'); if (region_name.match(AWS.params.region_match) === null || region_name.match(AWS.params.region_not_match) !== null) return; result = AWS.request('GET', region_name, 'ec2', AWS.prepareParams(payload), ''); if (typeof result !== 'object' || typeof result.DescribeInstancesResponse !== 'object' || typeof result.DescribeInstancesResponse.reservationSet !== 'object') { throw 'Cannot get EC2 instance list from AWS API. Check debug log for more information.'; } if (result.DescribeInstancesResponse.reservationSet === null) return []; if (typeof result.DescribeInstancesResponse.reservationSet.item !== 'object') throw 'Cannot get EC2 instance list from AWS API. Check debug log for more information.'; var reservation = result.DescribeInstancesResponse.reservationSet.item if (!Array.isArray(reservation)) reservation = [reservation] reservation.forEach(function (res_item) { var instances = AWS.getField(res_item, 'instancesSet.item') if (!Array.isArray(instances)) instances = [instances] instances.forEach(function (instance) { if (AWS.getField(instance, 'instanceState.name') === 'terminated') return; lld_array.push( { instanceId: AWS.getField(instance, 'instanceId'), instanceName: AWS.tagToNameInstances(instance), instanceRegion: region_name } ) }); }); }); return lld_array; } }; try { AWS.setParams(JSON.parse(value)); return JSON.stringify(AWS.listInstances()); } catch (error) { error += (String(error).endsWith('.')) ? '' : '.'; Zabbix.log(3, '[ AWS EC2 ] ERROR: ' + error); return JSON.stringify({ 'error': error }); } filter: evaltype: AND conditions: - macro: '{#AWS.EC2.INSTANCE.NAME}' value: '{$AWS.EC2.LLD.FILTER.NAME.MATCHES}' formulaid: A - macro: '{#AWS.EC2.INSTANCE.NAME}' value: '{$AWS.EC2.LLD.FILTER.NAME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: B - macro: '{#AWS.EC2.INSTANCE.REGION}' value: '{$AWS.EC2.LLD.FILTER.REGION.MATCHES}' formulaid: C - macro: '{#AWS.EC2.INSTANCE.REGION}' value: '{$AWS.EC2.LLD.FILTER.REGION.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: D description: 'Get EC2 instances.' host_prototypes: - uuid: c4c830c727294b07926c39b00cf19046 host: '{#AWS.EC2.INSTANCE.ID}' name: '{#AWS.EC2.INSTANCE.NAME}' group_links: - group: name: 'Virtual machines' templates: - name: 'AWS EC2 by HTTP' macros: - macro: '{$AWS.EC2.INSTANCE.ID}' value: '{#AWS.EC2.INSTANCE.ID}' description: 'EC2 instance ID.' - macro: '{$AWS.REGION}' value: '{#AWS.EC2.INSTANCE.REGION}' description: 'Amazon EC2 Region code.' tags: - tag: name value: '{#AWS.EC2.INSTANCE.NAME}' - tag: region value: '{#AWS.EC2.INSTANCE.REGION}' - tag: service value: ec2 custom_interfaces: 'YES' interfaces: - ip: '{#AWS.EC2.INSTANCE.ID}' timeout: '{$AWS.DATA.TIMEOUT}' parameters: - name: AccessKeyId value: '{$AWS.ACCESS.KEY.ID}' - name: auth_type value: '{$AWS.AUTH_TYPE}' - name: describe_region value: '{$AWS.DESCRIBE.REGION}' - name: proxy value: '{$AWS.PROXY}' - name: region_match value: '{$AWS.EC2.LLD.FILTER.REGION.MATCHES}' - name: region_not_match value: '{$AWS.EC2.LLD.FILTER.REGION.NOT_MATCHES}' - name: role_arn value: '{$AWS.ASSUME.ROLE.ARN}' - name: SecretAccessKey value: '{$AWS.SECRET.ACCESS.KEY}' - name: sts_region value: '{$AWS.STS.REGION}' lld_macro_paths: - lld_macro: '{#AWS.EC2.INSTANCE.ID}' path: $.instanceId - lld_macro: '{#AWS.EC2.INSTANCE.NAME}' path: $.instanceName - lld_macro: '{#AWS.EC2.INSTANCE.REGION}' path: $.instanceRegion - uuid: 44b68894d68c45ec9a5ea787c975ae16 name: 'ECS clusters discovery' type: SCRIPT key: aws.ecs.discovery delay: 12h params: | var AWS = { params: {}, metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials', setParams: function (params) { AWS.params['proxy'] = params.proxy; switch (AWS.getField(params, 'auth_type')) { case 'role_base': AWS.params['auth_type'] = 'role_base'; var request = new HttpRequest(); if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } var IamRoleName = request.get(AWS.metadata); if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') { throw 'Error getting security credentials from instance metadata. Role not found.'; } credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName)); if (request.getStatus() !== 200 || credentials === null || credentials === '') { throw 'Error getting security credentials from instance metadata.'; } try { credentials = JSON.parse(credentials); } catch (error) { throw 'Failed to parse response received from instance metadata. Check debug log for more information.'; } ['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; case 'assume_role': AWS.params['auth_type'] = 'assume_role'; ['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); role_arn_regex = /role\/(.+)$/; var payload = { 'Action': 'AssumeRole', 'Version': '2011-06-15', 'RoleArn': AWS.params.role_arn, 'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[1] + 'Session', }; credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials'); ['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; default: AWS.params['auth_type'] = 'access_key'; ['AccessKeyId', 'SecretAccessKey'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); } ['describe_region', 'region_match', 'region_not_match'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); }, getField: function (data, path) { var steps = path.split('.'); for (var i = 0; i < steps.length; i++) { var step = steps[i]; if (typeof data !== 'object' || typeof data[step] === 'undefined') { throw 'Required field was not found: ' + path; } data = data[step]; } return data; }, sign: function (key, message) { var hex = hmac('sha256', key, message); if ((hex.length % 2) === 1) { throw 'Invalid length of a hex string!'; } var result = new Int8Array(hex.length / 2); for (var i = 0, b = 0; i < hex.length; i += 2, b++) { result[b] = parseInt(hex.substring(i, i + 2), 16); } return result; }, prepareParams: function (params) { var result = []; Object.keys(params).sort().forEach(function (key) { if (typeof params[key] !== 'object') { result.push(key + '=' + encodeURIComponent(params[key])); } else { result.push(prepareObject(key, params[key])); } }); return result.join('&'); }, request: function (method, region, service, params, data) { if (typeof data === 'undefined' || data === null) { data = ''; } var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''), date = amzdate.replace(/T\d+Z/, ''), canonical_uri = '/', host = service + '.' + region + '.amazonaws.com', canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n', signed_headers = 'content-encoding;host;x-amz-date', canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data), credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request', request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request), key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date), key = AWS.sign(key, region), key = AWS.sign(key, service), key = AWS.sign(key, 'aws4_request'), request = new HttpRequest(), url = 'https://' + host + canonical_uri + '?' + params; if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } request.addHeader('x-amz-date: ' + amzdate); request.addHeader('x-amz-content-sha256:' + sha256(data)); request.addHeader('Accept: application/json'); request.addHeader('Content-Type: application/x-www-form-urlencoded'); request.addHeader('Content-Encoding: amz-1.0'); request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string)); if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken)); } Zabbix.log(4, '[ AWS ECS ] Sending request: ' + url); response = request.get(url); Zabbix.log(4, '[ AWS ECS ] Received response with status code ' + request.getStatus() + ': ' + response); if (request.getStatus() !== 200) { throw 'Request failed with status code ' + request.getStatus() + ': ' + response; } try { response = JSON.parse(response); } catch (error) { try { response = JSON.parse(XML.toJson(response)); } catch (error) { throw 'Failed to parse response received from AWS API. Check debug log for more information.'; } } return response; }, listRegions: function () { var payload = { 'Action': 'DescribeRegions', 'Version': '2016-11-15' }; regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item'); if (!Array.isArray(regions)) regions = [regions] return regions }, listClusters: function () { var data = [], regions = AWS.listRegions(), result, ECSClusters, payload = { 'Action': 'ListClusters', 'Version': '2014-11-13' }; regions.forEach(function (region) { var region_name = AWS.getField(region, 'regionName'); if (region_name.match(AWS.params.region_match) === null || region_name.match(AWS.params.region_not_match) !== null) return; result = AWS.request('GET', region_name, 'ecs', AWS.prepareParams(payload)); ECSClusters = AWS.getField(result, 'ListClustersResponse.ListClustersResult.clusterArns') for (k in ECSClusters) { clusters = ECSClusters[k]; json = {}; input = clusters.split('/'); for (var i = 1; i < input.length; i += 2) { json[input[i]] = input[i + 1]; } data.push({ 'clusters_name': input[1], 'region': region_name }); } }); return data; }, decribeClusters: function (cluster_name, region_name) { var payload = { 'Action': 'DescribeClusters', 'Version': '2014-11-13', 'clusters.clusterName': cluster_name, 'include.statistics': 'STATISTICS' }; result = AWS.request('GET', region_name, 'ecs', AWS.prepareParams(payload)); return result; } }; try { AWS.setParams(JSON.parse(value)); var clusters = AWS.listClusters(), infrastructure = [], metrics = ['runningEC2TasksCount', 'pendingEC2TasksCount', 'activeEC2ServiceCount', 'drainingEC2ServiceCount'], ECSClusters = [], DescribeClusters = []; DescribeClusters = clusters.map(function (cluster) { ECSClusters = AWS.getField(AWS.decribeClusters(cluster.clusters_name, cluster.region), 'DescribeClustersResponse.DescribeClustersResult.clusters') for (k in ECSClusters) { var ECS2 = 0; statistic = AWS.getField(ECSClusters[k], 'statistics'); statistic.forEach(function (id) { for (i in metrics) { if (AWS.getField(id, 'name') === metrics[i]) { ECS2 += Number(AWS.getField(id, 'value')); } } }) infrastructure = (ECS2 > 0) ? 'use_ecs2' : 'serverless'; return { 'clusterName': ECSClusters[k].clusterName, 'status': ECSClusters[k].status, 'infrastructure': infrastructure, 'region': cluster.region } } }) return JSON.stringify(DescribeClusters); } catch (error) { error += (String(error).endsWith('.')) ? '' : '.'; Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error); return JSON.stringify({ 'error': error }); } filter: evaltype: AND conditions: - macro: '{#AWS.ECS.CLUSTER.NAME}' value: '{$AWS.ECS.LLD.FILTER.NAME.MATCHES}' formulaid: A - macro: '{#AWS.ECS.CLUSTER.NAME}' value: '{$AWS.ECS.LLD.FILTER.NAME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: B - macro: '{#AWS.ECS.CLUSTER.REGION}' value: '{$AWS.ECS.LLD.FILTER.REGION.MATCHES}' formulaid: C - macro: '{#AWS.ECS.CLUSTER.REGION}' value: '{$AWS.ECS.LLD.FILTER.REGION.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: D - macro: '{#AWS.ECS.CLUSTER.STATUS}' value: '{$AWS.ECS.LLD.FILTER.STATUS.MATCHES}' formulaid: E - macro: '{#AWS.ECS.CLUSTER.STATUS}' value: '{$AWS.ECS.LLD.FILTER.STATUS.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: F description: 'Get ECS clusters.' host_prototypes: - uuid: 71072e5a149e45b293946866f8220c07 host: '{#AWS.ECS.CLUSTER.NAME}' name: '{#AWS.ECS.CLUSTER.NAME}' group_links: - group: name: Templates/Cloud macros: - macro: '{$AWS.ECS.CLUSTER.NAME}' value: '{#AWS.ECS.CLUSTER.NAME}' description: 'ECS cluster name.' - macro: '{$AWS.REGION}' value: '{#AWS.ECS.CLUSTER.REGION}' description: 'ECS cluster region.' tags: - tag: name value: '{#AWS.ECS.CLUSTER.NAME}' - tag: region value: '{#AWS.ECS.CLUSTER.REGION}' - tag: service value: ecs timeout: '{$AWS.DATA.TIMEOUT}' parameters: - name: AccessKeyId value: '{$AWS.ACCESS.KEY.ID}' - name: auth_type value: '{$AWS.AUTH_TYPE}' - name: describe_region value: '{$AWS.DESCRIBE.REGION}' - name: proxy value: '{$AWS.PROXY}' - name: region_match value: '{$AWS.ECS.LLD.FILTER.REGION.MATCHES}' - name: region_not_match value: '{$AWS.ECS.LLD.FILTER.REGION.NOT_MATCHES}' - name: role_arn value: '{$AWS.ASSUME.ROLE.ARN}' - name: SecretAccessKey value: '{$AWS.SECRET.ACCESS.KEY}' - name: sts_region value: '{$AWS.STS.REGION}' lld_macro_paths: - lld_macro: '{#AWS.ECS.CLUSTER.INFRASTRUCTURE}' path: $.infrastructure - lld_macro: '{#AWS.ECS.CLUSTER.NAME}' path: $.clusterName - lld_macro: '{#AWS.ECS.CLUSTER.REGION}' path: $.region - lld_macro: '{#AWS.ECS.CLUSTER.STATUS}' path: $.status overrides: - name: Serverless step: '1' filter: conditions: - macro: '{#AWS.ECS.CLUSTER.INFRASTRUCTURE}' value: ^serverless$ formulaid: A operations: - operationobject: HOST_PROTOTYPE operator: REGEXP templates: - name: 'AWS ECS Serverless Cluster by HTTP' - name: 'Use EC2 Infrastructure' step: '2' filter: conditions: - macro: '{#AWS.ECS.CLUSTER.INFRASTRUCTURE}' value: ^use_ecs2$ formulaid: A operations: - operationobject: HOST_PROTOTYPE operator: REGEXP templates: - name: 'AWS ECS Cluster by HTTP' - uuid: e7ac860c53bf403f9aee8cdd4b099c05 name: 'ELB load balancers discovery' type: SCRIPT key: aws.elb.discovery delay: 12h params: | var AWS = { params: {}, metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials', getField: function (data, path) { var steps = path.split('.'); for (var i = 0; i < steps.length; i++) { var step = steps[i]; if (typeof data !== 'object' || typeof data[step] === 'undefined') { throw 'Required field was not found: ' + path; } data = data[step]; } return data; }, setParams: function (params) { AWS.params['proxy'] = params.proxy; switch (AWS.getField(params, 'auth_type')) { case 'role_base': AWS.params['auth_type'] = 'role_base'; var request = new HttpRequest(); if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } var IamRoleName = request.get(AWS.metadata); if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') { throw 'Error getting security credentials from instance metadata. Role not found.'; } credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName)); if (request.getStatus() !== 200 || credentials === null || credentials === '') { throw 'Error getting security credentials from instance metadata.'; } try { credentials = JSON.parse(credentials); } catch (error) { throw 'Failed to parse response received from instance metadata. Check debug log for more information.'; } ['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; case 'assume_role': AWS.params['auth_type'] = 'assume_role'; ['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); role_arn_regex = /role\/(.+)$/; var payload = { 'Action': 'AssumeRole', 'Version': '2011-06-15', 'RoleArn': AWS.params.role_arn, 'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[1] + 'Session', }; credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials'); ['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; default: AWS.params['auth_type'] = 'access_key'; ['AccessKeyId', 'SecretAccessKey'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); } ['describe_region', 'region_match', 'region_not_match'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); }, sign: function (key, message) { var hex = hmac('sha256', key, message); if ((hex.length % 2) === 1) { throw 'Invalid length of a hex string!'; } var result = new Int8Array(hex.length / 2); for (var i = 0, b = 0; i < hex.length; i += 2, b++) { result[b] = parseInt(hex.substring(i, i + 2), 16); } return result; }, prepareParams: function (params) { var result = []; Object.keys(params).sort().forEach(function (key) { if (typeof params[key] !== 'object') { result.push(key + '=' + encodeURIComponent(params[key])); } else { result.push(prepareObject(key, params[key])); } }); return result.join('&'); }, request: function (method, region, service, params, data) { if (typeof data === 'undefined' || data === null) { data = ''; } var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''), date = amzdate.replace(/T\d+Z/, ''), canonical_uri = '/', host = service + '.' + region + '.amazonaws.com', canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n', signed_headers = 'content-encoding;host;x-amz-date', canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data), credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request', request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request), key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date), key = AWS.sign(key, region), key = AWS.sign(key, service), key = AWS.sign(key, 'aws4_request'), request = new HttpRequest(), url = 'https://' + host + canonical_uri + '?' + params; if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } request.addHeader('x-amz-date: ' + amzdate); request.addHeader('x-amz-content-sha256:' + sha256(data)); request.addHeader('Accept: application/json'); request.addHeader('Content-Type: application/json'); request.addHeader('Content-Encoding: amz-1.0'); request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string)); if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken)); } Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url); response = request.get(url); Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response); if (request.getStatus() !== 200) { throw 'Request failed with status code ' + request.getStatus() + ': ' + response; } try { response = JSON.parse(response); } catch (error) { try { response = JSON.parse(XML.toJson(response)); } catch (error) { throw 'Failed to parse response received from AWS API. Check debug log for more information.'; } } return response; }, listRegions: function () { var payload = { 'Action': 'DescribeRegions', 'Version': '2016-11-15' }; regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item'); if (!Array.isArray(regions)) regions = [regions] return regions }, listLoadBalancers: function () { var lld_array = [], regions = AWS.listRegions(), payload = { 'Action': 'DescribeLoadBalancers', 'Version': '2015-12-01' }; regions.forEach(function (region) { var region_name = AWS.getField(region, 'regionName'); if (region_name.match(AWS.params.region_match) === null || region_name.match(AWS.params.region_not_match) !== null) return; elb = AWS.getField(AWS.request('GET', region_name, 'elasticloadbalancing', AWS.prepareParams(payload)), 'DescribeLoadBalancersResponse.DescribeLoadBalancersResult.LoadBalancers'); if (!Array.isArray(elb)) elb = [elb] elb.forEach(function (elb) { lld_array.push( { name: AWS.getField(elb, 'LoadBalancerName'), arn: AWS.getField(elb, 'LoadBalancerArn'), type: AWS.getField(elb, 'Type'), state: AWS.getField(elb, 'State.Code'), dns_name: AWS.getField(elb, 'DNSName'), region: region_name } ) }); }); return lld_array; } }; try { AWS.setParams(JSON.parse(value)); return JSON.stringify(AWS.listLoadBalancers()); } catch (error) { error += (String(error).endsWith('.')) ? '' : '.'; Zabbix.log(3, '[ AWS ELB ] ERROR: ' + error); return JSON.stringify({ 'error': error }); } filter: evaltype: AND conditions: - macro: '{#AWS.ELB.NAME}' value: '{$AWS.ELB.LLD.FILTER.NAME.MATCHES}' formulaid: A - macro: '{#AWS.ELB.NAME}' value: '{$AWS.ELB.LLD.FILTER.NAME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: B - macro: '{#AWS.ELB.REGION}' value: '{$AWS.ELB.LLD.FILTER.REGION.MATCHES}' formulaid: C - macro: '{#AWS.ELB.REGION}' value: '{$AWS.ELB.LLD.FILTER.REGION.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: D - macro: '{#AWS.ELB.STATE}' value: '{$AWS.ELB.LLD.FILTER.STATE.MATCHES}' formulaid: E - macro: '{#AWS.ELB.STATE}' value: '{$AWS.ELB.LLD.FILTER.STATE.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: F description: 'Get ELB load balancers.' host_prototypes: - uuid: 2c31bc79209e41978f76315406339769 host: '{#AWS.ELB.NAME}' name: '{#AWS.ELB.NAME}' group_links: - group: name: Templates/Cloud macros: - macro: '{$AWS.ELB.ARN}' value: '{#AWS.ELB.ARN}' description: 'The Amazon Resource Names (ARN) of the load balancers.' - macro: '{$AWS.ELB.NAME}' value: '{#AWS.ELB.NAME}' description: 'ELB load balancer name.' - macro: '{$AWS.REGION}' value: '{#AWS.ELB.REGION}' description: 'ELB load balancer region.' tags: - tag: dns-name value: '{#AWS.ELB.DNS.NAME}' - tag: name value: '{#AWS.ELB.NAME}' - tag: region value: '{#AWS.ELB.REGION}' - tag: service value: elb - tag: type value: '{#AWS.ELB.TYPE}' timeout: '{$AWS.DATA.TIMEOUT}' parameters: - name: AccessKeyId value: '{$AWS.ACCESS.KEY.ID}' - name: auth_type value: '{$AWS.AUTH_TYPE}' - name: describe_region value: '{$AWS.DESCRIBE.REGION}' - name: proxy value: '{$AWS.PROXY}' - name: region_match value: '{$AWS.ELB.LLD.FILTER.REGION.MATCHES}' - name: region_not_match value: '{$AWS.ELB.LLD.FILTER.REGION.NOT_MATCHES}' - name: role_arn value: '{$AWS.ASSUME.ROLE.ARN}' - name: SecretAccessKey value: '{$AWS.SECRET.ACCESS.KEY}' - name: sts_region value: '{$AWS.STS.REGION}' lld_macro_paths: - lld_macro: '{#AWS.ELB.ARN}' path: $.arn - lld_macro: '{#AWS.ELB.DNS.NAME}' path: $.dns_name - lld_macro: '{#AWS.ELB.NAME}' path: $.name - lld_macro: '{#AWS.ELB.REGION}' path: $.region - lld_macro: '{#AWS.ELB.STATE}' path: $.state - lld_macro: '{#AWS.ELB.TYPE}' path: $.type overrides: - name: 'Application Load Balancers' step: '1' filter: conditions: - macro: '{#AWS.ELB.TYPE}' value: ^application$ formulaid: A operations: - operationobject: HOST_PROTOTYPE operator: REGEXP templates: - name: 'AWS ELB Application Load Balancer by HTTP' - name: 'Network Load Balancers' step: '2' filter: conditions: - macro: '{#AWS.ELB.TYPE}' value: ^network$ formulaid: A operations: - operationobject: HOST_PROTOTYPE operator: REGEXP templates: - name: 'AWS ELB Network Load Balancer by HTTP' - uuid: 691d96408dbc4c5c9235932cdbe70648 name: 'Lambda discovery' type: SCRIPT key: aws.lambda.discovery delay: 12h params: | var AWS = { params: {}, metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials', getField: function (data, path) { var steps = path.split('.'); for (var i = 0; i < steps.length; i++) { var step = steps[i]; if (typeof data !== 'object' || typeof data[step] === 'undefined') { throw 'Required field was not found: ' + path; } data = data[step]; } return data; }, setParams: function (params) { AWS.params['proxy'] = params.proxy; switch (AWS.getField(params, 'auth_type')) { case 'role_base': AWS.params['auth_type'] = 'role_base'; var request = new HttpRequest(); if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } var IamRoleName = request.get(AWS.metadata); if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') { throw 'Error getting security credentials from instance metadata. Role not found.'; } credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName)); if (request.getStatus() !== 200 || credentials === null || credentials === '') { throw 'Error getting security credentials from instance metadata.'; } try { credentials = JSON.parse(credentials); } catch (error) { throw 'Failed to parse response received from instance metadata. Check debug log for more information.'; } ['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; case 'assume_role': AWS.params['auth_type'] = 'assume_role'; ['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); role_arn_regex = /role\/(.+)$/; var payload = { 'Action': 'AssumeRole', 'Version': '2011-06-15', 'RoleArn': AWS.params.role_arn, 'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[1] + 'Session', }; credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), '', ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials'); ['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; default: AWS.params['auth_type'] = 'access_key'; ['AccessKeyId', 'SecretAccessKey'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); } ['describe_region', 'region_match', 'region_not_match'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); }, sign: function (key, message) { var hex = hmac('sha256', key, message); if ((hex.length % 2) === 1) { throw 'Invalid length of a hex string!'; } var result = new Int8Array(hex.length / 2); for (var i = 0, b = 0; i < hex.length; i += 2, b++) { result[b] = parseInt(hex.substring(i, i + 2), 16); } return result; }, prepareParams: function (params) { var result = []; Object.keys(params).sort().forEach(function (key) { if (typeof params[key] !== 'object') { result.push(key + '=' + encodeURIComponent(params[key])); } else { result.push(prepareObject(key, params[key])); } }); return result.join('&'); }, request: function (method, region, service, params, data, uri) { if (typeof data === 'undefined' || data === null) { data = ''; } var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''), date = amzdate.replace(/T\d+Z/, ''), canonical_uri = '/' + uri, host = service + '.' + region + '.amazonaws.com', canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n', signed_headers = 'content-encoding;host;x-amz-date', canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data), credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request', request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request), key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date), key = AWS.sign(key, region), key = AWS.sign(key, service), key = AWS.sign(key, 'aws4_request'), request = new HttpRequest(), url = 'https://' + host + canonical_uri + '?' + params; if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } request.addHeader('x-amz-date: ' + amzdate); request.addHeader('x-amz-content-sha256:' + sha256(data)); request.addHeader('Accept: application/json'); request.addHeader('Content-Type: application/json'); request.addHeader('Content-Encoding: amz-1.0'); request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string)); if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken)); } Zabbix.log(4, '[ AWS Lambda ] Sending request: ' + url); response = request.get(url); Zabbix.log(4, '[ AWS Lambda ] Received response with status code ' + request.getStatus() + ': ' + response); if (request.getStatus() !== 200) { throw 'Request failed with status code ' + request.getStatus() + ': ' + response; } try { response = JSON.parse(response); } catch (error) { try { response = JSON.parse(XML.toJson(response)); } catch (error) { throw 'Failed to parse response received from AWS API. Check debug log for more information.'; } } return response; }, listRegions: function () { var payload = { 'Action': 'DescribeRegions', 'Version': '2016-11-15' }; regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload), '', ''), 'DescribeRegionsResponse.regionInfo.item'); if (!Array.isArray(regions)) regions = [regions] return regions }, listFunctions: function () { var lldArray = [], regions = AWS.listRegions(); payload = { 'FunctionVersion': 'ALL', 'MaxItems': '10000' }; regions.forEach(function (region) { var region_name = AWS.getField(region, 'regionName'); if (region_name.match(AWS.params.region_match) === null || region_name.match(AWS.params.region_not_match) !== null) return; lambdaFunction = AWS.getField(AWS.request('GET', region_name, 'lambda', AWS.prepareParams(payload), '', '2015-03-31/functions'), 'Functions'); if (!Array.isArray(lambdaFunction)) lambdaFunction = [lambdaFunction] lambdaFunction.forEach(function (lambdaFunction) { lldArray.push( { name: AWS.getField(lambdaFunction, 'FunctionName'), arn: AWS.getField(lambdaFunction, 'FunctionArn'), runtime: AWS.getField(lambdaFunction, 'Runtime'), version: AWS.getField(lambdaFunction, 'Version'), region: region_name } ) }); }); return lldArray; } }; try { AWS.setParams(JSON.parse(value)); return JSON.stringify(AWS.listFunctions()); } catch (error) { error += (String(error).endsWith('.')) ? '' : '.'; Zabbix.log(3, '[ AWS Lambda ] ERROR: ' + error); return JSON.stringify({ 'error': error }); } filter: evaltype: AND conditions: - macro: '{#AWS.LAMBDA.NAME}' value: '{$AWS.LAMBDA.LLD.FILTER.NAME.MATCHES}' formulaid: A - macro: '{#AWS.LAMBDA.NAME}' value: '{$AWS.LAMBDA.LLD.FILTER.NAME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: B - macro: '{#AWS.LAMBDA.REGION}' value: '{$AWS.LAMBDA.LLD.FILTER.REGION.MATCHES}' formulaid: C - macro: '{#AWS.LAMBDA.REGION}' value: '{$AWS.LAMBDA.LLD.FILTER.REGION.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: D - macro: '{#AWS.LAMBDA.RUNTIME}' value: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.MATCHES}' formulaid: E - macro: '{#AWS.LAMBDA.RUNTIME}' value: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: F description: 'Get Lambda functions.' host_prototypes: - uuid: 7b468bda682c402b96fd55210aa85155 host: '{#AWS.LAMBDA.NAME}' name: '{#AWS.LAMBDA.NAME}' group_links: - group: name: Templates/Cloud templates: - name: 'AWS Lambda by HTTP' macros: - macro: '{$AWS.LAMBDA.ARN}' value: '{#AWS.LAMBDA.ARN}' description: 'The Amazon Resource Names (ARN) of the Lambda function.' - macro: '{$AWS.LAMBDA.NAME}' value: '{#AWS.LAMBDA.NAME}' description: 'Lambda function name.' - macro: '{$AWS.REGION}' value: '{#AWS.LAMBDA.REGION}' description: 'Lambda function region.' tags: - tag: name value: '{#AWS.LAMBDA.NAME}' - tag: region value: '{#AWS.LAMBDA.REGION}' - tag: runtime value: '{#AWS.LAMBDA.RUNTIME}' - tag: service value: lambda timeout: '{$AWS.DATA.TIMEOUT}' parameters: - name: AccessKeyId value: '{$AWS.ACCESS.KEY.ID}' - name: auth_type value: '{$AWS.AUTH_TYPE}' - name: describe_region value: '{$AWS.DESCRIBE.REGION}' - name: proxy value: '{$AWS.PROXY}' - name: region_match value: '{$AWS.LAMBDA.LLD.FILTER.REGION.MATCHES}' - name: region_not_match value: '{$AWS.LAMBDA.LLD.FILTER.REGION.NOT_MATCHES}' - name: role_arn value: '{$AWS.ASSUME.ROLE.ARN}' - name: SecretAccessKey value: '{$AWS.SECRET.ACCESS.KEY}' - name: sts_region value: '{$AWS.STS.REGION}' lld_macro_paths: - lld_macro: '{#AWS.LAMBDA.ARN}' path: $.arn - lld_macro: '{#AWS.LAMBDA.NAME}' path: $.name - lld_macro: '{#AWS.LAMBDA.REGION}' path: $.region - lld_macro: '{#AWS.LAMBDA.RUNTIME}' path: $.runtime - lld_macro: '{#AWS.LAMBDA.VERSION}' path: $.version - uuid: c1127e674b7548b2802cd8771f3a4768 name: 'RDS instances discovery' type: SCRIPT key: aws.rds.discovery delay: 12h params: | var AWS = { params: {}, metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials', getField: function (data, path) { var steps = path.split('.'); for (var i = 0; i < steps.length; i++) { var step = steps[i]; if (typeof data !== 'object' || typeof data[step] === 'undefined') { throw 'Required field was not found: ' + path; } data = data[step]; } return data; }, setParams: function (params) { AWS.params['proxy'] = params.proxy; switch (AWS.getField(params, 'auth_type')) { case 'role_base': AWS.params['auth_type'] = 'role_base'; var request = new HttpRequest(); if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } var IamRoleName = request.get(AWS.metadata); if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') { throw 'Error getting security credentials from instance metadata. Role not found.'; } credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName)); if (request.getStatus() !== 200 || credentials === null || credentials === '') { throw 'Error getting security credentials from instance metadata.'; } try { credentials = JSON.parse(credentials); } catch (error) { throw 'Failed to parse response received from instance metadata. Check debug log for more information.'; } ['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; case 'assume_role': AWS.params['auth_type'] = 'assume_role'; ['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); role_arn_regex = /role\/(.+)$/; var payload = { 'Action': 'AssumeRole', 'Version': '2011-06-15', 'RoleArn': AWS.params.role_arn, 'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[1] + 'Session', }; credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials'); ['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; default: AWS.params['auth_type'] = 'access_key'; ['AccessKeyId', 'SecretAccessKey'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); } ['describe_region', 'region_match', 'region_not_match'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); }, sign: function (key, message) { var hex = hmac('sha256', key, message); if ((hex.length % 2) === 1) { throw 'Invalid length of a hex string!'; } var result = new Int8Array(hex.length / 2); for (var i = 0, b = 0; i < hex.length; i += 2, b++) { result[b] = parseInt(hex.substring(i, i + 2), 16); } return result; }, prepareParams: function (params) { var result = []; Object.keys(params).sort().forEach(function (key) { if (typeof params[key] !== 'object') { result.push(key + '=' + encodeURIComponent(params[key])); } else { result.push(prepareObject(key, params[key])); } }); return result.join('&'); }, request: function (method, region, service, params, data) { if (typeof data === 'undefined' || data === null) { data = ''; } var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''), date = amzdate.replace(/T\d+Z/, ''), canonical_uri = '/', host = service + '.' + region + '.amazonaws.com', canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n', signed_headers = 'content-encoding;host;x-amz-date', canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data), credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request', request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request), key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date), key = AWS.sign(key, region), key = AWS.sign(key, service), key = AWS.sign(key, 'aws4_request'), request = new HttpRequest(), url = 'https://' + host + canonical_uri + '?' + params; if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } request.addHeader('x-amz-date: ' + amzdate); request.addHeader('x-amz-content-sha256:' + sha256(data)); request.addHeader('Accept: application/json'); request.addHeader('Content-Type: application/json'); request.addHeader('Content-Encoding: amz-1.0'); request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string)); if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken)); } Zabbix.log(4, '[ AWS RDS ] Sending request: ' + url); response = request.get(url); Zabbix.log(4, '[ AWS RDS ] Received response with status code ' + request.getStatus() + ': ' + response); if (request.getStatus() !== 200) { throw 'Request failed with status code ' + request.getStatus() + ': ' + response; } try { response = JSON.parse(response); } catch (error) { try { response = JSON.parse(XML.toJson(response)); } catch (error) { throw 'Failed to parse response received from AWS API. Check debug log for more information.'; } } return response; }, listRegions: function () { var payload = { 'Action': 'DescribeRegions', 'Version': '2016-11-15' }; regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item'); if (!Array.isArray(regions)) regions = [regions] return regions }, listInstances: function () { var lld_array = [], regions = AWS.listRegions(), payload = { 'Action': 'DescribeDBInstances', 'Version': '2014-10-31' }; regions.forEach(function (region) { var region_name = AWS.getField(region, 'regionName'); if (region_name.match(AWS.params.region_match) === null || region_name.match(AWS.params.region_not_match) !== null) return; result = AWS.request('GET', region_name, 'rds', AWS.prepareParams(payload)); databases = AWS.getField(result, 'DescribeDBInstancesResponse.DescribeDBInstancesResult.DBInstances') if (!Array.isArray(databases)) databases = [databases] databases.forEach(function (db) { lld_array.push( { DBInstanceIdentifier: AWS.getField(db, 'DBInstanceIdentifier'), instanceRegion: region_name } ) }); }); return lld_array; } }; try { AWS.setParams(JSON.parse(value)); return JSON.stringify(AWS.listInstances()); } catch (error) { error += (String(error).endsWith('.')) ? '' : '.'; Zabbix.log(3, '[ AWS RDS ] ERROR: ' + error); return JSON.stringify({ 'error': error }); } filter: evaltype: AND conditions: - macro: '{#AWS.RDS.INSTANCE.ID}' value: '{$AWS.RDS.LLD.FILTER.NAME.MATCHES}' formulaid: A - macro: '{#AWS.RDS.INSTANCE.ID}' value: '{$AWS.RDS.LLD.FILTER.NAME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: B - macro: '{#AWS.RDS.REGION}' value: '{$AWS.RDS.LLD.FILTER.REGION.MATCHES}' formulaid: C - macro: '{#AWS.RDS.REGION}' value: '{$AWS.RDS.LLD.FILTER.REGION.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: D description: 'Get RDS instances.' host_prototypes: - uuid: 799663c52a644f78aa3b3c14d4cc7235 host: '{#AWS.RDS.INSTANCE.ID}' name: '{#AWS.RDS.INSTANCE.ID}' group_links: - group: name: Templates/Databases templates: - name: 'AWS RDS instance by HTTP' macros: - macro: '{$AWS.RDS.INSTANCE.ID}' value: '{#AWS.RDS.INSTANCE.ID}' description: 'RDS instance ID.' - macro: '{$AWS.REGION}' value: '{#AWS.RDS.REGION}' description: 'RDS instance region.' tags: - tag: name value: '{#AWS.RDS.INSTANCE.ID}' - tag: region value: '{#AWS.RDS.REGION}' - tag: service value: rds custom_interfaces: 'YES' interfaces: - ip: '{#AWS.RDS.INSTANCE.ID}' timeout: '{$AWS.DATA.TIMEOUT}' parameters: - name: AccessKeyId value: '{$AWS.ACCESS.KEY.ID}' - name: auth_type value: '{$AWS.AUTH_TYPE}' - name: describe_region value: '{$AWS.DESCRIBE.REGION}' - name: proxy value: '{$AWS.PROXY}' - name: region_match value: '{$AWS.RDS.LLD.FILTER.REGION.MATCHES}' - name: region_not_match value: '{$AWS.RDS.LLD.FILTER.REGION.NOT_MATCHES}' - name: role_arn value: '{$AWS.ASSUME.ROLE.ARN}' - name: SecretAccessKey value: '{$AWS.SECRET.ACCESS.KEY}' - name: sts_region value: '{$AWS.STS.REGION}' lld_macro_paths: - lld_macro: '{#AWS.RDS.INSTANCE.ID}' path: $.DBInstanceIdentifier - lld_macro: '{#AWS.RDS.REGION}' path: $.instanceRegion - uuid: ab6a97a108fb4dbc9fd1e07378721ffe name: 'S3 buckets discovery' type: SCRIPT key: aws.s3.discovery delay: 12h params: | var AWS = { params: {}, metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials', getField: function (data, path) { var steps = path.split('.'); for (var i = 0; i < steps.length; i++) { var step = steps[i]; if (typeof data !== 'object' || typeof data[step] === 'undefined') { throw 'Required field was not found: ' + path; } data = data[step]; } return data; }, setParams: function (params) { AWS.params['proxy'] = params.proxy; switch (AWS.getField(params, 'auth_type')) { case 'role_base': AWS.params['auth_type'] = 'role_base'; var request = new HttpRequest(); if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } var IamRoleName = request.get(AWS.metadata); if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') { throw 'Error getting security credentials from instance metadata. Role not found.'; } credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName)); if (request.getStatus() !== 200 || credentials === null || credentials === '') { throw 'Error getting security credentials from instance metadata.'; } try { credentials = JSON.parse(credentials); } catch (error) { throw 'Failed to parse response received from instance metadata. Check debug log for more information.'; } ['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; case 'assume_role': AWS.params['auth_type'] = 'assume_role'; ['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); role_arn_regex = /role\/(.+)$/; var payload = { 'Action': 'AssumeRole', 'Version': '2011-06-15', 'RoleArn': AWS.params.role_arn, 'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[1] + 'Session', }; credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials'); ['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) { if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') { throw 'Required credentials is not set: "' + field + '".'; }; AWS.params[field] = credentials[field]; }); break; default: AWS.params['auth_type'] = 'access_key'; ['AccessKeyId', 'SecretAccessKey'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); } ['request_region'].forEach(function (field) { if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') { throw 'Required param is not set: "' + field + '".'; } AWS.params[field] = params[field]; }); }, sign: function (key, message) { var hex = hmac('sha256', key, message); if ((hex.length % 2) === 1) { throw 'Invalid length of a hex string!'; } var result = new Int8Array(hex.length / 2); for (var i = 0, b = 0; i < hex.length; i += 2, b++) { result[b] = parseInt(hex.substring(i, i + 2), 16); } return result; }, prepareParams: function (params) { var result = []; Object.keys(params).sort().forEach(function (key) { if (typeof params[key] !== 'object') { result.push(key + '=' + encodeURIComponent(params[key])); } else { result.push(prepareObject(key, params[key])); } }); return result.join('&'); }, request: function (method, region, service, params, data) { if (typeof data === 'undefined' || data === null) { data = ''; } var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''), date = amzdate.replace(/T\d+Z/, ''), canonical_uri = '/', host = service + '.' + region + '.amazonaws.com'; if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { token = AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken; var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' + 'x-amz-security-token:' + token + '\n', signed_headers = 'content-encoding;host;x-amz-date;x-amz-security-token'; } else { var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n', signed_headers = 'content-encoding;host;x-amz-date'; } var canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data), credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request', request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request), key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date), key = AWS.sign(key, region), key = AWS.sign(key, service), key = AWS.sign(key, 'aws4_request'), request = new HttpRequest(), url = 'https://' + host + canonical_uri + '?' + params; if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') { request.setProxy(AWS.params.proxy); } request.addHeader('x-amz-date: ' + amzdate); request.addHeader('x-amz-content-sha256:' + sha256(data)); request.addHeader('Accept: application/json'); request.addHeader('Content-Type: application/json'); request.addHeader('Content-Encoding: amz-1.0'); request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string)); if (AWS.params.auth_type === 'role_base' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) { request.addHeader('X-Amz-Security-Token: ' + token); } Zabbix.log(4, '[ AWS S3 ] Sending request: ' + url); response = request.get(url); Zabbix.log(4, '[ AWS S3 ] Received response with status code ' + request.getStatus() + ': ' + response); if (request.getStatus() !== 200) { throw 'Request failed with status code ' + request.getStatus() + ': ' + response; } try { response = JSON.parse(response); } catch (error) { try { response = JSON.parse(XML.toJson(response)); } catch (error) { throw 'Failed to parse response received from AWS API. Check debug log for more information.'; } } return response; }, listBuckets: function () { var payload = { 'Action': 'ListBuckets', 'Version': '2006-03-01' }; var result = AWS.getField(AWS.request('GET', AWS.params.request_region, 's3', AWS.prepareParams(payload)), 'ListAllMyBucketsResult.Buckets'); if (result === null) { return []; } result = AWS.getField(result, 'Bucket'); return Array.isArray(result) ? result : [result]; } }; try { AWS.setParams(JSON.parse(value)); return JSON.stringify(AWS.listBuckets()); } catch (error) { error += (String(error).endsWith('.')) ? '' : '.'; Zabbix.log(3, '[ AWS S3 ] ERROR: ' + error); return JSON.stringify({ 'error': error }); } filter: evaltype: AND conditions: - macro: '{#AWS.S3.NAME}' value: '{$AWS.S3.LLD.FILTER.NAME.MATCHES}' formulaid: A - macro: '{#AWS.S3.NAME}' value: '{$AWS.S3.LLD.FILTER.NAME.NOT_MATCHES}' operator: NOT_MATCHES_REGEX formulaid: B description: 'Get S3 bucket instances.' host_prototypes: - uuid: e45bd9810ea14718b17b875aad3fc544 host: '{#AWS.S3.NAME}' name: '{#AWS.S3.NAME}' group_links: - group: name: Templates/Applications templates: - name: 'AWS S3 bucket by HTTP' macros: - macro: '{$AWS.S3.BUCKET.NAME}' value: '{#AWS.S3.NAME}' description: 'S3 bucket name.' - macro: '{$AWS.S3.FILTER.ID}' value: '1' description: 'S3 bucket requests filter identifier.' tags: - tag: name value: '{#AWS.S3.NAME}' - tag: service value: s3 custom_interfaces: 'YES' interfaces: - ip: '{#AWS.S3.NAME}' timeout: '{$AWS.DATA.TIMEOUT}' parameters: - name: AccessKeyId value: '{$AWS.ACCESS.KEY.ID}' - name: auth_type value: '{$AWS.AUTH_TYPE}' - name: proxy value: '{$AWS.PROXY}' - name: request_region value: '{$AWS.REQUEST.REGION}' - name: role_arn value: '{$AWS.ASSUME.ROLE.ARN}' - name: SecretAccessKey value: '{$AWS.SECRET.ACCESS.KEY}' - name: sts_region value: '{$AWS.STS.REGION}' lld_macro_paths: - lld_macro: '{#AWS.S3.NAME}' path: $.Name tags: - tag: class value: software - tag: target value: aws macros: - macro: '{$AWS.ACCESS.KEY.ID}' description: 'Access key ID.' - macro: '{$AWS.ASSUME.ROLE.ARN}' description: 'ARN assume role; add when using the `assume_role` authorization method.' - macro: '{$AWS.AUTH_TYPE}' value: access_key description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.' - macro: '{$AWS.DATA.TIMEOUT}' value: 60s description: 'A response timeout for an API.' - macro: '{$AWS.DESCRIBE.REGION}' value: us-east-1 description: 'Region used in POST request `DescribeRegions`.' - macro: '{$AWS.EC2.LLD.FILTER.NAME.MATCHES}' value: '.*' description: 'Filter of discoverable EC2 instances by namespace.' - macro: '{$AWS.EC2.LLD.FILTER.NAME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered EC2 instances by namespace.' - macro: '{$AWS.EC2.LLD.FILTER.REGION.MATCHES}' value: '.*' description: 'Filter of discoverable EC2 instances by region.' - macro: '{$AWS.EC2.LLD.FILTER.REGION.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered EC2 instances by region.' - macro: '{$AWS.ECS.LLD.FILTER.NAME.MATCHES}' value: '.*' description: 'Filter of discoverable ECS clusters by name.' - macro: '{$AWS.ECS.LLD.FILTER.NAME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered ECS clusters by name.' - macro: '{$AWS.ECS.LLD.FILTER.REGION.MATCHES}' value: '.*' description: 'Filter of discoverable ECS clusters by region.' - macro: '{$AWS.ECS.LLD.FILTER.REGION.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered ECS clusters by region.' - macro: '{$AWS.ECS.LLD.FILTER.STATUS.MATCHES}' value: ACTIVE description: 'Filter of discoverable ECS clusters by status.' - macro: '{$AWS.ECS.LLD.FILTER.STATUS.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered ECS clusters by status.' - macro: '{$AWS.ELB.LLD.FILTER.NAME.MATCHES}' value: '.*' description: 'Filter of discoverable ELB load balancers by name.' - macro: '{$AWS.ELB.LLD.FILTER.NAME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered ELB load balancers by name.' - macro: '{$AWS.ELB.LLD.FILTER.REGION.MATCHES}' value: '.*' description: 'Filter of discoverable ELB load balancers by region.' - macro: '{$AWS.ELB.LLD.FILTER.REGION.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered ELB load balancers by region.' - macro: '{$AWS.ELB.LLD.FILTER.STATE.MATCHES}' value: active description: 'Filter of discoverable ELB load balancers by status.' - macro: '{$AWS.ELB.LLD.FILTER.STATE.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered ELB load balancer by status.' - macro: '{$AWS.LAMBDA.LLD.FILTER.NAME.MATCHES}' value: '.*' description: 'Filter of discoverable Lambda functions by name.' - macro: '{$AWS.LAMBDA.LLD.FILTER.NAME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered Lambda functions by name.' - macro: '{$AWS.LAMBDA.LLD.FILTER.REGION.MATCHES}' value: '.*' description: 'Filter of discoverable Lambda functions by region.' - macro: '{$AWS.LAMBDA.LLD.FILTER.REGION.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered Lambda functions by region.' - macro: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.MATCHES}' value: '.*' description: 'Filter of discoverable Lambda functions by Runtime.' - macro: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered Lambda functions by Runtime.' - macro: '{$AWS.PROXY}' description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.' - macro: '{$AWS.RDS.LLD.FILTER.NAME.MATCHES}' value: '.*' description: 'Filter of discoverable RDS instances by namespace.' - macro: '{$AWS.RDS.LLD.FILTER.NAME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered RDS instances by namespace.' - macro: '{$AWS.RDS.LLD.FILTER.REGION.MATCHES}' value: '.*' description: 'Filter of discoverable RDS instances by region.' - macro: '{$AWS.RDS.LLD.FILTER.REGION.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered RDS instances by region.' - macro: '{$AWS.REQUEST.REGION}' value: us-east-1 description: 'Region used in GET request `ListBuckets`.' - macro: '{$AWS.S3.LLD.FILTER.NAME.MATCHES}' value: '.*' description: 'Filter of discoverable S3 buckets by namespace.' - macro: '{$AWS.S3.LLD.FILTER.NAME.NOT_MATCHES}' value: CHANGE_IF_NEEDED description: 'Filter to exclude discovered S3 buckets by namespace.' - macro: '{$AWS.SECRET.ACCESS.KEY}' type: SECRET_TEXT description: 'Secret access key.' - macro: '{$AWS.STS.REGION}' value: us-east-1 description: 'Region used in assume role request.'