\n%s\n\n' \ 958 | '
\n%s\n\n' \ 959 | % (html_escape(repr(_e())), html_escape(format_exc())) 960 | environ['wsgi.errors'].write(err) 961 | headers = [('Content-Type', 'text/html; charset=UTF-8')] 962 | start_response('500 INTERNAL SERVER ERROR', headers, sys.exc_info()) 963 | return [tob(err)] 964 | 965 | def __call__(self, environ, start_response): 966 | ''' Each instance of :class:'Bottle' is a WSGI application. ''' 967 | return self.wsgi(environ, start_response) 968 | 969 | def __enter__(self): 970 | ''' Use this application as default for all module-level shortcuts. ''' 971 | default_app.push(self) 972 | return self 973 | 974 | def __exit__(self, exc_type, exc_value, traceback): 975 | default_app.pop() 976 | 977 | 978 | 979 | 980 | 981 | ############################################################################### 982 | # HTTP and WSGI Tools ########################################################## 983 | ############################################################################### 984 | 985 | class BaseRequest(object): 986 | """ A wrapper for WSGI environment dictionaries that adds a lot of 987 | convenient access methods and properties. Most of them are read-only. 988 | 989 | Adding new attributes to a request actually adds them to the environ 990 | dictionary (as 'bottle.request.ext.
Sorry, the requested URL {{repr(request.url)}} 3512 | caused an error:
3513 |{{e.body}}3514 | %%if DEBUG and e.exception: 3515 |
{{repr(e.exception)}}3517 | %%end 3518 | %%if DEBUG and e.traceback: 3519 |
{{e.traceback}}3521 | %%end 3522 | 3523 | 3524 | %%except ImportError: 3525 | ImportError: Could not generate the error page. Please add bottle to 3526 | the import path. 3527 | %%end 3528 | """ % __name__ 3529 | 3530 | #: A thread-safe instance of :class:`LocalRequest`. If accessed from within a 3531 | #: request callback, this instance always refers to the *current* request 3532 | #: (even on a multithreaded server). 3533 | request = LocalRequest() 3534 | 3535 | #: A thread-safe instance of :class:`LocalResponse`. It is used to change the 3536 | #: HTTP response for the *current* request. 3537 | response = LocalResponse() 3538 | 3539 | #: A thread-safe namespace. Not used by Bottle. 3540 | local = threading.local() 3541 | 3542 | # Initialize app stack (create first empty Bottle app) 3543 | # BC: 0.6.4 and needed for run() 3544 | app = default_app = AppStack() 3545 | app.push() 3546 | 3547 | #: A virtual package that redirects import statements. 3548 | #: Example: ``import bottle.ext.sqlite`` actually imports `bottle_sqlite`. 3549 | ext = _ImportRedirect('bottle.ext' if __name__ == '__main__' else __name__+".ext", 'bottle_%s').module 3550 | 3551 | if __name__ == '__main__': 3552 | opt, args, parser = _cmd_options, _cmd_args, _cmd_parser 3553 | if opt.version: 3554 | _stdout('Bottle %s\n'%__version__) 3555 | sys.exit(0) 3556 | if not args: 3557 | parser.print_help() 3558 | _stderr('\nError: No application specified.\n') 3559 | sys.exit(1) 3560 | 3561 | sys.path.insert(0, '.') 3562 | sys.modules.setdefault('bottle', sys.modules['__main__']) 3563 | 3564 | host, port = (opt.bind or 'localhost'), 8080 3565 | if ':' in host and host.rfind(']') < host.rfind(':'): 3566 | host, port = host.rsplit(':', 1) 3567 | host = host.strip('[]') 3568 | 3569 | run(args[0], host=host, port=int(port), server=opt.server, 3570 | reloader=opt.reload, plugins=opt.plugin, debug=opt.debug) 3571 | 3572 | 3573 | 3574 | 3575 | # THE END 3576 | -------------------------------------------------------------------------------- /metadata/otp.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import time 3 | import hmac 4 | import hashlib 5 | import base64 6 | 7 | class Totp(object): 8 | def __init__(self, secret, interval_secs=30, digits=6, digest=hashlib.sha1): 9 | """ 10 | Create a new TOTP code generator. 11 | 12 | Parameters: 13 | secret (string|list of byte): shared secret as either a base32 encoded string or byte array 14 | interval_secs (int): interval, in seconds, to generate codes at 15 | digits (int): number of digits in the generated codes 16 | digest (function): HMAC digest function to use 17 | """ 18 | if isinstance(secret, str): 19 | secret = secret_to_bytes(secret) 20 | 21 | self.secret = secret 22 | self.interval_secs = interval_secs 23 | self.digits = digits 24 | self.digest = digest 25 | 26 | def generate(self, at=None): 27 | """ 28 | Generate a new OTP code. 29 | 30 | Parameters: 31 | at (datetime): timestamp to generate the code for or None to use current time 32 | 33 | Returns: 34 | (int): generated code 35 | """ 36 | timecode = self.__timecode(at or datetime.now()) 37 | hmac_hash = hmac.new(self.secret, timecode, self.digest).digest() 38 | 39 | offset = ord(hmac_hash[19]) & 0xf 40 | code = ((ord(hmac_hash[offset]) & 0x7f) << 24 | 41 | (ord(hmac_hash[offset + 1]) & 0xff) << 16 | 42 | (ord(hmac_hash[offset + 2]) & 0xff) << 8 | 43 | (ord(hmac_hash[offset + 3]) & 0xff)) 44 | 45 | return code % 10 ** self.digits 46 | 47 | def __timecode(self, at): 48 | return timestamp_to_bytestring(int(time.mktime(at.timetuple()) / self.interval_secs)) 49 | 50 | def secret_to_bytes(secret): 51 | """Convert base32 encoded secret string to bytes""" 52 | return base64.b32decode(secret) 53 | 54 | def timestamp_to_bytestring(val, padding=8): 55 | """Convert Unix timestamp to bytes""" 56 | result = [] 57 | 58 | while val != 0: 59 | result.append(chr(val & 0xFF)) 60 | val = val >> 8 61 | 62 | return ''.join(reversed(result)).rjust(padding, '\0') 63 | -------------------------------------------------------------------------------- /metadata/prompt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | try: 5 | from tkinter import Tk, Label, Button, Entry, ACTIVE 6 | except: 7 | from Tkinter import Tk, Label, Button, Entry, ACTIVE 8 | 9 | root = Tk() 10 | root.wm_title("Enter MFA Token") 11 | 12 | Label(root, text="Token").pack() 13 | entry = Entry(root) 14 | entry.pack(padx=5) 15 | 16 | 17 | def done(): 18 | print(entry.get()) 19 | root.destroy() 20 | 21 | b = Button(root, text="OK", default=ACTIVE, command=done) 22 | b.pack(pady=5) 23 | 24 | entry.focus_force() 25 | root.bind('
Profile: {{profile_name}}
31 | %if session: 32 |Access Key | {{session.access_key}} |
Secret Key | ******* |
Session Token | ******* |
Expiration |
No session available
63 | %end 64 | 65 |94 | | Name | 95 |Access Key | 96 |Token Duration | 97 |Role ARN | 98 |Region | 99 |
---|---|---|---|---|---|
105 | | {{name}} | 106 |{{profile.access_key}} | 107 |{{profile.token_duration}} | 108 |{{profile.role_arn}} | 109 |{{profile.region}} | 110 |