【Ruby】ActiveSupportを使わず標準添付ライブラリReXML/JSONだけでXML→JSON変換する(ruby 2.2.0)

2016.03.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹@上越妙高オフィスです。 以前Chatwork APIを使う練習としてAWS Service Health DashboardのRSSの更新をChatworkへポストするというブログを書きました。

その際にRSS(XML)をJSONに変換するための、なんちゃってパーサーを使いました。

今回この処理をベースにAWSのセキュリティ関係RSSを追加しようとしたのですが、AWS Security Bulletinsの出力するRSSが整形されておらず、なんちゃってパーサーでは解析できませんでした。

RubyでXMLからJSONへの変換はActiveSupportを使うのが簡単なようです。が、今回ジョブを実行するJenkins環境をgemで汚したくないし、かといってBundlerでgemを個別管理するための仕組みを用意するのも大変なので標準ライブラリだけでがんばってみました。

ReXMLとJSONモジュール

RubyにはReXMLというXMLパーサーがあります。これを使うとRSSをオブジェクトとして取得できます。REXML::Elementに#to_hというハッシュへの変換を行うメソッドを追加してみました。

出力サンプル

実際出力するとrootエレメントの情報がなかったり、アトリビュートがいろいろ消えちゃったりしてますが、そこはご勘弁ください。

Amazon Security Bulletins

  • https://aws.amazon.com/jp/security/security-bulletins/
$ ./xml2json.rb aws_security_bulletins.rss| jq "."
{
  "channel": {
    "link": "https://aws.amazon.com/security/security-bulletins.rss",
    "title": "Security Bulletins",
    "managingEditor": "aws@amazon.com",
    "lastBuildDate": "Tue, 01 Mar 2016 18:25:33 +0000",
    "pubDate": "Tue, 01 Mar 2016 18:25:33 +0000",
    "docs": "http://blogs.law.harvard.edu/tech/rss",
    "image": {
      "url": "https://a0.awsstatic.com/main/images/feed/AWSlogo_200x100.png",
      "link": "https://aws.amazon.com/security/security-bulletins.rss",
      "title": "Security Bulletins",
      "width": "144",
      "height": "400"
    },
    "item": [
      {
        "link": "https://aws.amazon.com/security/security-bulletins/cve-2016-0800-advisory/",
        "guid": "c3a386db682f2ef7726948a67991da6a810a8bb8",
        "title": "CVE-2016-0800 Advisory",
        "description": "<p><b>2016/03/01 - 10:30 AM PDT</b></p> \n<p>&nbsp;</p> \n<p>We have reviewed the issues described in <a href=\"https://www.openssl.org/news/secadv/20160301.txt\" target=\"_blank\">CVE-2016-0800</a>, known as “DROWN,” and have determined that AWS Services are not affected. Amazon Elastic Load Balancer customers that have modified their default ELB configurations in order to explicitly accept SSLv2 should immediately follow the steps below to disable SSLv2 from their environment.</p> \n<p>&nbsp;</p> \n<p>The following steps can be used to enable the AWS-recommended Predefined Security Policy via the AWS Console:</p> \n<p>&nbsp;&nbsp;&nbsp; 1. Select your load balancer (EC2 &gt; Load Balancers).</p> \n<p>&nbsp;&nbsp;&nbsp; 2. In the Listeners tab, click &quot;Change&quot; in the Cipher column.</p> \n<p>&nbsp;&nbsp;&nbsp; 3. Ensure that the radio button for &quot;Predefined Security Policy&quot; is selected</p> \n<p>&nbsp;&nbsp;&nbsp; 4. In the dropdown, select the &quot;ELBSecurityPolicy-2015-05&quot; policy.</p> \n<p>&nbsp;&nbsp;&nbsp; 5. Click &quot;Save&quot; to apply the settings to the listener.</p> \n<p>&nbsp;&nbsp;&nbsp; 6. Repeat these steps for each listener that is using HTTPS or SSL for each load balancer.</p> \n<p>For more information, please see:</p> \n<p><a target=\"_blank\" href=\"http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-ssl-security-policy.html\">http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-ssl-security-policy.html</a></p> \n<p>&nbsp;</p> \n<p>&nbsp;</p> \n<p>&nbsp;</p> \n<p>&nbsp;</p>",
        "pubDate": "Tue, 01 Mar 2016 18:23:18 +0000",
        "author": "aws@amazon.com"
      },

Amazon Linux AMI Security Bulletins

  • https://alas.aws.amazon.com
$ ./xml2json.rb alas.rss| jq "."
{
  "channel": {
    "title": "Amazon Linux AMI Security Bulletins",
    "description": "Amazon Linux AMI Security Bulletins",
    "link": "https://alas.aws.amazon.com",
    "language": "en-us",
    "ttl": "35",
    "item": [
      {
        "title": "ALAS-2016-655 (medium): nginx",
        "description": "\n            CVE-2016-0747, CVE-2016-0746, CVE-2016-0742\n        ",
        "pubDate": "Fri, 19 Feb 2016 15:50:00 GMT",
        "guid": "https://alas.aws.amazon.com/ALAS-2016-655.html",
        "link": "https://alas.aws.amazon.com/ALAS-2016-655.html"
      },

JVN(Japan Vulnerability Notes)

JVNは RSS1.0 なので上2つとちょっと形式が違います。

  • http://jvn.jp/
$ ./xml2json.rb jvn.rss| jq "."
{
  "channel": {
    "title": "JVNRSS Feed - Update Entry",
    "link": "http://jvn.jp/",
    "description": "JVN サイト新着ならびに更新情報",
    "publisher": "JVN",
    "creator": "jvn@jvn.jp",
    "date": "2016-03-03T10:22:08+09:00",
    "modified": "2016-03-03T10:22:08+09:00",
    "items": {
      "Seq": {}
    }
  },
  "item": [
    {
      "title": "glibc にバッファオーバーフローの脆弱性",
      "link": "http://jvn.jp/vu/JVNVU97236594/",
      "description": "glibc には、バッファオーバーフローの脆弱性が存在します。",
      "publisher": "JVN",
      "creator": "jvn@jvn.jp",
      "identifier": "JVNVU#97236594",
      "relation": "http://jvn.jp/vu/JVNVU97236594/",
      "date": "2016-03-03T10:30:00+09:00",
      "issued": "2016-02-17T13:45:15+09:00",
      "modified": "2016-03-03T10:30:00+09:00"
    },

まとめ

標準ライブラリが充実してると処理が簡単になって、ポータビリティもあがってうれしいですね。(その昔CPANが使えない環境でPerl5のスクリプトを書いたことがあります)

RSSをJSONにできれば、jqなりで好きなように処理してChatworkにポストすればOKです。 RubyでRSS読み込んでそのままChatworkにポストすればJSONに変換する必要もないんですが、シェルスクリプトが好きなんです。

というわけでRubyの小ネタでした。