Initial commit of an ldap search and seed file creation tool.
[gentoo-keys.git] / gkeyldap / cli.py
1 #!/usr/bin/env python
2
3 from __future__ import print_function
4
5 import ldap
6 import sys
7 import os
8 import argparse
9
10 from gkeys.log import logger
11 from gkeys.config import GKeysConfig, GKEY
12 from gkeys.seed import Seeds
13 from gkeyldap.search import (LdapSearch, UID, CN, STATUS, GPGKEY,
14     MAIL, GPGFINGERPRINT, gkey2ldap_map, gkey2SEARCH)
15
16
17 # set debug level to max
18 logger.setLevel(1)
19
20
21 class Main(object):
22     '''Main command line interface class'''
23
24
25     def __init__(self, root=None, config=None, print_results=True):
26         """ Main class init function.
27
28         @param root: string, root path to use
29         """
30         self.root = root or "/"
31         self.config = config or GKeysConfig(root=root)
32         self.print_results = print_results
33         self.args = None
34         self.seeds = None
35
36
37     def __call__(self, args=None):
38         logger.debug("Main:__call__()")
39         if args:
40             self.run(self.parse_args(args))
41         else:
42             self.run(self.parse_args(sys.argv[1:]))
43
44
45     def parse_args(self, args):
46         '''Parse a list of aruments
47
48         @param args: list
49         @returns argparse.Namespace object
50         '''
51         logger.debug('args: %s' % args)
52         actions = ['ldapsearch', 'updateseeds']
53         parser = argparse.ArgumentParser(
54             prog='gkeys',
55             description='Gentoo-keys manager program',
56             epilog='''Caution: adding untrusted keys to these keyrings can
57                 be hazardous to your system!''')
58         # actions
59         parser.add_argument('action', choices=actions, nargs='?',
60             default='ldapsearch', help='Search ldap or update the seed file')
61         # options
62         parser.add_argument('-c', '--config', dest='config', default=None,
63             help='The path to an alternate config file')
64         parser.add_argument('-d', '--dest', dest='destination', default=None,
65             help='The destination db file path')
66         parser.add_argument('-N', '--name', dest='name', default=None,
67             help='The name to search for')
68         parser.add_argument('-n', '--nick', dest='nick', default=None,
69             help='The nick or user id (uid) to search for')
70         parser.add_argument('-m', '--mail', dest='mail', default=None,
71             help='The email address to search for')
72         parser.add_argument('-k', '--keyid', dest='keyid', default=None,
73             help='The gpg keyid to search for')
74         parser.add_argument('-f', '--fingerprint', dest='fingerprint', default=None,
75             help='The gpg fingerprint to search for')
76         parser.add_argument('-S', '--status', default=False,
77             help='The seedfile path to use')
78
79         return parser.parse_args(args)
80
81
82     def run(self, args):
83         '''Run the args passed in
84
85         @param args: list or argparse.Namespace object
86         '''
87         if not args:
88             logger.error("Main.run() invalid args argument passed in")
89         if isinstance(args, list):
90             args = self.parse_args(args)
91         if args.config:
92             logger.debug("Found alternate config request: %s" % args.config)
93             self.config.defaults['config'] = args.config
94         # now make it load the config file
95         self.config.read_config()
96
97         func = getattr(self, '_action_%s' % args.action)
98         logger.debug('Found action: %s' % args.action)
99         results = func(args)
100
101
102     def _action_ldapsearch(self, args):
103         l = LdapSearch()
104         if not l.connect():
105             print("Aborting Search...Connection failed")
106             return False
107         logging.debug("args = %s" % str(args))
108         x, target, search_field = self.get_args(args)
109         results = l.search(target, search_field)
110         devs = l.result2dict(results, gkey2ldap_map[x])
111         for dev in sorted(devs):
112             print(dev, devs[dev])
113         print("============================================")
114         print "Total number of devs in results:", len(devs)
115         return True
116
117
118     def _action_updateseeds(self, args):
119         l = LdapSearch()
120         if not l.connect():
121             print("Aborting Update...Connection failed")
122             return False
123         results = l.search('*', UID)
124         info = l.result2dict(results, 'uid')
125         logger.debug("_action_updateseeds, got results :) converted to info")
126         if not self.create_seedfile(info):
127             logger.error("Dev seed file update failure: "
128                 "Original seed file is intact & untouched.")
129         old = self.config['dev-seedfile'] + '.old'
130         try:
131             if os.path.exists(old):
132                 logger.debug("Removing 'old' seed file: %s" % old)
133                 os.unlink(old)
134             if os.path.exists(self.config['dev-seedfile']):
135                 logger.debug("Renaming current seed file to: %s" % old)
136                 os.rename(self.config['dev-seedfile'], old)
137             logger.debug("Renaming 'new' seed file to: %s" % self.config['dev-seedfile'])
138             os.rename(self.config['dev-seedfile'] + '.new',
139                 self.config['dev-seedfile'])
140         except IOError:
141             raise
142         print("Developer Seed file updated")
143         return True
144
145
146     def create_seedfile(self, devs):
147         logger.debug("create_seedfile, arrived")
148         filename = self.config['dev-seedfile'] + '.new'
149         self.seeds = Seeds(filename)
150         for dev in devs:
151             logger.debug("create_seedfile, dev = %s, %s" % (str(dev), str(devs[dev])))
152             new_gkey = GKEY._make(self.build_gkeylist(devs[dev]))
153             self.seeds.add(new_gkey)
154         logger.debug("create_seedfile, seeds created...saving file: %s" % filename)
155         return self.seeds.save()
156
157
158     @staticmethod
159     def get_args(args):
160         for x in ['nick', 'name', 'gpgkey', 'fingerprint', 'status']:
161             if x:
162                 target = getattr(args, x)
163                 search_field = gkey2SEARCH[x]
164                 break
165         return (x, target, search_field)
166
167
168
169     @staticmethod
170     def build_gkeydict(info):
171         keyinfo = {}
172         for x in GKEY._fields:
173             field = gkey2ldap_map[x]
174             if not field:
175                 continue
176             try:
177                 values = info[field]
178                 if values and values in ['uid' ]:
179                     value = values[0]
180                 else:
181                     value = values
182                 if value:
183                     keyinfo[x] = value
184             except KeyError:
185                 pass
186         return keyinfo
187
188
189     @staticmethod
190     def build_gkeylist(info):
191         keyinfo = []
192         logger.debug("build_gkeylist, info = %s" % str(info))
193         for x in GKEY._fields:
194             field = gkey2ldap_map[x]
195             if not field:
196                 keyinfo.append(None)
197                 continue
198             try:
199                 values = info[field]
200                 if values and field in ['uid', 'name' ]:
201                     value = values[0]
202                 else:
203                     value = values
204                 keyinfo.append(value)
205             except KeyError:
206                 keyinfo.append(None)
207         return keyinfo
208
209
210 if __name__ == '__main__':
211
212     Main()
213
214
215