public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/gentoo-keys:master commit in: gkeygen/, bin/
@ 2014-08-20  3:55 Brian Dolbec
  0 siblings, 0 replies; only message in thread
From: Brian Dolbec @ 2014-08-20  3:55 UTC (permalink / raw
  To: gentoo-commits

commit:     10dd9249bb181f0cc7fbb289a56cd5bcf58ea784
Author:     Pavlos Ratis <dastergon <AT> gentoo <DOT> org>
AuthorDate: Wed Jul 30 17:17:37 2014 +0000
Commit:     Brian Dolbec <brian.dolbec <AT> gmail <DOT> com>
CommitDate: Wed Jul 30 17:17:37 2014 +0000
URL:        http://sources.gentoo.org/gitweb/?p=proj/gentoo-keys.git;a=commit;h=10dd9249

 add gkey-gen implementation (GLEP 63 openPGP key generator)

 Developers and users are now able to create GLEP 63 based GPG keys

---
 bin/gkey-gen        |  52 +++++++++++++++++++++++
 gkeygen/__init__.py |   0
 gkeygen/actions.py  | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gkeygen/cli.py      | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 282 insertions(+)

diff --git a/bin/gkey-gen b/bin/gkey-gen
new file mode 100755
index 0000000..5b8ba10
--- /dev/null
+++ b/bin/gkey-gen
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+'''Gentoo-keys is a gpg key manager for managing
+ gentoo's gpg-signing keys.  It is these keys that are
+ used to verify and validate release media, etc..
+
+ Distributed under the terms of the GNU General Public License v2
+
+ Copyright:
+             (c) 2014 Pavlos Ratis
+             Distributed under the terms of the GNU General Public License v2
+
+ Author(s):
+             Pavlos Ratis <dastergon@gentoo.org>
+
+'''
+
+from __future__ import print_function
+
+import os
+import sys
+
+# This block ensures that ^C interrupts are handled quietly.
+try:
+    import signal
+
+    def exithandler(signum,frame):
+        signal.signal(signal.SIGINT, signal.SIG_IGN)
+        signal.signal(signal.SIGTERM, signal.SIG_IGN)
+        print()
+        sys.exit(1)
+
+    signal.signal(signal.SIGINT, exithandler)
+    signal.signal(signal.SIGTERM, exithandler)
+    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+except KeyboardInterrupt:
+    print()
+    sys.exit(1)
+
+
+from gkeygen.cli import Main
+
+root = None
+try:
+    root = os.environ['ROOT']
+except KeyError:
+    pass
+
+main = Main(root=root)
+main()

diff --git a/gkeygen/__init__.py b/gkeygen/__init__.py
new file mode 100644
index 0000000..e69de29

diff --git a/gkeygen/actions.py b/gkeygen/actions.py
new file mode 100644
index 0000000..80a8b25
--- /dev/null
+++ b/gkeygen/actions.py
@@ -0,0 +1,116 @@
+#
+#-*- coding:utf-8 -*-
+
+"""
+    Gentoo-Keys - gkeygen/actions.py
+
+    Primary API interface module
+    @copyright: 2014 by Pavlos Ratis <dastergon@gentoo.org>
+    @license: GNU GPL2, see COPYING for details
+"""
+
+import gpgme
+import os
+import re
+import shutil
+import urllib2
+
+from gkeys.fileops import ensure_dirs
+
+Available_Actions = ["genkey"]
+
+# temp link till we move it in api.g.o
+GPG_CONF = "https://dev.gentoo.org/~dastergon/glep63-gpg-conf.skel"
+
+# temp spec file till we move it in api.g.o
+SPEC = 'https://dev.gentoo.org/~dastergon/glep63.spec'
+
+class Actions(object):
+
+    def __init__(self, config, output=None, logger=None):
+        self.config = config
+        self.output = output
+        self.logger = logger
+
+    def genkey(self, args):
+        '''Key generation action'''
+        if not args.homedir:
+            gpghome = os.path.join(os.getcwd(), 'gpghome')
+        else:
+            if os.path.exists(args.homedir):
+                gpghome = os.path.join(args.homedir, 'gpghome')
+            else:
+                self.output("Aborting... %s path does not exist." % args.homedir)
+                return False
+        self.logger.debug("MAIN: _action_genkey; setting gpghome destination: %s" % gpghome)
+        self.logger.debug("MAIN: _action_genkey; args= %s" % str(args))
+        key_params = self.get_input()
+        ack = None
+        while ack not in ["y", "yes", "n", "no"]:
+            ack = raw_input("Continue?[y/n]: ").lower()
+        if ack in ["n", "no"]:
+            self.output("\nKey generation aborted.")
+            return False
+        elif ack in ["y", "yes"]:
+            # Set the environment to custom gpg directory
+            os.environ['GNUPGHOME'] = gpghome
+            gpghome_full_path = os.path.abspath(gpghome)
+            self.logger.info("MAIN: _action_genkey; create custom gpg directory: %s" % gpghome_full_path)
+            self.output("\n* Creating gpg folder at %s" % gpghome_full_path)
+            ensure_dirs(gpghome)
+            # Copy default gpg-conf.skel and append glep63 requirements
+            self.output("* Creating gpg.conf file at %s" % gpghome_full_path)
+            newgpgconfpath = os.path.join(gpghome, 'gpg.conf')
+            shutil.copy('/usr/share/gnupg/gpg-conf.skel', newgpgconfpath)
+            with open(newgpgconfpath, 'a') as conf:
+                for line in urllib2.urlopen(GPG_CONF):
+                    conf.write(line)
+            # Key generation
+            ctx = gpgme.Context()
+            self.logger.info("MAIN: _action_genkey: Generating GPG key...")
+            self.output("""
+    ____________________
+    < Generating GPG key >
+     --------------------
+            \   ^__^
+             \  (oo)\_______
+                (__)\       )\/
+                    ||----w |
+                    ||     ||""")
+            self.output("\n* Give the password for the key. (Pick a strong one)\n")
+            try:
+                result = ctx.genkey(key_params)
+            except gpgme.GpgmeError:
+                self.logger.debug("MAIN: _action_genkey: Aborting... No given password.")
+                self.output("Aborting... No given password.")
+                return False
+            key = ctx.get_key(result.fpr, True)
+            self.logger.debug("MAIN: _action_genkey: Generated key: %s - %s"
+                              % (key.uids[0].uid, key.subkeys[0].fpr))
+            self.output("Your new GLEP 63 based OpenPGP key has been created in %s" % gpghome_full_path)
+            self.output("""
+        GPG key info:
+            Full Name: %s,
+            Email: %s,
+            Fingerprint: %s
+                        """ % (key.uids[0].name, key.uids[0].email,
+                               key.subkeys[0].fpr))
+            self.output("In order to use your new key, place the new gpghome to your ~/.gnupg folder by running the following command:\n"
+                        "    mv %s ~/.gnupg\n"
+                        "Important: If you have another old key in ~/.gnupg please make sure you backup it up first.\n\n"
+                        "Please read the FAQ for post-generation steps that are available in: \n"
+                        "https://wiki.gentoo.org/wiki/Project:Gentoo-keys/Generating_GLEP_63_based_OpenPGP_keys\n" % gpghome_full_path)
+            return True
+
+    def get_input(self):
+        '''Interactive user input'''
+        self.output("\nGPG key creator based on GLEP 63\n"
+                    "(https://wiki.gentoo.org/wiki/GLEP:63)\n")
+        name = raw_input("Give your Full Name: ")
+        email = raw_input("Give your Email: ")
+        while not re.match(r'[\w.-]+@[\w.-]+', email):
+            self.output("\nBad email input. Try again.")
+            email = raw_input("Give your Email: ")
+        print("\nReview:\n Full Name: %s\n Email: %s\n" % (name, email))
+        key_properties = urllib2.urlopen(SPEC).read()
+        return key_properties.format(name, email)

diff --git a/gkeygen/cli.py b/gkeygen/cli.py
new file mode 100644
index 0000000..ca09899
--- /dev/null
+++ b/gkeygen/cli.py
@@ -0,0 +1,114 @@
+#
+#-*- coding:utf-8 -*-
+
+from __future__ import print_function
+
+
+import sys
+import argparse
+
+from gkeys.config import GKeysConfig
+from gkeys.log import log_levels, set_logger
+from gkeygen.actions import Actions, Available_Actions
+
+class Main(object):
+    '''Main command line interface class'''
+
+
+    def __init__(self, root=None, config=None, print_results=True):
+        """ Main class init function.
+
+        @param root: string, root path to use
+        @param config: optional GKeysConfig instance, For API use
+        @param print_results: optional boolean, for API use
+        """
+        self.root = root or "/"
+        self.config = config or GKeysConfig(root=root)
+        self.print_results = print_results
+        self.args = None
+
+
+    def __call__(self, args=None):
+        """Main class call function
+
+        @param args: Optional list of argumanets to parse and action to run
+                     Defaults to sys.argv[1:]
+        """
+        if args:
+            self.run(self.parse_args(args))
+        else:
+            self.run(self.parse_args(sys.argv[1:]))
+
+
+    def parse_args(self, args):
+        '''Parse a list of aruments
+
+        @param args: list
+        @returns argparse.Namespace object
+        '''
+        #logger.debug('MAIN: parse_args; args: %s' % args)
+        actions = Available_Actions
+        parser = argparse.ArgumentParser(
+            prog='gkeys-gen',
+            description='Gentoo Keys GPG key generator program',
+            epilog='''Caution: adding untrusted keys to these keyrings can
+                be hazardous to your system!''')
+        # actions
+        parser.add_argument('action', choices=actions, nargs='?',
+                            default='genkey', help='Generate GPG key based on GLEP 63')
+        # options
+        parser.add_argument('-c', '--config', dest='config', default=None,
+                            help='The path to an alternate config file')
+        parser.add_argument('-D', '--debug', default='DEBUG',
+                            choices=list(log_levels),
+                            help='The logging level to set for the logfile')
+        parser.add_argument('-H', '--homedir', dest='homedir', default=None,
+                            help='The destination for the generate key')
+        parser.add_argument('-m', '--mail', dest='mail', default=None,
+                            help='The email address to search for')
+        parser.add_argument('-n', '--nick', dest='nick', default=None,
+                            help='The nick or user id (uid) to search for')
+        parser.add_argument('-N', '--name', dest='name', default=None,
+                            help='The name to search for')
+        return parser.parse_args(args)
+
+
+    def run(self, args):
+        '''Run the args passed in
+
+        @param args: list or argparse.Namespace object
+        '''
+        global logger
+        message = None
+        if not args:
+            message = "Main: run; invalid args argument passed in"
+        if isinstance(args, list):
+            args = self.parse_args(args)
+        if args.config:
+            self.config.defaults['config'] = args.config
+        # now make it load the config file
+        self.config.read_config()
+
+        # establish our logger and update it in the imported files
+        logger = set_logger('gkeys-gen', self.config['logdir'], args.debug)
+        #config.logger = logger
+
+        if message:
+            logger.error(message)
+
+        # now that we have a logger, record the alternate config setting
+        if args.config:
+            logger.debug("Main: run; Found alternate config request: %s"
+                % args.config)
+
+        # establish our actions instance
+        self.actions = Actions(self.config, print, logger)
+
+        logger.info("Begin running action: %s" % args.action)
+
+        # run the action
+        func = getattr(self.actions, '%s' % args.action)
+
+        logger.debug('Main: run; Found action: %s' % args.action)
+        results = func(args)
+        return results


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2014-08-20  3:55 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-20  3:55 [gentoo-commits] proj/gentoo-keys:master commit in: gkeygen/, bin/ Brian Dolbec

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox