Patchwork [1,of,5] chgserver: add utilities to calculate confighash

login
register
mail settings
Submitter Jun Wu
Date Feb. 24, 2016, 10:30 p.m.
Message ID <fbc26e0249811675aaa7.1456353012@x1c>
Download mbox | patch
Permalink /patch/13375/
State Superseded
Commit 53dc4aada2d9eeb93302caa5b7b9a244193f2f41
Delegated to: Yuya Nishihara
Headers show

Comments

Jun Wu - Feb. 24, 2016, 10:30 p.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1456346139 0
#      Wed Feb 24 20:35:39 2016 +0000
# Node ID fbc26e0249811675aaa764b7c74fabc46cd421e5
# Parent  9c014b8b58c67018c6e5f897f1890162542868de
chgserver: add utilities to calculate confighash

confighash is the hash of sensitive config items like [extensions], and
sensitive environment variables like HG*, LD_*, etc. The config items
can come from global, user, repo config, and command line flags.

For chgserver, it is designed that once confighash changes, the server is
not qualified to serve its client and should redirect the client to a new
server. The server does not need to exit in this case, since it can still
be valid (have a matched confighash) to serve other chg clients.
Yuya Nishihara - Feb. 25, 2016, 2:21 p.m.
On Wed, 24 Feb 2016 22:30:12 +0000, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark@fb.com>
> # Date 1456346139 0
> #      Wed Feb 24 20:35:39 2016 +0000
> # Node ID fbc26e0249811675aaa764b7c74fabc46cd421e5
> # Parent  9c014b8b58c67018c6e5f897f1890162542868de
> chgserver: add utilities to calculate confighash
> 
> confighash is the hash of sensitive config items like [extensions], and
> sensitive environment variables like HG*, LD_*, etc. The config items
> can come from global, user, repo config, and command line flags.
> 
> For chgserver, it is designed that once confighash changes, the server is
> not qualified to serve its client and should redirect the client to a new
> server. The server does not need to exit in this case, since it can still
> be valid (have a matched confighash) to serve other chg clients.
> 
> diff --git a/hgext/chgserver.py b/hgext/chgserver.py
> --- a/hgext/chgserver.py
> +++ b/hgext/chgserver.py
> @@ -30,6 +30,7 @@
>  
>  import SocketServer
>  import errno
> +import hashlib
>  import os
>  import re
>  import signal
> @@ -58,6 +59,36 @@
>  
>  _log = commandserver.log
>  
> +def _hashlist(items):
> +    """return sha256 hexdigest for a list"""
> +    return hashlib.sha256(str(items)).hexdigest()

There are util.shaxxx functions, but sha256 isn't. Since we don't need
cryptographic strength of sha256, we can pick one from util.shaxxx.

> +# sensitive config sections affecting confighash
> +_configsections = ['extensions', 'extdiff', 'experimental']

Let's start with ['extensions']. The other sections would need detailed
comments. It's easy to add sections, but hard to remove them from the list.

> +# sensitive environment variables affecting confighash
> +_envre = re.compile('CHGHG|HG.*|LANG|LC_.*|LD.*|PATH|PYTHON.*|TERM(?:INFO)?'
> +                    '|TZ')

Missing '$' at the end?
re.match() passes if a string starts with the pattern, but you seem to expect
an exact match.

But both LANG and LANGUAGE need to be caught.

> +def _confighash(ui):
> +    """return a quick hash for detecting config/env changes
> +
> +    confighash is the hash of sensitive config items and environment variables.
> +
> +    for chgserver, it is designed that once confighash changes, the server is
> +    not qualified to serve its client and should redirect the client to a new
> +    server. different from mtimehash, confighash change will not mark the
> +    server outdated and exit since the user can have different configs at the
> +    same time.
> +    """
> +    sectionitems = []
> +    for section in _configsections:
> +        sectionitems.append(sorted(ui.configitems(section)))

configitems() have a stable order. IIRC, we can't be 100% sure that the loading
order of extensions never change the behavior.

> +    sectionhash = _hashlist(sectionitems)
> +    envitems = [(k, v) for k, v in os.environ.items() if _envre.match(k)]

.iteritems() for now.

Patch

diff --git a/hgext/chgserver.py b/hgext/chgserver.py
--- a/hgext/chgserver.py
+++ b/hgext/chgserver.py
@@ -30,6 +30,7 @@ 
 
 import SocketServer
 import errno
+import hashlib
 import os
 import re
 import signal
@@ -58,6 +59,36 @@ 
 
 _log = commandserver.log
 
+def _hashlist(items):
+    """return sha256 hexdigest for a list"""
+    return hashlib.sha256(str(items)).hexdigest()
+
+# sensitive config sections affecting confighash
+_configsections = ['extensions', 'extdiff', 'experimental']
+
+# sensitive environment variables affecting confighash
+_envre = re.compile('CHGHG|HG.*|LANG|LC_.*|LD.*|PATH|PYTHON.*|TERM(?:INFO)?'
+                    '|TZ')
+
+def _confighash(ui):
+    """return a quick hash for detecting config/env changes
+
+    confighash is the hash of sensitive config items and environment variables.
+
+    for chgserver, it is designed that once confighash changes, the server is
+    not qualified to serve its client and should redirect the client to a new
+    server. different from mtimehash, confighash change will not mark the
+    server outdated and exit since the user can have different configs at the
+    same time.
+    """
+    sectionitems = []
+    for section in _configsections:
+        sectionitems.append(sorted(ui.configitems(section)))
+    sectionhash = _hashlist(sectionitems)
+    envitems = [(k, v) for k, v in os.environ.items() if _envre.match(k)]
+    envhash = _hashlist(sorted(envitems))
+    return sectionhash[:6] + envhash[:6]
+
 # copied from hgext/pager.py:uisetup()
 def _setuppagercmd(ui, options, cmd):
     if not ui.formatted():