From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1303884-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id 8FC1B139347
	for <garchives@archives.gentoo.org>; Mon, 19 Jul 2021 02:55:08 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 367DBE0B2E;
	Mon, 19 Jul 2021 02:55:07 +0000 (UTC)
Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id 10B1EE0B2E
	for <gentoo-commits@lists.gentoo.org>; Mon, 19 Jul 2021 02:55:07 +0000 (UTC)
Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 9AADD342AD5
	for <gentoo-commits@lists.gentoo.org>; Mon, 19 Jul 2021 02:55:05 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id 323D57D9
	for <gentoo-commits@lists.gentoo.org>; Mon, 19 Jul 2021 02:55:04 +0000 (UTC)
From: "John Helmert III" <ajak@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "John Helmert III" <ajak@gentoo.org>
Message-ID: <1626663293.f1634540fe60edd3cbcff258b04d3b4e3aa31577.ajak@gentoo>
Subject: [gentoo-commits] proj/security:ajak-cvetool commit in: bin/
X-VCS-Repository: proj/security
X-VCS-Files: bin/GLSATool.py
X-VCS-Directories: bin/
X-VCS-Committer: ajak
X-VCS-Committer-Name: John Helmert III
X-VCS-Revision: f1634540fe60edd3cbcff258b04d3b4e3aa31577
X-VCS-Branch: ajak-cvetool
Date: Mon, 19 Jul 2021 02:55:04 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
X-Archives-Salt: 27477205-ac83-4e32-a48a-b8a235d1b36a
X-Archives-Hash: 18536d6ebd5897d9b0a5f17e0aef5721

commit:     f1634540fe60edd3cbcff258b04d3b4e3aa31577
Author:     John Helmert III <ajak <AT> gentoo <DOT> org>
AuthorDate: Mon Jul 19 02:49:49 2021 +0000
Commit:     John Helmert III <ajak <AT> gentoo <DOT> org>
CommitDate: Mon Jul 19 02:54:53 2021 +0000
URL:        https://gitweb.gentoo.org/proj/security.git/commit/?id=f1634540

glsatool: add partial releasing functionality

This separates the previous functionality into a `glsatool new` and adds
some new functionality as `glsatool release`. Currently only fetches the
GLSA XML and text, places the XML in your glsa.git repository, and adds
the necessary headers to the mail text.

Signed-off-by: John Helmert III <ajak <AT> gentoo.org>

 bin/GLSATool.py | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 90 insertions(+), 9 deletions(-)

diff --git a/bin/GLSATool.py b/bin/GLSATool.py
index c7fc804..a2a1b1b 100644
--- a/bin/GLSATool.py
+++ b/bin/GLSATool.py
@@ -2,6 +2,7 @@ from configparser import ConfigParser
 import argparse
 import os
 import re
+import sys
 
 import bugzilla
 import requests
@@ -19,9 +20,15 @@ class GLSATool:
         self.auth = glsamaker_key
         self.bgo = bugzilla.Bugzilla('https://bugs.gentoo.org',
                                      api_key=bgo_key, force_rest=True)
-
-    def get_csrf_token(self):
-        soup = bs(self.request('/glsas/new'), features='lxml')
+        config_path = os.path.join(os.path.expanduser('~'),
+                                   '.config', 'glsatool')
+        c = ConfigParser()
+        c.read(config_path)
+        self.glsa_path = c['default']['glsa']
+        self.from_str = c['default']['from']
+
+    def get_csrf_token(self, path):
+        soup = bs(self.request(path), features='lxml')
         csrf_token = \
             soup.find('input', {'name': 'authenticity_token'})['value']
         return csrf_token
@@ -45,6 +52,64 @@ class GLSATool:
             raise RuntimeError(path + ': ' + str(response.status_code))
         return response.text
 
+    def get_int_input(self, msg):
+        while True:
+            i = input(msg)
+            try:
+                return int(i)
+            except (ValueError, EOFError):
+                continue
+
+    def release_glsa(self, num=None):
+        if not num:
+            soup = bs(self.request('/glsas/drafts'), features='lxml')
+            glsas = soup.find_all('tr', {'class': True})
+            for idx, item in enumerate(glsas):
+                print('[{0}] {1}'.format(idx, item.find('a').text))
+            i = self.get_int_input("Which GLSA to release? ")
+            print("Selected '{0}'".format(glsas[i].a.text))
+            num = glsas[i].a['href'][-4:]
+
+        prepare_path = '/glsas/{}/prepare_release'.format(num)
+        release_path = '/glsas/{}/release'.format(num)
+        xml_path = '/glsas/{}/download.xml'.format(num)
+        txt_path = '/glsas/{}/download.txt'.format(num)
+
+        data = {
+            'value': 'Release &gt;',
+            'authenticity_token': self.get_csrf_token(prepare_path)
+        }
+
+        # Click the "release" button
+        released_soup = bs(self.request(release_path, method='POST', data=data),
+                           features='lxml')
+        glsa_id = 'glsa-' + released_soup.find('strong').text.split()[1]
+
+        # Grab the xml
+        xml = self.request(xml_path)
+        xml_filename = '{}.xml'.format(glsa_id)
+        xml_path = os.path.join(self.glsa_path, xml_filename)
+
+        # Write and (TODO) commit it
+        with open(xml_path, 'w') as f:
+            f.write(xml)
+        print("Wrote {}".format(xml_filename))
+
+        # Grab the mail text
+        txt = self.request(txt_path)
+        txt_filename = '{}.txt'.format(glsa_id)
+
+        # Write it
+        with open(txt_filename, 'w') as f:
+            f.write('From: {}\n'.format(self.from_str))
+            f.write('Reply-To: security@gentoo.org\n')
+            f.write(txt)
+        print("Wrote {}".format(txt_filename))
+
+        # TODO:
+        # Mail it
+        # Close bugs
+
     def new_whiteboard(self, old_whiteboard):
         regex = re.compile('[A-C~][0-4] \[.*\]')
         severity = old_whiteboard[:2]
@@ -78,7 +143,7 @@ class GLSATool:
             'access': 'public',
             'import_references': '1',
             'what': 'request',  # ???
-            'authenticity_token': self.get_csrf_token()
+            'authenticity_token': self.get_csrf_token('/glsas/new')
         }
         self.request('/glsas', method='POST', data=data)
         print("GLSA request filed")
@@ -104,10 +169,26 @@ def bgo_key():
 
 def glsatool():
     parser = argparse.ArgumentParser()
-    parser.add_argument('-b', '--bugs', required=True, nargs='+')
-    parser.add_argument('-t', '--title', required=True)
+    subparsers = parser.add_subparsers(dest='command')
+
+    new_parser = subparsers.add_parser('new')
+    new_parser.add_argument('-b', '--bugs', required=True, nargs='+')
+    new_parser.add_argument('-t', '--title', required=True)
+
+    release_parser = subparsers.add_parser('release')
+    release_parser.add_argument('-i', '--id')
+
     args = parser.parse_args()
     auth = glsamaker_key()
-    for bug in args.bugs:
-        CVETool(auth, 'dobug', [bug])
-    GLSATool(auth, bgo_key()).new_glsa(args.title, args.bugs)
+    gtool = GLSATool(auth, bgo_key())
+    if args.command == 'new':
+        for bug in args.bugs:
+            CVETool(auth, 'dobug', [bug])
+        gtool.new_glsa(args.title, args.bugs)
+    elif args.command == 'release':
+        if args.id:
+            gtool.release_glsa(num=args.id)
+        else:
+            gtool.release_glsa()
+    else:
+        print("No command given!")