|
//実行メニューを作成 |
|
function onOpen() { |
|
var ui = SpreadsheetApp.getUi(); |
|
var menu = ui.createMenu("GAS実行"); |
|
menu.addItem("脆弱性一覧取得", "getVulnOverviewListFromAPI"); |
|
menu.addToUi(); |
|
} |
|
|
|
//MyJVN APIからフィードを取得 |
|
function getVulnOverviewListFromAPI() { |
|
var ss = SpreadsheetApp.getActiveSpreadsheet(); |
|
|
|
var col_count = 8; |
|
var loop_count = 0; |
|
var isContinued = true; |
|
var values = []; |
|
|
|
//当月のスプレッドシート名が存在するか確認する |
|
var today = new Date(); |
|
var yesterday = new Date(); |
|
yesterday.setDate(today.getDate() - 1); |
|
|
|
var sheetName = Utilities.formatDate(yesterday, 'Asia/Tokyo', 'yyyyMM'); |
|
var sheet = ss.getSheetByName(sheetName); |
|
|
|
//シートが存在しなければ2シート目に作成してヘッダーをセット(1シート目は説明用シートを想定) |
|
if (sheet == null) { |
|
ss.insertSheet(sheetName, 1); |
|
sheet = ss.getActiveSheet(); |
|
|
|
//ヘッダー追加 |
|
values.push([ |
|
'更新日', |
|
'ID', |
|
'スコア', |
|
'緊急度', |
|
'タイトル', |
|
'説明', |
|
'影響を受ける製品', |
|
'リンク' |
|
]); |
|
} |
|
|
|
//対象シートの最終行を取得 |
|
var lastRow = sheet.getLastRow(); |
|
|
|
try |
|
{ |
|
//名前空間を取得 |
|
var xmlns = XmlService.getNamespace('http://purl.org/rss/1.0/'); |
|
var rss = XmlService.getNamespace('http://purl.org/rss/1.0/'); |
|
var dc = XmlService.getNamespace('dc', 'http://purl.org/dc/elements/1.1/'); |
|
var dcterms = XmlService.getNamespace('dcterms', 'http://purl.org/dc/terms/'); |
|
var sec = XmlService.getNamespace('sec', 'http://jvn.jp/rss/mod_sec/3.0/'); |
|
|
|
while(isContinued){ |
|
// rangeDatePublic=n : 発見日指定なし(デフォルトは1週間以内) |
|
// rangeDateFirstPublished=n : 発行日指定なし(デフォルトは1週間以内) |
|
var API_URL = 'https://jvndb.jvn.jp/myjvn?method=getVulnOverviewList&feed=hnd&rangeDatePublic=n&rangeDateFirstPublished=n'; |
|
|
|
// 前日に更新された脆弱性のみを取得 |
|
var publishedStartY = 'datePublishedStartY=' + Utilities.formatDate(yesterday, 'Asia/Tokyo', 'yyyy'); |
|
var publishedStartM = 'datePublishedStartM=' + Utilities.formatDate(yesterday, 'Asia/Tokyo', 'M'); |
|
var publishedStartD = 'datePublishedStartD=' + Utilities.formatDate(yesterday, 'Asia/Tokyo', 'd'); |
|
var publishedEndY = 'datePublishedEndY=' + Utilities.formatDate(yesterday, 'Asia/Tokyo', 'yyyy'); |
|
var publishedEndM = 'datePublishedEndM=' + Utilities.formatDate(yesterday, 'Asia/Tokyo', 'M'); |
|
var publishedEndD = 'datePublishedEndD=' + Utilities.formatDate(yesterday, 'Asia/Tokyo', 'd'); |
|
var startItem = 'startItem=' + (1 + 50 * loop_count); |
|
|
|
// 重要度でフィルタしたい場合はseverityをセット(ただし"h:重要 or c:クリティカル"といった複数指定はできない) |
|
//var severity = 'severity=h' //h=重要(7.0~8.9) |
|
|
|
API_URL += '&' + publishedStartY + '&' + publishedStartM + '&' + publishedStartD; |
|
API_URL += '&' + publishedEndY + '&' + publishedEndM + '&' + publishedEndD+ '&' + startItem; |
|
|
|
// 脆弱性概要一覧を取得(最大50行) |
|
var xml = UrlFetchApp.fetch(API_URL).getContentText(); |
|
var document = XmlService.parse(xml); |
|
var root = document.getRootElement(); |
|
var items = root.getChildren('item', rss); |
|
|
|
// 該当する脆弱性が存在しない場合は処理を終了 |
|
// itemsが0件の場合(startItemが検索結果件数を超えた場合)はgetChildできないのでitemsが1件の場合のみに限定 |
|
if(items.length == 1) |
|
{ |
|
if(items[0].getChild('title', rss).getText() == 'MyJVN 該当する脆弱性対策情報はありません。') |
|
{ |
|
Logger.log('該当する脆弱性対策情報はありません。'); |
|
return; |
|
} |
|
} |
|
|
|
for(var i = 0; i < items.length; i++) { |
|
var value = []; |
|
|
|
// スプレッドシート上で既出のJVNであればスキップする |
|
if(JVN_Exists(items[i].getChild('identifier', sec).getText())) |
|
{ |
|
continue; |
|
} |
|
|
|
// pubDate:更新日 |
|
// ※issueDateは発行日であり、発見日に該当する値は詳細取得APIでなければ取得できない |
|
var pubDate = new Date(items[i].getChild('date', dc).getText()); |
|
value.push(Utilities.formatDate(pubDate, 'Asia/Tokyo', 'yyyy/MM/dd')); |
|
|
|
|
|
// JVN識別子 |
|
value.push(items[i].getChild('identifier', sec).getText()); |
|
|
|
// 稀にCVSSが存在しないケースがあるので、その場合はscoreとseverityはブランクにする |
|
if(items[i].getChildren('cvss', sec).length == 0) |
|
{ |
|
value.push(''); |
|
value.push(''); |
|
} |
|
else |
|
{ |
|
// CVSSはv2とv3の2つあるので、v3の方を取得する |
|
var item_cvss = items[i].getChildren('cvss', sec).filter(function(item) { |
|
return item.getAttribute('version').getValue() == '3.0'; |
|
}); |
|
|
|
// 古い脆弱性情報はCVSS v2しかないので、v2を取得する |
|
if(item_cvss.length == 0) |
|
{ |
|
item_cvss = items[i].getChildren('cvss', sec).filter(function(item) { |
|
return item.getAttribute('version').getValue() == '2.0'; |
|
}); |
|
} |
|
|
|
value.push(item_cvss[0].getAttribute('score').getValue()); |
|
value.push(item_cvss[0].getAttribute('severity').getValue()); |
|
} |
|
value.push(items[i].getChild('title', rss).getText()); |
|
value.push(items[i].getChild('description',rss).getText()); |
|
|
|
// 影響を受ける製品(複数存在する場合はセル内改行) |
|
var products = ''; |
|
for(var j= 0; j < items[i].getChildren('cpe', sec).length;j++){ |
|
products = products + items[i].getChildren('cpe', sec)[j].getAttribute('product').getValue() + String.fromCharCode(10); |
|
} |
|
|
|
// 末尾のセル内改行を削除 |
|
if(products.slice(-1) == String.fromCharCode(10)) |
|
{ |
|
products = products.substr(0,products.length - 1); |
|
} |
|
|
|
value.push(products); |
|
value.push(items[i].getChild('link', rss).getText()); |
|
values.push(value); |
|
} |
|
|
|
// 取得件数が50件だった場合は、残りが無なくなるまで処理を繰り返す |
|
if(items.length == 50){ |
|
loop_count++; |
|
}else{ |
|
isContinued = false; |
|
} |
|
} |
|
|
|
// 取得したデータをスプレッドシートにセット |
|
if(values.length > 0){ |
|
sheet.getRange(lastRow + 1, 1, values.length, col_count).setValues(values); |
|
sheet.getRange(lastRow + 1, 1, values.length, col_count).setVerticalAlignment('top') |
|
} |
|
}catch(e){ |
|
Logger.log(e); |
|
console.log(e); |
|
} |
|
} |
|
|
|
//既出のJVN IDの場合はtrueを返す |
|
function JVN_Exists(JVNID){ |
|
var ss = SpreadsheetApp.getActiveSpreadsheet(); |
|
|
|
for(i = 0; i < ss.getNumSheets();i++){ |
|
var sheet = ss.getSheets()[i] ; |
|
|
|
var textFinder = sheet.createTextFinder(JVNID); |
|
var results = textFinder.findAll(); |
|
if(results.length > 0) |
|
{ |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |