Exemplo n.º 1
0
  def AddAccountsFromDatabase(self, account_db_path):
    """Add accounts from the database at |account_db_path| to self.

    Overrides previously loaded accounts.

    Args:
      account_db_path: path to file containing an account database.
    """
    raw_db = json_lib.ParseJsonFileWithComments(account_db_path)
    json_lib.AssertIsInstance(raw_db, dict, 'accounts database')

    # We don't mandate that an accounts database specify either field.
    raw_db.setdefault(USERS_KEY, [])
    raw_db.setdefault(GROUPS_KEY, [])
    user_list = json_lib.PopValueOfType(raw_db, USERS_KEY, list,
                                        'list of users in accounts database')
    group_list = json_lib.PopValueOfType(raw_db, GROUPS_KEY, list,
                                         'list of groups in accounts database')

    # We do mandate that the database contain only fields we know about.
    if raw_db:
      raise ValueError('Accounts database include unknown fields: %r' %
                       raw_db.keys())

    for user in user_list:
      json_lib.AssertIsInstance(
          user, dict, 'user specification in accounts database')
      self._AddUser(user)

    for group in group_list:
      json_lib.AssertIsInstance(
          group, dict, 'group specification in accounts database')
      self._AddGroup(group)
    def _AddUser(self, user_spec):
        """Add a user to this account database based on |user_spec|.

    Args:
      user_spec: dict of information from an accounts database.
          This fragment is expected to have been parsed from
          developer supplied JSON and will be type checked.
    """
        # By default, user accounts are locked and cannot be logged into.
        user_spec.setdefault(USER_PASSWORD_KEY, u'!')
        # By default, users don't get a shell.
        user_spec.setdefault(USER_SHELL_KEY, u'/bin/false')
        # By default, users don't get a home directory.
        user_spec.setdefault(USER_HOME_KEY, u'/dev/null')
        # By default, users don't get a fixed UID.
        user_spec.setdefault(USER_FIXED_ID_KEY, False)
        # By default, users don't need a comment.
        user_spec.setdefault(USER_COMMENT_KEY, u'')
        # By default, users are not defunct.
        user_spec.setdefault(USER_DEFUNCT_KEY, False)

        name = json_lib.PopValueOfType(user_spec, USER_NAME_KEY, six.text_type,
                                       'username from user spec')
        password = json_lib.PopValueOfType(user_spec, USER_PASSWORD_KEY,
                                           six.string_types,
                                           'password for user %s' % name)
        uid = json_lib.PopValueOfType(user_spec, USER_ID_KEY, int,
                                      'default uid for user %s' % name)
        group_name = json_lib.PopValueOfType(
            user_spec, USER_GROUP_KEY, six.text_type,
            'primary group for user %s' % name)
        description = json_lib.PopValueOfType(user_spec, USER_COMMENT_KEY,
                                              six.text_type,
                                              'description for user %s' % name)
        home = json_lib.PopValueOfType(user_spec, USER_HOME_KEY, six.text_type,
                                       'home directory for user %s' % name)
        shell = json_lib.PopValueOfType(user_spec, USER_SHELL_KEY,
                                        six.text_type,
                                        'shell for user %s' % name)
        is_fixed_id = json_lib.PopValueOfType(
            user_spec, USER_FIXED_ID_KEY, bool,
            'whether UID for user %s is fixed' % name)
        is_defunct = json_lib.PopValueOfType(
            user_spec, USER_DEFUNCT_KEY, bool,
            'whether user %s is defunct.' % name)

        if user_spec:
            raise ValueError('Unexpected keys in user spec for user %s: %r' %
                             (name, user_spec.keys()))

        self.users[name] = User(name=name,
                                password=password,
                                uid=uid,
                                group_name=group_name,
                                description=description,
                                home=home,
                                shell=shell,
                                is_fixed_id=is_fixed_id,
                                is_defunct=is_defunct)
