Merge branch 'stable-2.12' into stable-2.13
authorHrvoje Ribicic <riba@google.com>
Thu, 3 Dec 2015 21:13:39 +0000 (21:13 +0000)
committerHrvoje Ribicic <riba@google.com>
Thu, 3 Dec 2015 21:13:39 +0000 (21:13 +0000)
* stable-2.12
  Restrict showing of DRBD secret using types
  Calculate correct affected nodes set in InstanceChangeGroup

* stable-2.11
  (no changes)

* stable-2.10
  (no changes)

* stable-2.9
  QA: Ensure the DRBD secret is not retrievable via RAPI
  Redact the DRBD secret in instance queries
  Do not attempt to use the DRBD secret in gnt-instance info

Signed-off-by: Hrvoje Ribicic <riba@google.com>
Reviewed-by: Oleg Ponomarev <oponomarev@google.com>

1  2 
lib/client/gnt_instance.py
lib/cmdlib/instance.py
lib/cmdlib/instance_query.py
lib/objects.py
lib/storage/drbd.py
qa/ganeti-qa.py
qa/qa_rapi.py
src/Ganeti/Config.hs
src/Ganeti/Objects.hs
test/hs/Test/Ganeti/Objects.hs

Simple merge
Simple merge
Simple merge
diff --cc lib/objects.py
Simple merge
Simple merge
diff --cc qa/ganeti-qa.py
Simple merge
diff --cc qa/qa_rapi.py
@@@ -1260,49 -1254,55 +1261,103 @@@ def TestInterClusterInstanceMove(src_in
                        target_nodes=(pnode.primary, snode.primary))
  
  
 +def TestFilters():
 +  """Testing filter management via the remote API.
 +
 +  """
 +
 +  body = {
 +    "priority": 10,
 +    "predicates": [],
 +    "action": "CONTINUE",
 +    "reason": [(constants.OPCODE_REASON_SRC_USER,
 +               "reason1",
 +               utils.EpochNano())],
 +  }
 +
 +  body1 = copy.deepcopy(body)
 +  body1["priority"] = 20
 +
 +  # Query filters
 +  _DoTests([("/2/filters", [], "GET", None)])
 +
 +  # Add a filter via POST and delete it again
 +  uuid = _DoTests([("/2/filters", None, "POST", body)])[0]
 +  uuid_module.UUID(uuid)  # Check if uuid is a valid UUID
 +  _DoTests([("/2/filters/%s" % uuid, lambda r: r is None, "DELETE", None)])
 +
 +  _DoTests([
 +    # Check PUT-inserting a nonexistent filter with given UUID
 +    ("/2/filters/%s" % uuid, lambda u: u == uuid, "PUT", body),
 +    # Check PUT-inserting an existent filter with given UUID
 +    ("/2/filters/%s" % uuid, lambda u: u == uuid, "PUT", body1),
 +    # Check that the update changed the filter
 +    ("/2/filters/%s" % uuid, lambda f: f["priority"] == 20, "GET", None),
 +    # Delete it again
 +    ("/2/filters/%s" % uuid, lambda r: r is None, "DELETE", None),
 +    ])
 +
 +  # Add multiple filters, query and delete them
 +  uuids = _DoTests([
 +    ("/2/filters", None, "POST", body),
 +    ("/2/filters", None, "POST", body),
 +    ("/2/filters", None, "POST", body),
 +    ])
 +  _DoTests([("/2/filters", lambda rs: [r["uuid"] for r in rs] == uuids,
 +             "GET", None)])
 +  for u in uuids:
 +    _DoTests([("/2/filters/%s" % u, lambda r: r is None, "DELETE", None)])
++
++
+ _DRBD_SECRET_RE = re.compile('shared-secret.*"([0-9A-Fa-f]+)"')
+ def _RetrieveSecret(instance, pnode):
+   """Retrieves the DRBD secret given an instance object and the primary node.
+   @type instance: L{qa_config._QaInstance}
+   @type pnode: L{qa_config._QaNode}
+   @rtype: string
+   """
+   instance_info = GetInstanceInfo(instance.name)
+   # We are interested in only the first disk on the primary
+   drbd_minor = instance_info["drbd-minors"][pnode.primary][0]
+   # This form should work for all DRBD versions
+   drbd_command = ("drbdsetup show %d; drbdsetup %d show || true" %
+                   (drbd_minor, drbd_minor))
+   instance_drbd_info = \
+     qa_utils.GetCommandOutput(pnode.primary, drbd_command)
+   match_obj = _DRBD_SECRET_RE.search(instance_drbd_info)
+   if match_obj is None:
+     raise qa_error.Error("Could not retrieve DRBD secret for instance %s from"
+                          " node %s." % (instance.name, pnode.primary))
+   return match_obj.groups(0)[0]
+ def TestInstanceDataCensorship(instance, inodes):
+   """Test protection of sensitive instance data."""
+   if instance.disk_template != constants.DT_DRBD8:
+     print qa_utils.FormatInfo("Only the DRBD secret is a sensitive parameter"
+                               " right now, skipping for non-DRBD instance.")
+     return
+   drbd_secret = _RetrieveSecret(instance, inodes[0])
+   job_id = _rapi_client.GetInstanceInfo(instance.name)
+   if not _rapi_client.WaitForJobCompletion(job_id):
+     raise qa_error.Error("Could not fetch instance info for instance %s" %
+                          instance.name)
+   info_dict = _rapi_client.GetJobStatus(job_id)
+   if drbd_secret in str(info_dict):
+     print qa_utils.FormatInfo("DRBD secret: %s" % drbd_secret)
+     print qa_utils.FormatInfo("Retrieved data\n%s" % str(info_dict))
+     raise qa_error.Error("Found DRBD secret in contents of RAPI instance info"
+                          " call; see above.")
Simple merge
Simple merge
Simple merge