def parse(self):
        """
        Parse the config and return a dict with the parsed values.

        :rtype: ``dict``
        """
        result = defaultdict(dict)

        if not os.path.isfile(self.config_file_path):
            # Config doesn't exist, return the default values
            return CONFIG_DEFAULT_VALUES

        config_dir_path = os.path.dirname(self.config_file_path)

        if self.validate_config_permissions:
            # Make sure the directory permissions == 0o770
            if bool(os.stat(config_dir_path).st_mode & 0o7):
                self.LOG.warning(
                    "The StackStorm configuration directory permissions are "
                    "insecure (too permissive): others have access."
                )

            # Make sure the setgid bit is set on the directory
            if not bool(os.stat(config_dir_path).st_mode & 0o2000):
                self.LOG.info(
                    "The SGID bit is not set on the StackStorm configuration "
                    "directory."
                )

            # Make sure the file permissions == 0o660
            if bool(os.stat(self.config_file_path).st_mode & 0o7):
                self.LOG.warning(
                    "The StackStorm configuration file permissions are "
                    "insecure: others have access."
                )

        config = ConfigParser()
        with io.open(self.config_file_path, "r", encoding="utf8") as fp:
            config.read_file(fp)
        for section, keys in six.iteritems(CONFIG_FILE_OPTIONS):
            for key, options in six.iteritems(keys):
                key_type = options["type"]
                key_default_value = options["default"]

                if config.has_option(section, key):
                    if key_type in ["str", "string"]:
                        get_func = config.get
                    elif key_type in ["int", "integer"]:
                        get_func = config.getint
                    elif key_type in ["float"]:
                        get_func = config.getfloat
                    elif key_type in ["bool", "boolean"]:
                        get_func = config.getboolean
                    else:
                        msg = 'Invalid type "%s" for option "%s"' % (key_type, key)
                        raise ValueError(msg)

                    value = get_func(section, key, raw=True)
                    result[section][key] = value
                else:
                    result[section][key] = key_default_value

        return dict(result)

        Parse the config and return a dict with the parsed values.

        :rtype: ``dict``
        
st2client/st2client/config_parser.py