From: Enrico Scholz <[email protected]>

Some integrations require that passwords or secret tokens are
assigned to bitbake variables.  E.g. the meta-dependencytrack
layer has a 'DEPENDENCYTRACK_API_KEY' or my sstate-server requires
a 'SSTATE_SERVER_SESSION' token.

These secrets will appear in testdata.json which can easily leak them
when the deploy directory is published publicly.

Patch adds a special 'secrets' flag for variables.  When a variable is
marked with it, its content will be replaced by '**masked**'.

E.g. formerly

|    "SSTATE_SERVER_PATH": "HKBOZ8C279S4iwBA",
|    "SSTATE_MIRRORS": "    ... 
https://sstate..../api/v1/download/HKBOZ8C279S4iwBA/sstate/...

and now

|    "SSTATE_SERVER_PATH": "**masked**",
|    "SSTATE_MIRRORS": "    ... 
https://sstate..../api/v1/download/**masked**/sstate

Corresponding bbclass contains

| SSTATE_SERVER_PATH ??= "-"
| SSTATE_SERVER_PATH[secret] = "true"

Signed-off-by: Enrico Scholz <[email protected]>
---
 meta/lib/oe/data.py | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/meta/lib/oe/data.py b/meta/lib/oe/data.py
index 37121cfad2b7..57a8e5b5e049 100644
--- a/meta/lib/oe/data.py
+++ b/meta/lib/oe/data.py
@@ -5,7 +5,9 @@
 #
 
 import json
+import re
 import oe.maketype
+import oe.types
 
 def typed_value(key, d):
     """Construct a value for the specified metadata variable, using its flags
@@ -23,9 +25,10 @@ def typed_value(key, d):
     except (TypeError, ValueError) as exc:
         bb.msg.fatal("Data", "%s: %s" % (key, str(exc)))
 
-def export2json(d, json_file, expand=True, searchString="",replaceString=""):
+def export2json(d, json_file, expand=True, searchString="",replaceString="", 
mask_secrets=True):
     data2export = {}
     keys2export = []
+    secrets = []
 
     for key in d.keys():
         if key.startswith("_"):
@@ -38,12 +41,34 @@ def export2json(d, json_file, expand=True, 
searchString="",replaceString=""):
             continue
         elif d.getVarFlag(key, "func"):
             continue
+        elif mask_secrets and oe.types.boolean(d.getVarFlag(key, "secret") or 
"false"):
+            var = d.getVar(key)
+
+            ## When secret variable contains a placeholder (is empty
+            ## or single character), show it.  When it is too short
+            ## emit a warning and exclude it completely from output
+            ## but do not mask out its value in other places.
+            if var is None or len(var) < 2:
+                bb.debug(1, "variable '%s' is marked as secret but seems to 
contain some placeholder; showing it" % key)
+            elif len(var) < 8:
+                bb.warn("variable '%s' is marked as secret but content is too 
short; skipping it" % key)
+                continue
+            else:
+                secrets.append(re.escape(var))
 
         keys2export.append(key)
 
+    if len(secrets) == 0:
+        secrets = None
+    else:
+        secrets = re.compile('|'.join(secrets))
+
     for key in keys2export:
         try:
-            data2export[key] = d.getVar(key, 
expand).replace(searchString,replaceString)
+            var = d.getVar(key, expand).replace(searchString,replaceString)
+            if secrets:
+                var = secrets.sub("**masked**", var)
+            data2export[key] = var
         except bb.data_smart.ExpansionError:
             data2export[key] = ''
         except AttributeError:
-- 
2.41.0

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#184876): 
https://lists.openembedded.org/g/openembedded-core/message/184876
Mute This Topic: https://lists.openembedded.org/mt/100368202/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to