Victor Romano e00c7223b5 Modify kube-rootca audit to alarm first
On previous installations, the subcloud kube-rootca certificate is
different than the one from system controller. Currently, the audit
is comparing cert_id and declaring out-of-sync if they don't match,
which leads to an out-of-sync in the endpoint post upgrade. This
commit changes the audit logic to first audit by alarms so upgraded
subclouds can remain in-sync. Audit by cert_id still happen, but
only if the subcloud was rehomed.

Additionally, the force parameter was re-introduced in kube-rootca
update orchestration. Since with alarm based audit different cert_ids
can still present an in-sync status, the user might want to update
subcloud cert to match system controller, so the force parameter is
necessary to allow this.

Note: Dcagent didn't previously allowed extra_args to be sent in
in the payload. To avoid breaking audit with previous versions of
dcagent sending an unknown key in the payload (which will thrown an
error), extra_args are being sent in request header with the key
"X-DCAGENT-HEADERS". Support for extra_args in the payload was added,
but can only be used when all supported dcagent versions have this
option.

Note: Due to the current issue that blocks upgrade test, this commit
did not test subcloud upgrade, but the scenario would follow a
similar path from the second test case below, where updating a
subcloud rootca to a different cert from system controller results in
an in-sync endpoint status.

Test plan:
  - PASS: Deploy a subcloud and verify kube-rootca_sync_status is
          in-sync.
  - PASS: Perform a kube-rootca update orchestration directly in the
          subcloud without passing a cert so it will auto generate
          one and verify kube-rootca_sync_status is still in-sync.
  - PASS: Rehome the subcloud from the previous test and verify
          kube-rootca_sync_status is out-of-sync.
  - PASS: Perform a kube-rootca update orchestration using dcmanager
          in an out-of-sync subcloud providing system controller certs
          and verify the final sync status is in-sync.
  - PASS: Perform a kube-rootca update orchestration using dcmanager
          in an in-sync subcloud with force parameter without
          providing certs and verify the final sync status is in-sync.
  - PASS: Install a N-1 release and verify kube-rootca_sync_status is
          in-sync.

Closes-bug: 2092069

Change-Id: If0cc002d0d4970730771ae90d80dc50c7daf4d4c
Signed-off-by: Victor Romano <victor.gluzromano@windriver.com>
2024-12-19 21:16:18 +00:00

78 lines
2.6 KiB
Python

#
# Copyright (c) 2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import http.client
import json
from oslo_config import cfg
from oslo_log import log as logging
import pecan
from pecan import expose
from pecan import request
from dcagent.api.controllers import restcomm
from dcagent.common.audit_manager import RequestedAudit
from dcagent.common.exceptions import UnsupportedAudit
from dcagent.common.i18n import _
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
class AuditController(object):
@expose(generic=True, template="json")
def index(self):
# Route the request to specific methods with parameters
pass
@index.when(method="PATCH", template="json")
def patch(self):
"""Return the audit information."""
context = restcomm.extract_context_from_environ()
# Convert JSON string in request to Python dict
try:
payload = json.loads(request.body)
except ValueError:
pecan.abort(http.client.BAD_REQUEST, _("Request body decoding error"))
if not payload:
pecan.abort(http.client.BAD_REQUEST, _("Body required"))
# TODO(vgluzrom): Remove extra_args from header and keep it only in payload
# once all supported dcagent versions have this possibility. If system
# controller sends extra_args in payload to a dcagent that doesn't support it,
# it will raise an UnsupportedAudit exception.
try:
headers = json.loads(request.headers.get("X-DCAGENT-HEADERS", "{}"))
except ValueError:
pecan.abort(http.client.BAD_REQUEST, _("Request headers decoding error"))
extra_args = payload.pop("extra_args", {})
extra_args = {**extra_args, **headers}
LOG.debug(
f"Payload sent by system controller: {payload}. Extra args: {extra_args}"
)
try:
# Delete "use_cache" from payload so it doesn't get passed as an audit
use_cache = payload.pop("use_cache", True)
# request_token is used for calls not involving cache
requested_audit = RequestedAudit(
request_token=context.auth_token, use_cache=use_cache
)
return requested_audit.get_sync_status(payload, extra_args)
except UnsupportedAudit as ex:
LOG.exception(ex)
pecan.abort(http.client.BAD_REQUEST, ex.msg)
except Exception as ex:
LOG.exception(ex)
msg = f"Unable to get audit info: {ex}"
pecan.abort(http.client.INTERNAL_SERVER_ERROR, _(msg))