RPKI Engine 1.0
|
00001 """ 00002 Command line IR back-end control program for rpkid and pubd. 00003 00004 $Id: irbe_cli.py 3711 2011-03-03 14:01:23Z sra $ 00005 00006 Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") 00007 00008 Permission to use, copy, modify, and distribute this software for any 00009 purpose with or without fee is hereby granted, provided that the above 00010 copyright notice and this permission notice appear in all copies. 00011 00012 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 00013 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00014 AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 00015 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00016 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00017 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00018 PERFORMANCE OF THIS SOFTWARE. 00019 00020 Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") 00021 00022 Permission to use, copy, modify, and distribute this software for any 00023 purpose with or without fee is hereby granted, provided that the above 00024 copyright notice and this permission notice appear in all copies. 00025 00026 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH 00027 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00028 AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, 00029 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00030 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00031 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00032 PERFORMANCE OF THIS SOFTWARE. 00033 """ 00034 00035 import getopt, sys, textwrap 00036 import rpki.left_right, rpki.http, rpki.x509, rpki.config, rpki.log 00037 import rpki.publication, rpki.async 00038 00039 pem_out = None 00040 00041 class UsageWrapper(textwrap.TextWrapper): 00042 """ 00043 Call interface around Python textwrap.Textwrapper class. 00044 """ 00045 00046 def __call__(self, *args): 00047 """ 00048 Format arguments, with TextWrapper indentation. 00049 """ 00050 return self.fill(textwrap.dedent(" ".join(args))) 00051 00052 usage_fill = UsageWrapper(subsequent_indent = " " * 4) 00053 00054 class reply_elt_mixin(object): 00055 """ 00056 Protocol mix-in for printout of reply PDUs. 00057 """ 00058 00059 is_cmd = False 00060 00061 def client_reply_decode(self): 00062 pass 00063 00064 def client_reply_show(self): 00065 print self.element_name 00066 for i in self.attributes + self.elements: 00067 if getattr(self, i) is not None: 00068 print " %s: %s" % (i, getattr(self, i)) 00069 00070 class cmd_elt_mixin(reply_elt_mixin): 00071 """ 00072 Protocol mix-in for command line client element PDUs. 00073 """ 00074 00075 is_cmd = True 00076 00077 ## @var excludes 00078 # XML attributes and elements that should not be allowed as command 00079 # line arguments. 00080 excludes = () 00081 00082 @classmethod 00083 def usage(cls): 00084 """ 00085 Generate usage message for this PDU. 00086 """ 00087 args = " ".join("--" + x + "=" for x in cls.attributes + cls.elements if x not in cls.excludes) 00088 bools = " ".join("--" + x for x in cls.booleans) 00089 if args and bools: 00090 return args + " " + bools 00091 else: 00092 return args or bools 00093 00094 def client_getopt(self, argv): 00095 """ 00096 Parse options for this class. 00097 """ 00098 opts, argv = getopt.getopt(argv, "", [x + "=" for x in self.attributes + self.elements if x not in self.excludes] + list(self.booleans)) 00099 for o, a in opts: 00100 o = o[2:] 00101 handler = getattr(self, "client_query_" + o, None) 00102 if handler is not None: 00103 handler(a) 00104 elif o in self.booleans: 00105 setattr(self, o, True) 00106 else: 00107 assert o in self.attributes 00108 setattr(self, o, a) 00109 return argv 00110 00111 def client_query_bpki_cert(self, arg): 00112 """ 00113 Special handler for --bpki_cert option. 00114 """ 00115 self.bpki_cert = rpki.x509.X509(Auto_file = arg) 00116 00117 def client_query_glue(self, arg): 00118 """ 00119 Special handler for --bpki_glue option. 00120 """ 00121 self.bpki_glue = rpki.x509.X509(Auto_file = arg) 00122 00123 def client_query_bpki_cms_cert(self, arg): 00124 """ 00125 Special handler for --bpki_cms_cert option. 00126 """ 00127 self.bpki_cms_cert = rpki.x509.X509(Auto_file = arg) 00128 00129 def client_query_cms_glue(self, arg): 00130 """ 00131 Special handler for --bpki_cms_glue option. 00132 """ 00133 self.bpki_cms_glue = rpki.x509.X509(Auto_file = arg) 00134 00135 class cmd_msg_mixin(object): 00136 """ 00137 Protocol mix-in for command line client message PDUs. 00138 """ 00139 00140 @classmethod 00141 def usage(cls): 00142 """ 00143 Generate usage message for this PDU. 00144 """ 00145 for k, v in cls.pdus.items(): 00146 if v.is_cmd: 00147 print usage_fill(k, v.usage()) 00148 00149 # left-right protcol 00150 00151 class self_elt(cmd_elt_mixin, rpki.left_right.self_elt): 00152 pass 00153 00154 class bsc_elt(cmd_elt_mixin, rpki.left_right.bsc_elt): 00155 00156 excludes = ("pkcs10_request",) 00157 00158 def client_query_signing_cert(self, arg): 00159 """--signing_cert option.""" 00160 self.signing_cert = rpki.x509.X509(Auto_file = arg) 00161 00162 def client_query_signing_cert_crl(self, arg): 00163 """--signing_cert_crl option.""" 00164 self.signing_cert_crl = rpki.x509.CRL(Auto_file = arg) 00165 00166 def client_reply_decode(self): 00167 global pem_out 00168 if pem_out is not None and self.pkcs10_request is not None: 00169 if isinstance(pem_out, str): 00170 pem_out = open(pem_out, "w") 00171 pem_out.write(self.pkcs10_request.get_PEM()) 00172 00173 class parent_elt(cmd_elt_mixin, rpki.left_right.parent_elt): 00174 pass 00175 00176 class child_elt(cmd_elt_mixin, rpki.left_right.child_elt): 00177 pass 00178 00179 class repository_elt(cmd_elt_mixin, rpki.left_right.repository_elt): 00180 pass 00181 00182 class list_published_objects_elt(cmd_elt_mixin, rpki.left_right.list_published_objects_elt): 00183 excludes = ("uri",) 00184 00185 class list_received_resources_elt(cmd_elt_mixin, rpki.left_right.list_received_resources_elt): 00186 excludes = ("parent_handle", "notBefore", "notAfter", "uri", "sia_uri", "aia_uri", "asn", "ipv4", "ipv6") 00187 00188 class report_error_elt(reply_elt_mixin, rpki.left_right.report_error_elt): 00189 pass 00190 00191 class left_right_msg(cmd_msg_mixin, rpki.left_right.msg): 00192 pdus = dict((x.element_name, x) 00193 for x in (self_elt, bsc_elt, parent_elt, child_elt, repository_elt, 00194 list_published_objects_elt, list_received_resources_elt, report_error_elt)) 00195 00196 class left_right_sax_handler(rpki.left_right.sax_handler): 00197 pdu = left_right_msg 00198 00199 class left_right_cms_msg(rpki.left_right.cms_msg): 00200 saxify = left_right_sax_handler.saxify 00201 00202 # Publication protocol 00203 00204 class config_elt(cmd_elt_mixin, rpki.publication.config_elt): 00205 00206 def client_query_bpki_crl(self, arg): 00207 """ 00208 Special handler for --bpki_crl option. 00209 """ 00210 self.bpki_crl = rpki.x509.CRL(Auto_file = arg) 00211 00212 class client_elt(cmd_elt_mixin, rpki.publication.client_elt): 00213 pass 00214 00215 class certificate_elt(cmd_elt_mixin, rpki.publication.certificate_elt): 00216 pass 00217 00218 class crl_elt(cmd_elt_mixin, rpki.publication.crl_elt): 00219 pass 00220 00221 class manifest_elt(cmd_elt_mixin, rpki.publication.manifest_elt): 00222 pass 00223 00224 class roa_elt(cmd_elt_mixin, rpki.publication.roa_elt): 00225 pass 00226 00227 class report_error_elt(reply_elt_mixin, rpki.publication.report_error_elt): 00228 pass 00229 00230 class publication_msg(cmd_msg_mixin, rpki.publication.msg): 00231 pdus = dict((x.element_name, x) 00232 for x in (config_elt, client_elt, certificate_elt, crl_elt, manifest_elt, roa_elt, report_error_elt)) 00233 00234 class publication_sax_handler(rpki.publication.sax_handler): 00235 pdu = publication_msg 00236 00237 class publication_cms_msg(rpki.publication.cms_msg): 00238 saxify = publication_sax_handler.saxify 00239 00240 # Usage 00241 00242 top_opts = ["config=", "help", "pem_out=", "quiet", "verbose"] 00243 00244 def usage(code = 1): 00245 if __doc__ is not None: 00246 print __doc__.strip() 00247 print 00248 print "Usage:" 00249 print 00250 print "# Top-level options:" 00251 print usage_fill(*["--" + x for x in top_opts]) 00252 print 00253 print "# left-right protocol:" 00254 left_right_msg.usage() 00255 print 00256 print "# publication protocol:" 00257 publication_msg.usage() 00258 sys.exit(code) 00259 00260 # Main program 00261 00262 rpki.log.init("irbe_cli") 00263 00264 argv = sys.argv[1:] 00265 00266 if not argv: 00267 usage(0) 00268 00269 cfg_file = None 00270 verbose = True 00271 00272 opts, argv = getopt.getopt(argv, "c:hpqv?", top_opts) 00273 for o, a in opts: 00274 if o in ("-?", "-h", "--help"): 00275 usage(0) 00276 elif o in ("-c", "--config"): 00277 cfg_file = a 00278 elif o in ("-p", "--pem_out"): 00279 pem_out = a 00280 elif o in ("-q", "--quiet"): 00281 verbose = False 00282 elif o in ("-v", "--verbose"): 00283 verbose = True 00284 00285 if not argv: 00286 usage(1) 00287 00288 cfg = rpki.config.parser(cfg_file, "irbe_cli") 00289 00290 q_msg_left_right = [] 00291 q_msg_publication = [] 00292 00293 while argv: 00294 if argv[0] in left_right_msg.pdus: 00295 q_pdu = left_right_msg.pdus[argv[0]]() 00296 q_msg = q_msg_left_right 00297 elif argv[0] in publication_msg.pdus: 00298 q_pdu = publication_msg.pdus[argv[0]]() 00299 q_msg = q_msg_publication 00300 else: 00301 usage(1) 00302 argv = q_pdu.client_getopt(argv[1:]) 00303 q_msg.append(q_pdu) 00304 00305 if q_msg_left_right: 00306 00307 class left_right_proto(object): 00308 cms_msg = left_right_cms_msg 00309 msg = left_right_msg 00310 00311 call_rpkid = rpki.async.sync_wrapper(rpki.http.caller( 00312 proto = left_right_proto, 00313 client_key = rpki.x509.RSA( Auto_file = cfg.get("rpkid-irbe-key")), 00314 client_cert = rpki.x509.X509(Auto_file = cfg.get("rpkid-irbe-cert")), 00315 server_ta = rpki.x509.X509(Auto_file = cfg.get("rpkid-bpki-ta")), 00316 server_cert = rpki.x509.X509(Auto_file = cfg.get("rpkid-cert")), 00317 url = cfg.get("rpkid-url"), 00318 debug = verbose)) 00319 00320 call_rpkid(*q_msg_left_right) 00321 00322 if q_msg_publication: 00323 00324 class publication_proto(object): 00325 msg = publication_msg 00326 cms_msg = publication_cms_msg 00327 00328 call_pubd = rpki.async.sync_wrapper(rpki.http.caller( 00329 proto = publication_proto, 00330 client_key = rpki.x509.RSA( Auto_file = cfg.get("pubd-irbe-key")), 00331 client_cert = rpki.x509.X509(Auto_file = cfg.get("pubd-irbe-cert")), 00332 server_ta = rpki.x509.X509(Auto_file = cfg.get("pubd-bpki-ta")), 00333 server_cert = rpki.x509.X509(Auto_file = cfg.get("pubd-cert")), 00334 url = cfg.get("pubd-url")), 00335 debug = verbose) 00336 00337 call_pubd(*q_msg_publication)