Exemplo n.º 3
0
 def testPopValueOfType(self):
   """Test that PopValueOfType is correct."""
   input_dict = {'key': 'value'}
   self.assertEqual(
       'value',
       json_lib.GetValueOfType(input_dict, 'key', str, 'value'))
   self.assertEqual(
       'value',
       json_lib.PopValueOfType(input_dict, 'key', str, 'value'))
   self.assertFalse(input_dict)
    def _AddGroup(self, group_spec):
        """Add a group to this account database based on |group_spec|.

    Args:
      group_spec: dict of information from an accounts database.
          This fragment is expected to have been parsed from
          developer supplied JSON and will be type checked.
    """
        # By default, groups don't get a fixed GID.
        group_spec.setdefault(GROUP_FIXED_ID_KEY, False)
        # By default, groups don't get a password.
        group_spec.setdefault(GROUP_PASSWORD_KEY, u'!')
        # By default, groups are not defunct.
        group_spec.setdefault(GROUP_DEFUNCT_KEY, False)

        name = json_lib.PopValueOfType(group_spec, GROUP_NAME_KEY,
                                       six.text_type,
                                       'groupname from group spec')
        password = json_lib.PopValueOfType(group_spec, GROUP_PASSWORD_KEY,
                                           six.text_type,
                                           'password for group %s' % name)
        gid = json_lib.PopValueOfType(group_spec, GROUP_ID_KEY, int,
                                      'gid for group %s' % name)
        users = json_lib.PopValueOfType(group_spec, GROUP_USERS_KEY, list,
                                        'users in group %s' % name)
        is_fixed_id = json_lib.PopValueOfType(
            group_spec, GROUP_FIXED_ID_KEY, bool,
            'whether GID for group %s is fixed' % name)
        is_defunct = json_lib.PopValueOfType(
            group_spec, GROUP_DEFUNCT_KEY, bool,
            'whether group %s is defunct' % name)

        for username in users:
            json_lib.AssertIsInstance(username, six.text_type,
                                      'user in group %s' % name)

        if group_spec:
            raise ValueError('Unexpected keys in group spec for group %s: %r' %
                             (name, group_spec.keys()))

        self.groups[name] = Group(name=name,
                                  password=password,
                                  gid=gid,
                                  users=users,
                                  is_fixed_id=is_fixed_id,
                                  is_defunct=is_defunct)
Exemplo n.º 5
0
def _GetPortList(desired_protocol, appc_port_list):
  """Get the list of ports opened for |desired_protocol| from |appc_port_list|.

  Args:
    desired_protocol: one of VALID_PROTOCOLS.
    appc_port_list: list of port specifications from a appc pod manifest.

  Returns:
    Instance of PortSpec.
  """
  # The port specification is optional.
  if appc_port_list is None:
    return PortSpec(False, [])

  json_lib.AssertIsInstance(appc_port_list, list, 'port specification list')

  allow_all = False
  port_list = []
  for port_dict in appc_port_list:
    json_lib.AssertIsInstance(port_dict, dict, 'port specification')
    port_dict = copy.deepcopy(port_dict)

    # By default, we open a single specified port.
    port_dict.setdefault(PORT_SPEC_COUNT, 1)
    # By default, don't set socket activated.
    port_dict.setdefault(PORT_SPEC_SOCKET_ACTIVATED, False)

    # We don't actually use the port name, but it's handy for documentation
    # and standard adherence to enforce its existence.
    port_name = json_lib.PopValueOfType(
        port_dict, PORT_SPEC_NAME, unicode, 'port name')
    logging.debug('Validating appc specifcation of "%s"', port_name)
    port = json_lib.PopValueOfType(port_dict, PORT_SPEC_PORT, int, 'port')
    protocol = json_lib.PopValueOfType(
        port_dict, PORT_SPEC_PROTOCOL, unicode, 'protocol')

    count = json_lib.PopValueOfType(
        port_dict, PORT_SPEC_COUNT, int, 'port range count')

    # We also don't use the socketActivated flag, but we should tolerate safe
    # values.
    socket_activated = json_lib.PopValueOfType(
        port_dict, PORT_SPEC_SOCKET_ACTIVATED, bool, 'socket activated flag')

    # Validate everything before acting on it.
    if protocol not in VALID_PROTOCOLS:
      raise ValueError('Port protocol must be in %r, not "%s"' %
                       (VALID_PROTOCOLS, protocol))
    if protocol != desired_protocol:
      continue

    if socket_activated != False:
      raise ValueError('No support for socketActivated==True in %s' % port_name)

    if port_dict:
      raise ValueError('Unknown keys found in port spec %s: %r' %
                       (port_name, port_dict.keys()))

    if port == -1:
      # Remember that we're going to return that all ports are opened, but
      # continue validating all the remaining specifications.
      allow_all = True
      continue

    # Now we know it's not the wildcard port, and that we've never declared
    # a wildcard for this protocol.
    port = remote_access.NormalizePort(port)

    if count < 1:
      raise ValueError('May only specify positive port ranges for %s' %
                       port_name)
    if port + count >= 65536:
      raise ValueError('Port range extends past max port number for %s' %
                       port_name)

    for effective_port in xrange(port, port + count):
      port_list.append(effective_port)

  return PortSpec(allow_all, port_list)