latchset / custodia

An API to manage secrets storage and retrieval
GNU General Public License v3.0
85 stars 27 forks source link

Add plugin API to customize custodia client CLI #239

Open tiran opened 6 years ago

tiran commented 6 years ago

Custodia has plugins for store, authn and authz but no plugins to modify the behavior of custodia.cli. Rather than baking features like #238 directly into the CLI, Custodia should have an API to allow customization of CLI. I'm thinking about a similar approach as https://docs.pytest.org/en/latest/writing_plugins.html

Any package can provide a CLI plugin as custodia.cli entry point.

API draft

class CustodiaCLIPlugin(object):
    name = 'gssapi'
    priority = 100
    title = 'GSSAPI authentication'
    description = None

    def __init__(self, parser, subparsers):
        """Init

        :param parser: argparse Parser instance 
        :param subparsers: subparser instance 
        """
        self.parser = parser
        self.subparsers = subparsers

    def add_arguments(self):
        """Add argparse arguments

        :param group: argparse Parser group
        :return: None
        """
        group = self.parser.add_argument_group(
            self.title, self.description
        )
        group.add_argument(
           '--gssapi', action='store_true',
            help='Use Negotiate / GSSAPI auth'
        )

    def validate_arguments(self, args):
        """Validate arguments after parsing

        :param args: namespace from parser.parse_args(...)
        :return: None
        """
        if args.gssapi and args.certfile:
            self.parser.error(
                "gssapi and certfile are mutually exclusive.\n"
            )
        if args.gssapi and requests_gssapi is None:
            self.parser.error(
                "'requests_gssapi' package is not available! You can "
                "install it with: 'pip install custodia[gssapi]'.\n"
            )

    def create_client(self, args):
        """Create custodia client instance

        Plugins are sorted by priority and name. The first plugin that
        returns a client instance wins.

        :param args: namespace from parser.parse_args(...)
        :return: None or instance of CustodiaHTTPClient subclass
        """

    def update_client(self, args, client):
        """Update client with settings

        :param args: namespace from parser.parse_args(...) 
        :param client: Custodia client instance 
        :return: 
        """
        if args.gssapi:
            client.set_gssapi_auth()
simo5 commented 6 years ago

SGTM