From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 395A7C4363F for ; Wed, 12 May 2021 16:37:56 +0000 (UTC) Received: by mail.kernel.org (Postfix) id 00FAE61107; Wed, 12 May 2021 16:37:56 +0000 (UTC) Received: by mail.kernel.org (Postfix) with ESMTPSA id A6EB460BBB for ; Wed, 12 May 2021 16:37:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1620837475; bh=wWdyhJFBSwLO5u00+l60QfF/m/7QRen8eqRy1nf048A=; h=From:List-Id:To:Subject:Date:In-Reply-To:References:From; b=ysGqW7mnlutkrE4KHdZ4EDUfML55NBhxd6iSkVu+D9+9ty+IBv0lH9zOQAeAwg/eC /MeZtX8JP7grL+7rB39arESdB5A+0e/xg7dOTkigDfYpHHNdc+U/XPZuX+SlPNeHT7 EYDHfdVvrLsjDrxbd/EC6EwijbRlt4zHNKswWbkw= From: Konstantin Ryabitsev List-Id: To: signatures@kernel.org Subject: [PATCH 2/3] Support other git dirs as sources Date: Wed, 12 May 2021 16:37:53 +0000 Message-Id: <20210512163754.4865-2-konstantin@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210512163754.4865-1-konstantin@linuxfoundation.org> References: <20210512163754.4865-1-konstantin@linuxfoundation.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1620837474; l=8542; h=from:subject; bh=wWdyhJFBSwLO5u00+l60QfF/m/7QRen8eqRy1nf048A=; b=pWalrinoVUEZyggaAc9qkkqXi8Jd7iTFJ2BHVfcVBU8ds7m2Iri9mPMKpKB6ikxEl/sut3rK98zF 4XGrLHLACdqjfD39szHuwvS/5sJtLkQliloHi7exVFeiok30ICVq X-Developer-Key: i=konstantin@linuxfoundation.org; a=ed25519; pk=9ciBWmyn5HjhDlbO11pAsl37cQv79bkr5meFI7Av/+w= Content-Transfer-Encoding: 8bit We need to have a way to specify other git dirs as sources, so change how our ref: locations work. Instead of: ref:[refname]:[subpath] we now have: ref:[repopath]:[refname]:[subpath] Additionally, add a way to deal with one level of symlinks. Signed-off-by: Konstantin Ryabitsev --- README.rst | 22 ++++++------- man/patatt.5 | 2 +- man/patatt.5.rst | 4 +-- patatt/__init__.py | 79 ++++++++++++++++++++++++++++------------------ 4 files changed, 63 insertions(+), 44 deletions(-) diff --git a/README.rst b/README.rst index e0272b8..6cde177 100644 --- a/README.rst +++ b/README.rst @@ -368,12 +368,12 @@ check, via the ``keyringsrc`` setting (can be specified multiple times and will be checked in the listed order):: [patatt] - # Empty ref means "use currently checked out ref" - keyringsrc = ref::.keys - # Use a dedicated ref called refs/meta/keyring - keyringsrc = ref:refs/meta/keyring: - # You can fetch other project's keyring into its own ref - keyringsrc = ref:refs/meta/someone-elses-keyring: + # Empty ref means "use currently checked out ref in this repo" + keyringsrc = ref:::.keys + # Use a dedicated ref in this repo called refs/meta/keyring + keyringsrc = ref::refs/meta/keyring: + # Use a ref in a different repo + keyringsrc = ref:~/path/to/another/repo:refs/heads/main:.keys # Use a regular dir on disk keyringsrc = ~/git/pgpkeys/keyring @@ -385,13 +385,13 @@ Any path on disk can be used for a keyring location, and some will always be checked just in case. The following locations are added by default:: - ref::.keys - ref::.local-keys - ref:refs/meta/keyring: + ref:::.keys + ref:::.local-keys + ref::refs/meta/keyring: $XDG_DATA_HOME/patatt/public -The "::" means "whatever ref is currently checked out", and -$XDG_DATA_HOME usually points at ~/.local/share. +The ":::" means "whatever ref is checked out in the current repo", +and $XDG_DATA_HOME usually points at $HOME/.local/share. Getting support and contributing patches ---------------------------------------- diff --git a/man/patatt.5 b/man/patatt.5 index 5e97753..70cea05 100644 --- a/man/patatt.5 +++ b/man/patatt.5 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH PATATT 5 "2021-05-07" "0.1.0" "" +.TH PATATT 5 "2021-05-11" "0.2.0" "" .SH NAME PATATT \- DKIM-like cryptographic patch attestation . diff --git a/man/patatt.5.rst b/man/patatt.5.rst index f607ed9..2ab345c 100644 --- a/man/patatt.5.rst +++ b/man/patatt.5.rst @@ -5,10 +5,10 @@ DKIM-like cryptographic patch attestation ----------------------------------------- :Author: mricon@kernel.org -:Date: 2021-05-07 +:Date: 2021-05-11 :Copyright: The Linux Foundation and contributors :License: MIT-0 -:Version: 0.1.0 +:Version: 0.2.0 :Manual section: 5 SYNOPSIS diff --git a/patatt/__init__.py b/patatt/__init__.py index be32e36..e547b28 100644 --- a/patatt/__init__.py +++ b/patatt/__init__.py @@ -41,9 +41,6 @@ RES_ERROR = 16 RES_BADSIG = 32 REQ_HDRS = [b'from', b'subject'] -DEFAULT_CONFIG = { - 'keyringsrc': ['ref::.keys', 'ref::.local-keys', 'ref:refs/meta/keyring:'], -} # Quick cache for key info KEYCACHE = dict() @@ -598,9 +595,9 @@ def _run_command(cmdargs: list, stdin: bytes = None, env: Optional[dict] = None) def git_run_command(gitdir: Optional[str], args: list, stdin: Optional[bytes] = None, env: Optional[dict] = None) -> Tuple[int, bytes, bytes]: if gitdir: - env = {'GIT_DIR': gitdir} - - args = ['git', '--no-pager'] + args + args = ['git', '--git-dir', gitdir, '--no-pager'] + args + else: + args = ['git', '--no-pager'] + args return _run_command(args, stdin=stdin, env=env) @@ -688,36 +685,55 @@ def get_public_key(source: str, keytype: str, identity: str, selector: str) -> T keypath = make_pkey_path(keytype, identity, selector) logger.debug('Looking for %s in %s', keypath, source) - if source.find('ref:') == 0: - gittop = get_git_toplevel() + # ref:refs/heads/someref:in-repo/path + if source.startswith('ref:'): + # split by : + parts = source.split(':', 4) + if len(parts) < 4: + raise ConfigurationError('Invalid ref, must have at least 3 colons: %s' % source) + gittop = parts[1] + gitref = parts[2] + gitsub = parts[3] + if not gittop: + gittop = get_git_toplevel() if not gittop: raise KeyError('Not in a git tree, so cannot use a ref: source') - # format is: ref:refspec:path - # or it could omit the refspec, meaning "whatever the current ref" - # but it should always have at least two ":" - chunks = source.split(':', 2) - if len(chunks) < 3: - logger.debug('ref: sources must have refspec and path, e.g.: ref:refs/heads/master:.keys') - raise ConfigurationError('Invalid ref: source: %s' % source) + + gittop = os.path.expanduser(gittop) + if gittop.find('$') >= 0: + gittop = os.path.expandvars(gittop) + if os.path.isdir(os.path.join(gittop, '.git')): + gittop = os.path.join(gittop, '.git') + + # it could omit the refspec, meaning "whatever the current ref" # grab the key from a fully ref'ed path - ref = chunks[1] - pathtop = chunks[2] - subpath = os.path.join(pathtop, keypath) + subpath = os.path.join(gitsub, keypath) - if not ref: + if not gitref: # What is our current ref? - cmdargs = ['git', 'symbolic-ref', 'HEAD'] - ecode, out, err = _run_command(cmdargs) + cmdargs = ['symbolic-ref', 'HEAD'] + ecode, out, err = git_run_command(gittop, cmdargs) if ecode == 0: - ref = out.decode().strip() + gitref = out.decode().strip() + if not gitref: + raise KeyError('Could not figure out current ref in %s' % gittop) - cmdargs = ['git'] - keysrc = f'{ref}:{subpath}' - cmdargs += ['show', keysrc] - ecode, out, err = _run_command(cmdargs) + keysrc = f'{gitref}:{subpath}' + cmdargs = ['show', keysrc] + ecode, out, err = git_run_command(gittop, cmdargs) if ecode == 0: + # Handle one level of symlinks + if out.find(b'\n') < 0 < out.find(b'/'): + # Check this path as well + linktgt = os.path.normpath(os.path.join(os.path.dirname(subpath), out.decode())) + keysrc = f'{gitref}:{linktgt}' + cmdargs = ['show', keysrc] + ecode, out, err = git_run_command(gittop, cmdargs) + if ecode == 0: + logger.debug('KEYSRC : %s (symlinked)', keysrc) + return out, 'ref:%s:%s' % (gittop, keysrc) logger.debug('KEYSRC : %s', keysrc) - return out, keysrc + return out, 'ref:%s:%s' % (gittop, keysrc) # Does it exist on disk in gittop? fullpath = os.path.join(gittop, subpath) @@ -726,7 +742,7 @@ def get_public_key(source: str, keytype: str, identity: str, selector: str) -> T logger.debug('KEYSRC : %s', fullpath) return fh.read(), fullpath - raise KeyError('Could not find %s in %s' % (subpath, ref)) + raise KeyError('Could not find %s in %s:%s' % (subpath, gittop, gitref)) # It's a disk path, then # Expand ~ and env vars @@ -1084,8 +1100,11 @@ def command() -> None: ch.setLevel(logging.CRITICAL) logger.addHandler(ch) - config = get_config_from_git(r'patatt\..*', section=_args.section, - defaults=DEFAULT_CONFIG, multivals=['keyringsrc']) + config = get_config_from_git(r'patatt\..*', section=_args.section, multivals=['keyringsrc']) + # Append some extra keyring locations + if 'keyringsrc' not in config: + config['keyringsrc'] = list() + config['keyringsrc'] += ['ref:::.keys', 'ref:::.local-keys', 'ref::refs/meta/keyring:'] logger.debug('config: %s', config) if 'func' not in _args: -- 2.25.1