White-listing of captured environment variables

This commit is contained in:
Marcin Kulik
2017-09-16 22:18:24 +02:00
parent 9010650330
commit 5f2849a7a0
6 changed files with 27 additions and 9 deletions

View File

@@ -211,6 +211,7 @@ available options set:
[record] [record]
command = /bin/bash -l command = /bin/bash -l
env = SHELL,TERM,USER
maxwait = 2 maxwait = 2
yes = true yes = true
quiet = true quiet = true

View File

@@ -22,7 +22,7 @@ def positive_float(value):
def rec_command(args, config): def rec_command(args, config):
api = Api(config.api_url, os.environ.get("USER"), config.api_token) api = Api(config.api_url, os.environ.get("USER"), config.api_token)
return RecordCommand(api, args.filename, args.command, args.title, args.yes, args.quiet, args.max_wait) return RecordCommand(api, args.filename, args.command, args.env, args.title, args.yes, args.quiet, args.max_wait)
def play_command(args, config): def play_command(args, config):
@@ -78,6 +78,7 @@ For help on a specific command run:
# create the parser for the "rec" command # create the parser for the "rec" command
parser_rec = subparsers.add_parser('rec', help='Record terminal session') parser_rec = subparsers.add_parser('rec', help='Record terminal session')
parser_rec.add_argument('-c', '--command', help='command to record, defaults to $SHELL', default=cfg.record_command) parser_rec.add_argument('-c', '--command', help='command to record, defaults to $SHELL', default=cfg.record_command)
parser_rec.add_argument('-e', '--env', help='list of environment variables to capture, defaults to ' + config.DEFAULT_RECORD_ENV, default=cfg.record_env)
parser_rec.add_argument('-t', '--title', help='title of the asciicast') parser_rec.add_argument('-t', '--title', help='title of the asciicast')
parser_rec.add_argument('-w', '--max-wait', help='limit recorded terminal inactivity to max <sec> seconds (can be fractional)', type=positive_float, default=maybe_str(cfg.record_max_wait)) parser_rec.add_argument('-w', '--max-wait', help='limit recorded terminal inactivity to max <sec> seconds (can be fractional)', type=positive_float, default=maybe_str(cfg.record_max_wait))
parser_rec.add_argument('-y', '--yes', help='answer "yes" to all prompts (e.g. upload confirmation)', action='store_true', default=cfg.record_yes) parser_rec.add_argument('-y', '--yes', help='answer "yes" to all prompts (e.g. upload confirmation)', action='store_true', default=cfg.record_yes)

View File

@@ -80,24 +80,24 @@ class Recorder:
self.pty_recorder = pty_recorder if pty_recorder is not None else PtyRecorder() self.pty_recorder = pty_recorder if pty_recorder is not None else PtyRecorder()
self.env = env if env is not None else os.environ self.env = env if env is not None else os.environ
def record(self, path, user_command, title, max_wait): def record(self, path, user_command, env_whitelist, title, max_wait):
cols = int(subprocess.check_output(['tput', 'cols'])) cols = int(subprocess.check_output(['tput', 'cols']))
lines = int(subprocess.check_output(['tput', 'lines'])) lines = int(subprocess.check_output(['tput', 'lines']))
saved_env = { vars = filter(None, map((lambda var: var.strip()), env_whitelist.split(',')))
'TERM': self.env.get('TERM'), captured_env = {var: self.env.get(var) for var in vars}
'SHELL': self.env.get('SHELL')
}
header = { header = {
'version': 2, 'version': 2,
'width': cols, 'width': cols,
'height': lines, 'height': lines,
'timestamp': int(time.time()), 'timestamp': int(time.time()),
'env': saved_env,
# TODO save max_wait here # TODO save max_wait here
} }
if captured_env:
header['env'] = captured_env
if title: if title:
header['title'] = title header['title'] = title

View File

@@ -9,11 +9,12 @@ from asciinema.api import APIError
class RecordCommand(Command): class RecordCommand(Command):
def __init__(self, api, filename, command, title, assume_yes, quiet, max_wait, recorder=None): def __init__(self, api, filename, command, env_whitelist, title, assume_yes, quiet, max_wait, recorder=None):
Command.__init__(self, quiet) Command.__init__(self, quiet)
self.api = api self.api = api
self.filename = filename self.filename = filename
self.command = command self.command = command
self.env_whitelist = env_whitelist
self.title = title self.title = title
self.assume_yes = assume_yes or quiet self.assume_yes = assume_yes or quiet
self.max_wait = max_wait self.max_wait = max_wait
@@ -36,7 +37,7 @@ class RecordCommand(Command):
self.print_info("Asciicast recording started.") self.print_info("Asciicast recording started.")
self.print_info("""Hit Ctrl-D or type "exit" to finish.""") self.print_info("""Hit Ctrl-D or type "exit" to finish.""")
self.recorder.record(self.filename, self.command, self.title, self.max_wait) self.recorder.record(self.filename, self.command, self.env_whitelist, self.title, self.max_wait)
self.print_info("Asciicast recording finished.") self.print_info("Asciicast recording finished.")

View File

@@ -10,6 +10,7 @@ class ConfigError(Exception):
DEFAULT_API_URL = 'https://asciinema.org' DEFAULT_API_URL = 'https://asciinema.org'
DEFAULT_RECORD_ENV = 'SHELL,TERM'
class Config: class Config:
@@ -39,6 +40,10 @@ class Config:
def record_command(self): def record_command(self):
return self.config.get('record', 'command', fallback=None) return self.config.get('record', 'command', fallback=None)
@property
def record_env(self):
return self.config.get('record', 'env', fallback=DEFAULT_RECORD_ENV)
@property @property
def record_max_wait(self): def record_max_wait(self):
return self.config.getfloat('record', 'maxwait', fallback=None) return self.config.getfloat('record', 'maxwait', fallback=None)

View File

@@ -40,6 +40,11 @@ def test_default_record_command():
assert_equal(None, config.record_command) assert_equal(None, config.record_command)
def test_default_record_env():
config = create_config('')
assert_equal('SHELL,TERM', config.record_env)
def test_default_record_max_wait(): def test_default_record_max_wait():
config = create_config('') config = create_config('')
assert_equal(None, config.record_max_wait) assert_equal(None, config.record_max_wait)
@@ -102,6 +107,11 @@ def test_record_command():
assert_equal(command, config.record_command) assert_equal(command, config.record_command)
def test_record_env():
config = create_config("[record]\nenv = FOO,BAR")
assert_equal('FOO,BAR', config.record_env)
def test_record_max_wait(): def test_record_max_wait():
max_wait = '2.35' max_wait = '2.35'
config = create_config("[record]\nmaxwait = %s" % max_wait) config = create_config("[record]\nmaxwait = %s" % max_wait)