text: import functools
  import getpass
  import grp
  import logging
  import os
  import random
  import re
  import shutil
  import subprocess
  import sys
  import tempfile
  
  import click
  
  from seamless.signer import Signer
  
  
  logger = logging.getLogger(__name__)
  LOG_FILE_PATH = '/var/log/seamless/seamless.log'
  USER_GROUP = 'seamless'
  
  key_file_format_re = re.compile(r'^(?P<algo>ssh-\w+)\s+(?P<key>\S+)\s+(?P<user>\S+)\s*')
  
  
  def system_setup():
      try:
          grp.getgrnam(USER_GROUP)
      except KeyError:
          print('group "{}" does not exist. creating.'.format(USER_GROUP))
          print(subprocess.check_output('addgroup {}'.format(USER_GROUP), shell=True))
      if not os.path.exists(LOG_FILE_PATH):
          print('log file {} does not exist. creating'.format(LOG_FILE_PATH))
          subprocess.check_output('''
              mkdir -p {log_dir};
              touch {log_file};
              chown -R root:{group} {log_dir};
              chmod 0750 {log_dir};
              chmod 0620 {log_file};
          '''.format(
              log_dir=os.path.dirname(LOG_FILE_PATH),
              log_file=LOG_FILE_PATH,
              group=USER_GROUP,
          ), shell=True)
  
  
  class Scope(object):
      def __init__(self, name):
          self.name = name
  
      @property
      def secret_file(self):
          return os.path.join(self.path, 'secret')
  
      @property
      def authorized_keys_file(self):
          return os.path.join(self.path, '.ssh/authorized_keys')
  
      @property
      def key_dir(self):
          return os.path.join(self.path, 'keys')
  
      @property
      def path(self):
          return os.path.expanduser('~{}'.format(self.name))
  
      def init(self, secret=None):
          system_setup()
          print("creating user {}, home={}".format(self.name, self.path))
          subprocess.check_output('useradd {name} --create-home --skel {skel} --comment "seamless user" --groups {group}'.format(
              name=self.name,
              skel=tempfile.mkdtemp(),
              group=USER_GROUP,
          ), shell=True)
          if not secret:
              secret = '%x' % random.getrandbits(256)
          with open(self.secret_file, 'w') as f:
              f.write(secret.strip())
          subprocess.check_output("""
              mkdir {ssh_dir};
              mkdir {key_dir};
              touch {key_file};
              chown -R {user}:{user} {home_dir};
              chmod 400 {secret_file};
              chmod 700 {ssh_dir}
          """.format(
              user=self.name,
              secret_file=self.secret_file,
              key_file=self.authorized_keys_file,
              home_dir=self.path,
              ssh_dir=os.path.join(self.path, '.ssh'),
              key_dir=self.key_dir,
          ), shell=True)
  
      def delete(self):
          group = grp.getgrnam(USER_GROUP)
          if self.name not in group.gr_mem:
              print("{} is not a member of group {}, aborting.".format(self.name, USER_GROUP))
              return
          subprocess.check_output('deluser {name} --remove-home'.format(self.name))
  
      def get_secret(self):
          with open(self.secret_file, 'r') as f:
              return f.read()
  
      def get_token(self, username):
          return Signer(self.get_secret()).sign(username)
  
      def add(self, keyfile, username=None):
          if not username:
              username = os.path.basename(keyfile)
          shutil.copyfile(keyfile, os.path.join(self.key_dir, username))
  
      def remove(self, username):
          raise NotImplementedError()
  
      def sync(self):
          lines = []
          for filename in os.listdir(self.key_dir):
              if filename.startswith('.'):
                  continue
              path = os.path.join(self.key_dir, filename)
              command = '{python} -m seamless.cli token {name} --user {user}'.format(python=sys.executable, name=self.name, user=filename)
              with open(path, 'r') as f:
                  key = f.read()
                  match = key_file_format_re.match(key)
                  if not match:
                      print('{} does not look like a valid ssh key, skipping.'.format(path))
                      continue
                  key = '{algo} {key} {user}'.format(**match.groupdict())
                  print("found key for {}".format(filename))
                  lines.append('command="{command}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {key}\n'.format(
                      command=command,
                      key=key.strip(),
                      user=filename,
                  ))
  
          with open(self.authorized_keys_file, 'w') as f:
              f.write('# autogenerated by seamless. do not edit.\n')
              for line in lines:
                  f.write(line)
          subprocess.check_output('chmod 400 {key_file}; chown {user}:{user} {key_file}'.format(user=self.name, key_file=self.authorized_keys_file), shell=True)
  
  
  def require_root(cmd):
      @functools.wraps(cmd)
      def wrapped_command(*args, **kwargs):
          if getpass.getuser() != 'root':
              print("must be root")
              sys.exit(1)
          return cmd(*args, **kwargs)
      return wrapped_command
  
  
  def print_version(ctx, param, value):
      from seamless import __version__
      print(__version__)
      ctx.exit()
  
  
  @click.group()
  @click.option('--version', is_flag=True, is_eager=True, expose_value=False, callback=print_version)
  def main():
      if os.path.exists(LOG_FILE_PATH):
          handler = logging.FileHandler(LOG_FILE_PATH)
          handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(message)s'))
          logger.addHandler(handler)
          logger.setLevel(logging.INFO)
      logger.info(' '.join(sys.argv))
  
  
  @main.command()
  @click.argument('name')
  @click.option('--secret')
  @require_root
  def init(name, secret):
      scope = Scope(name)
      scope.init(secret=secret)
  
  
  @main.command()
  @click.argument('name')
  @click.option('--user')
  def token(name, user):
      try:
          scope = Scope(name)
          print scope.get_token(user)
      except:
          # don't leak exceptions to clients
          logger.exception('token creation failed')
  
  
  @main.command()
  @click.argument('name')
  @require_root
  def sync(name):
      scope = Scope(name)
      scope.sync()
  
  
  @main.command()
  @click.argument('name')
  @click.argument('keyfile')
  @click.option('--user')
  @require_root
  def add(name, keyfile, user):
      scope = Scope(name)
      scope.add(keyfile, user)
      scope.sync()
  
  
  @main.command()
  @click.argument('name')
  @click.argument('user')
  @require_root
  def remove(name, user):
      scope = Scope(name)
      scope.remove(user)
      scope.sync()
  
  
  @main.command()
  @click.argument('name')
  @require_root
  def delete(name):
      scope = Scope(name)
      scope.delete()
  
  
  if __name__ == '__main__':
      main()
  