diff options
-rw-r--r-- | Gemfile | 8 | ||||
-rw-r--r-- | Gemfile.lock | 41 | ||||
-rw-r--r-- | anzen.rb | 88 | ||||
-rw-r--r-- | config.ru | 3 | ||||
-rw-r--r-- | lib/glsa_repository.rb | 55 | ||||
-rw-r--r-- | lib/glsav1.rb | 37 | ||||
-rw-r--r-- | lib/helpers.rb | 62 | ||||
-rw-r--r-- | public/css/main.css | 3 | ||||
-rw-r--r-- | views/glsa.erb | 21 | ||||
-rw-r--r-- | views/glsa/glsav1.erb | 86 | ||||
-rw-r--r-- | views/index.erb | 33 | ||||
-rw-r--r-- | views/layout.erb | 118 | ||||
-rw-r--r-- | views/subscribe.erb | 76 |
13 files changed, 631 insertions, 0 deletions
@@ -0,0 +1,8 @@ +source 'https://rubygems.org' + +gem 'sinatra' +gem 'sinatra-partial' +gem 'json' +gem 'nokogiri' +gem 'thin' +gem 'sanitize'
\ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..192e498 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,41 @@ +GEM + remote: https://rubygems.org/ + specs: + crass (1.0.1) + daemons (1.1.9) + eventmachine (1.0.4) + json (1.8.2) + mini_portile (0.6.2) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) + nokogumbo (1.2.0) + nokogiri + rack (1.6.0) + rack-protection (1.5.3) + rack + sanitize (3.1.1) + crass (~> 1.0.1) + nokogiri (>= 1.4.4) + nokogumbo (= 1.2.0) + sinatra (1.4.5) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (~> 1.3, >= 1.3.4) + sinatra-partial (0.4.0) + sinatra + thin (1.6.3) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0) + rack (~> 1.0) + tilt (1.4.1) + +PLATFORMS + ruby + +DEPENDENCIES + json + nokogiri + sanitize + sinatra + sinatra-partial + thin diff --git a/anzen.rb b/anzen.rb new file mode 100644 index 0000000..cd52ec7 --- /dev/null +++ b/anzen.rb @@ -0,0 +1,88 @@ +# /usr/bin/env ruby +# 安全 [anzen] aka security.gentoo.org +# Alex Legler <a3li@gentoo.org> +# AGPLv3 + +require 'bundler/setup' +require 'yaml' +require 'singleton' +require 'nokogiri' +require 'sinatra' +require 'sinatra/partial' + +require_relative 'lib/helpers.rb' +require_relative 'lib/glsa_repository.rb' + +configure do + set :partial_template_engine, :erb + mime_type :atom, 'application/atom+xml' +end + +# Implicitly load advisories +GLSARepository.instance + +BASE_URL = 'https://security.gentoo.org/'.freeze + +get '/glsa' do + @ids = GLSARepository.instance.get.keys.reverse + @nav = :glsa + erb :glsa +end + +get '/glsa/feed.:format' do + items = GLSARepository.instance.get.values.reverse[0..50] + case params[:format] + when 'atom' + content_type :atom + feed('atom', items) + when 'rss1' + content_type :xml + feed('1.0', items) + when 'rss', 'rss2' + content_type :xml + feed('2.0', items) + else + status 404 + body 'Feed not available.' + return + end +end + +get '/glsa/:glsaid.xml' do + if params[:glsaid] =~ /^\d{6}-\d{2}$/ and GLSARepository.instance.has? params[:glsaid] + send_file(File.join(File.dirname(__FILE__), 'data/glsa/glsa-' + params[:glsaid] + '.xml'), type: :xml) + else + status 404 + body 'GLSA not found.' + return + end +end + +get '/glsa/:glsaid' do + if GLSARepository.instance.has? params[:glsaid] + @glsa = GLSARepository.instance[params[:glsaid]] + template = :glsa + + if @glsa.is_a? GLSAv1 + template = :'glsa/glsav1' + end + + @nav = :glsa + erb template + else + status 404 + body 'GLSA not found.' + return + end +end + +get '/subscribe' do + @nav = :subscribe + erb :subscribe +end + +get '/' do + @ids = GLSARepository.instance.get.keys.reverse + @nav = :index + erb :index +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..f8f414c --- /dev/null +++ b/config.ru @@ -0,0 +1,3 @@ +require File.expand_path '../anzen.rb', __FILE__ + +run Sinatra::Application diff --git a/lib/glsa_repository.rb b/lib/glsa_repository.rb new file mode 100644 index 0000000..90c9899 --- /dev/null +++ b/lib/glsa_repository.rb @@ -0,0 +1,55 @@ +require_relative 'glsav1.rb' +require 'date' + +class GLSARepository + include Singleton + + CACHE_SECONDS = 3600 + DATA_PATH = File.join(File.dirname(__FILE__), '../data/glsa/') + + def initialize + update! + end + + def update! + advisories = {} + + Dir.glob(DATA_PATH + '*.xml').each do |glsa_file| + f = File.open(glsa_file) + glsa = Nokogiri::XML(f) + f.close + + if glsa.root.key? 'version' + # Future extension: GLSAv2 + else + begin + advisories[glsa.root['id']] = GLSAv1.new.parse(glsa) + rescue + next + end + end + end + + @load_date = DateTime.now + @advisories = advisories.freeze + end + + def get + @advisories + end + + def[](id) + @advisories[id] + end + + def has?(id) + @advisories.has_key? id + end + + private + def update? + if ((DateTime.now - @load_date) * 60 * 60 * 24).to_i > CACHE_SECONDS + update! + end + end +end
\ No newline at end of file diff --git a/lib/glsav1.rb b/lib/glsav1.rb new file mode 100644 index 0000000..789de2b --- /dev/null +++ b/lib/glsav1.rb @@ -0,0 +1,37 @@ +# A version 1 GLSA +class GLSAv1 + attr_reader :id, :title, :synopsis, :product, :date, :revised, :revision, :bugs, :access, :packages, + :background, :description, :severity, :impact, :workaround, :resolution, :references + + def parse(xml) + @id = xml.root['id'] + @title = xml.xpath('/glsa/title/text()').first.content + @synopsis = xml.xpath('/glsa/synopsis/text()').first.content + @product = xml.xpath('/glsa/product/text()').first.content + @date = xml.xpath('/glsa/announced/text()').first.content + @revised, + @revision = xml.xpath('/glsa/revised/text()').first.content.split(': ') + + @bugs = xml.xpath('/glsa/bug/text()').map {|bug_node| bug_node.content.to_i } + @access = xml.xpath('/glsa/access/text()').first.content + + @packages = {} + xml.xpath('/glsa/affected/package').each do |package| + @packages[package['name'] + ':' + package['arch']] = { + auto: package['auto'] == 'yes', + unaffected: package.xpath('./unaffected').map {|ver| [ver['range'], ver.content] }, + vulnerable: package.xpath('./vulnerable').map {|ver| [ver['range'], ver.content] } + } + end + + @background = xml.xpath('/glsa/background').first.children.to_xml.strip + @description = xml.xpath('/glsa/description').first.children.to_xml.strip + @severity = xml.xpath('/glsa/impact').first['type'] + @impact = xml.xpath('/glsa/impact').first.children.to_xml.strip + @workaround = xml.xpath('/glsa/workaround').first.children.to_xml.strip + @resolution = xml.xpath('/glsa/resolution').first.children.to_xml.strip + @references = xml.xpath('/glsa/references/uri').map {|uri| [uri.content, uri['link']] } + + self + end +end
\ No newline at end of file diff --git a/lib/helpers.rb b/lib/helpers.rb new file mode 100644 index 0000000..34ed17f --- /dev/null +++ b/lib/helpers.rb @@ -0,0 +1,62 @@ +require 'sanitize' +require 'erb' +require 'rss' + +COMP_MAP = { + '>=' => 'ge', + '>' => 'gt', + '=' => 'eq', + '<=' => 'le', + '<' => 'lt', + 'revision <' => 'rlt', + 'revision <=' => 'rle', + 'revision >' => 'rgt', + 'revision >=' => 'rge' +}.freeze + +helpers do + def h(text) + Rack::Utils.escape_html(text) + end + + def u(text) + ERB::Util::url_encode(text) + end + + def h2(text) + Sanitize.clean(text, Sanitize::Config::BASIC) + end + + def code2pre(text) + text.gsub('<code>', '<pre>').gsub('</code>', '</pre>').gsub(/ +/, ' ').chomp + end + + # Returns the comparator in the format needed for the XML + def xml_comp(val) + COMP_MAP[val] + end + + def reverse_xml_comp(val) + COMP_MAP.invert[val] + end + + def feed(type, items) + RSS::Maker.make(type) do |maker| + maker.channel.author = "Gentoo Security Team" + maker.channel.about = "https://security.gentoo.org/glsa" + maker.channel.link = "https://security.gentoo.org/glsa" + maker.channel.description = "This feed contains new Gentoo Linux Security Advisories. Contact security@gentoo.org with questions." + maker.channel.title = "Gentoo Linux Security Advisories" + maker.channel.updated = Time.now.to_s + + items.each do |input_item| + maker.items.new_item do |item| + item.link = BASE_URL + 'glsa/' + input_item.id + item.title = "GLSA %s: %s" % [input_item.id, input_item.title] + item.updated = Time.now.to_s + end + end + end.to_s + end + +end
\ No newline at end of file diff --git a/public/css/main.css b/public/css/main.css new file mode 100644 index 0000000..cd6ffd3 --- /dev/null +++ b/public/css/main.css @@ -0,0 +1,3 @@ +.anzen-metadata-title-col { + width: 15em; +}
\ No newline at end of file diff --git a/views/glsa.erb b/views/glsa.erb new file mode 100644 index 0000000..17c77ce --- /dev/null +++ b/views/glsa.erb @@ -0,0 +1,21 @@ +<h1 class="first-header">Gentoo Linux Security Advisories (GLSA)</h1> + +<p> + This page lists all Security Advisories that were released by the Gentoo Security Team. + For more information, please visit our distribution's <a href="http://www.gentoo.org/security/en/index.xml">Security overview</a>. +</p> + +<div class="table-responsive"> + <table class="table table-striped"> + <tr> + <th>ID</th> + <th>Title</th> + </tr> + <% @ids.each do |id| %> + <tr> + <th><a href="/glsa/<%= h id %>"><%= h id %></a></th> + <td><%= h GLSARepository.instance[id].title %></td> + </tr> + <% end %> + </table> +</div>
\ No newline at end of file diff --git a/views/glsa/glsav1.erb b/views/glsa/glsav1.erb new file mode 100644 index 0000000..f779ead --- /dev/null +++ b/views/glsa/glsav1.erb @@ -0,0 +1,86 @@ +<h1 class="first-header"> + <%= h @glsa.title %> + <small>— GLSA <strong><%= h @glsa.id %></strong></small> +</h1> + +<div class="row"> + <div class="col-xs-12 col-md-10"> + <p class="lead"> + <%= h @glsa.synopsis %> + </p> + + <h3>Affected Packages</h3> + + <div class="table-responsive"> + <% @glsa.packages.each_pair do |package, data| + atom, arch = package.split ':' + %> + <table class="table"> + <tr> + <th class="anzen-metadata-title-col">Package</th> + <td><strong><%= h atom %></strong> on <% if arch == '*' %>all architectures<% else %>the <%= h arch %> architecture<% end %></td> + </tr> + <tr class="danger"> + <th>Affected versions</th> + <td><%= data[:unaffected].map { |ver| "%s <strong>%s</strong>" % [h(reverse_xml_comp(ver[0])), h(ver[1])] }.join ', ' %></td> + </tr> + <tr class="success"> + <th>Unaffected versions</th> + <td><%= data[:vulnerable].map { |ver| "%s <strong>%s</strong>" % [h(reverse_xml_comp(ver[0])), h(ver[1])] }.join ', ' %></td> + </tr> + </table> + <% end %> + </div> + + <h3>Background</h3> + <%= h2 @glsa.background %> + + <h3>Description</h3> + <%= h2 @glsa.description %> + + <h3>Impact</h3> + <%= h2 @glsa.impact %> + + <h3>Workaround</h3> + <%= h2 @glsa.workaround %> + + <h3>Resolution</h3> + <%= h2(code2pre(@glsa.resolution)) %> + + <h3>References</h3> + <ul> + <% @glsa.references.each do |ref| %> + <li><a href="<%= h ref[1] %>"><%= h ref[0] %></a></li> + <% end %> + </div> + <div class="col-xs-12 col-md-2"> + <p> + <strong>Release Date</strong> + <br> + <%= h @glsa.date %> + </p> + <p> + <strong>Latest Revision</strong> + <br> + <%= h @glsa.revised %>: <%= h @glsa.revision %> + </p> + <p> + <strong>Severity</strong> + <br> + <%= h @glsa.severity %> + </p> + <p> + <strong>Exploitable</strong> + <br> + <%= h @glsa.access %> + </p> + <p> + <strong>Bugzilla entries</strong> + </p> + <ul> + <% @glsa.bugs.each do |bug| %> + <li><a href="https://bugs.gentoo.org/show_bug.cgi?id=<%= h bug %>"><%= h bug %></a></li> + <% end %> + </ul> + </div> +</div>
\ No newline at end of file diff --git a/views/index.erb b/views/index.erb new file mode 100644 index 0000000..2c42c78 --- /dev/null +++ b/views/index.erb @@ -0,0 +1,33 @@ +<h1 class="first-header">Gentoo Security Database</h1> + +<p> + This page contains security data related to the Gentoo distribution. + Currently, you can find our advisories here. + In the future, more information on CVE names as well as statistics will be available. +</p> + +<div class="alert alert-info"> + <strong>Security Documentation</strong> + <br> + If you want to learn more about keeping your Gentoo system secure, or how to report vulnerabilities, + please visit our <a href="http://www.gentoo.org/security/en/" class="alert-link">security documentation</a>. +</div> + +<h2>Most recent Gentoo Linux Security Advisories</h2> + +<div class="table-responsive"> + <table class="table table-striped"> + <tr> + <th>ID</th> + <th>Title</th> + <th>Date</th> + </tr> + <% @ids[0..10].each do |id| %> + <tr> + <th><a href="/glsa/<%= h id %>"><%= h id %></a></th> + <td><%= h GLSARepository.instance[id].title %></td> + <td><%= h GLSARepository.instance[id].date %></td> + </tr> + <% end %> + </table> +</div>
\ No newline at end of file diff --git a/views/layout.erb b/views/layout.erb new file mode 100644 index 0000000..c55548e --- /dev/null +++ b/views/layout.erb @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<html> + <head> + <title><%= "#{h @title} - " if @title %>Gentoo Security</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content="The Gentoo Mailing List Archives"> + <link href="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/bootstrap.min.css" rel="stylesheet" media="screen"> + <link href="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/tyrian.min.css" rel="stylesheet" media="screen"> + <link href="/css/main.css" rel="stylesheet" media="screen"> + <link rel="icon" href="//www.gentoo.org/favicon.ico" type="image/x-icon"> + </head> + <body> + <header> + <div class="site-title"> + <div class="container"> + <div class="row"> + <div class="site-title-buttons"> + <div class="btn-group btn-group-sm"> + <a href="http://get.gentoo.org/" role="button" class="btn get-gentoo"><span class="fa fa-download"></span> <strong>Get Gentoo!</strong></a> + <div class="btn-group btn-group-sm"> + <a class="btn gentoo-org-sites dropdown-toggle" data-toggle="dropdown" data-target="#" href="#"> + <span class="glyphicon glyphicon-globe"></span> gentoo.org sites <span class="caret"></span> + </a> + <ul class="dropdown-menu"> + <li><a href="http://www.gentoo.org/" title="Main Gentoo website"><span class="fa fa-home fa-fw"></span> gentoo.org</a></li> + <li><a href="http://wiki.gentoo.org/" title="Find and contribute documentation"><span class="fa fa-file-text fa-fw"></span> Wiki</a></li> + <li><a href="https://bugs.gentoo.org/" title="Report issues and find common issues"><span class="fa fa-bug fa-fw"></span> Bugs</a></li> + <li><a href="http://forums.gentoo.org/" title="Discuss with the community"><span class="fa fa-comments-o fa-fw"></span> Forums</a></li> + <li><a href="http://packages.gentoo.org/" title="Find software for your Gentoo"><span class="fa fa-hdd-o fa-fw"></span> Packages</a></li> + <li class="divider"></li> + <li><a href="http://overlays.gentoo.org/" title="Collaborate on maintaining packages"><span class="fa fa-code-fork fa-fw"></span> Overlays</a></li> + <li><a href="http://planet.gentoo.org/" title="Find out what's going on in the developer community"><span class="fa fa-rss fa-fw"></span> Planet</a></li> + <li><a href="http://archives.gentoo.org/" title="Read up on past discussions"><span class="fa fa-archive fa-fw"></span> Archives</a></li> + <li><a href="http://sources.gentoo.org/" title="Browse our source code"><span class="fa fa-code fa-fw"></span> Sources</a></li> + <li class="divider"></li> + <li><a href="http://infra-status.gentoo.org/" title="Get updates on the services provided by Gentoo"><span class="fa fa-tasks fa-fw"></span> Infra Status</a></li> + </ul> + </div> + </div> + </div> + <div class="logo"> + <img src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/site-logo.png" data-at2x="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/site-logo@2x.png" alt="Gentoo Linux Logo" /> + <span class="site-label">Security</span> + </div> + </div> + </div> + </div> + <nav class="tyrian-navbar" role="navigation"> + <div class="container"> + <div class="row"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + <div class="collapse navbar-collapse navbar-main-collapse"> + <ul class="nav navbar-nav"> + <li class="<%= 'active' if @nav == :index %>"><a href="/">Home</a></li> + <li class="<%= 'active' if @nav == :subscribe %>"><a href="/subscribe">Stay informed</a></li> + <li class="<%= 'active' if @nav == :glsa %>"><a href="/glsa">Advisories</a></li> + </ul> + </div> + </div> + </div> + </nav> + </header> + + <div class="container"> + <div class="row"> + <div class="col-xs-12"> + <%= yield %> + </div> + </div> + </div> + + <footer> + <div class="container"> + <div class="row"> + <div class="col-xs-12 col-md-offset-2 col-md-7"> + <p class="spacer"> + </p> + </div> + <div class="col-xs-12 col-md-3"> + <h3 class="footerhead">Questions or comments?</h3> + Please feel free to <a href="mailto:security@gentoo.org">contact us</a>. + </div> + </div> + <div class="row"> + <div class="col-xs-2 col-sm-3 col-md-2"> + <ul class="footerlinks three-icons"> + <li><a href="http://twitter.com/gentoo" title="@Gentoo on Twitter"><span class="fa fa-twitter fa-fw"></span></a></li> + <li><a href="https://plus.google.com/+Gentoo" title="+Gentoo on Google+"><span class="fa fa-google-plus fa-fw"></span></a></li> + <li><a href="https://www.facebook.com/gentoo.org" title="Gentoo on Facebook"><span class="fa fa-facebook fa-fw"></span></a></li> + </ul> + </div> + <div class="col-xs-10 col-sm-9 col-md-10"> + <strong>© 2001–2015 Gentoo Foundation, Inc.</strong><br /> + <small> + Gentoo is a trademark of the Gentoo Foundation, Inc. + The contents of this document, unless otherwise expressly stated, are licensed under the + <a href="http://creativecommons.org/licenses/by-sa/3.0/" rel="license">CC-BY-SA-3.0</a> license. + The <a href="http://www.gentoo.org/main/en/name-logo.xml">Gentoo Name and Logo Usage Guidelines</a> apply. + </small> + </div> + </div> + </div> + </footer> + + <script src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/jquery.min.js"></script> + <script src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/bootstrap.min.js"></script> + <script src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/retina.min.js"></script> + </body> +</html>
\ No newline at end of file diff --git a/views/subscribe.erb b/views/subscribe.erb new file mode 100644 index 0000000..45ad15c --- /dev/null +++ b/views/subscribe.erb @@ -0,0 +1,76 @@ +<h1 class="first-header">Stay informed</h1> + +<div class="row"> + <div class="col-md-4 text-right"> + <i class="fa fa-terminal fa-5x"></i> + </div> + <div class="col-md-8"> + <h2>Check your system's status</h2> + + <p>Use <kbd>glsa-check</kbd> to check your system's security status.<br> + To see all advisories that affect your system, run:</p> + + <p class="lead"><kbd>% glsa-check -t affected</kbd></p> + + <p> + If you don't have the utility installed, run <kbd>emerge -va app-portage/gentoolkit</kbd>.<br> + For more information, review the <a href="https://wiki.gentoo.org/wiki/GLSA">documentation</a> on our Wiki.</p> + </div> +</div> + +<hr> + +<div class="row"> + <div class="col-md-4 text-right"> + <i class="fa fa-inbox fa-5x"></i> + </div> + <div class="col-md-8"> + <h2>Subscribe via E-Mail</h2> + + <p>Our advisories are posted to the <em>gentoo-announce</em> mailing list.</p> + + <p>You can subscribe by sending an emtpy e-mail to:</p> + + <p class="lead"><a href="mailto:gentoo-announce+subscribe@lists.gentoo.org">gentoo-announce+subscribe@lists.gentoo.org</a></p> + + <p>A confirmation email will be sent. Reply to this email to complete the subscription.</p> + </div> +</div> + +<hr> + +<div class="row"> + <div class="col-md-4 text-right"> + <i class="fa fa-rss fa-5x"></i> + </div> + <div class="col-md-8"> + <h2>Feeds</h2> + + <p>We offer <em>RSS</em> and <em>Atom</em> feeds that you can subscribe to using your news reader:</p> + + <ul class="lead"> + <li><a href="/glsa/feed.rss">RSS 2.0</a></li> + <li><a href="/glsa/feed.atom">Atom 1.4.3</a></li> + </ul> + </div> +</div> + +<hr> + +<div class="row"> + <div class="col-md-4 text-right"> + <i class="fa fa-twitter fa-5x"></i> + </div> + <div class="col-md-8"> + <h2>Twitter</h2> + + <p>There were several <strong>unofficial</strong> Twitter feeds containing GLSAs.</p> + + <p>None of them are currently up to date. Stay tuned.</p> + + <!--<ul class="lead"> + <li><a href="http://twitter.com/gentoosecurity">gentoosecurity <i class="fa-twitter fa"></i></a></li> + </ul> + --> + </div> +</div>
\ No newline at end of file |