Skip to content

Commit

Permalink
feat(events): WIP add route to get all the events generated by Gateke…
Browse files Browse the repository at this point in the history
…eper

WIP

Add a route /events/<context> to get all the events generated by Gatekeeper in its namespace.

This is useful to get in realtime violatoins to constraints for requests that get rejected and won't appear in the audit logs.

This depends on an alpha feature of Gatekeeper: https://open-policy-agent.github.io/gatekeeper/website/docs/customize-startup/#alpha-emit-admission-and-audit-events

Note that this is blocked by an issue in the Kubernetes client libray that explodes when the event_time is null: kubernetes-client/python#1616
  • Loading branch information
ralgozino committed Jan 2, 2023
1 parent 3d5db55 commit 14d84f1
Showing 1 changed file with 67 additions and 0 deletions.
67 changes: 67 additions & 0 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ def get_api(context=None):
config.new_client_from_config(context=context)
),
"apis": client.ApisApi(config.new_client_from_config(context=context)),
"events": client.EventsV1Api(
config.new_client_from_config(context=context)
),
}
elif app.config.get("MODE") == "CLUSTER":
app.logger.debug("entering CLUSTER MODE and getting API objects")
Expand Down Expand Up @@ -419,6 +422,70 @@ def get_gatekeeperconfigs(context=None):
return jsonify(configs.get("items"))


@app.route("/api/v1/events/")
@app.route("/api/v1/events/<context>/")
@login_required_conditional
def get_events(context=None):
"""Gatekeeper Events"""
try:
api = get_api(context)
# FIXME: we should get the namespace from the config
# There's a bug in the Kubernetes Clietn that prevents the following from working.
# See https://github.com/kubernetes-client/python/issues/1616
# When event_time is None the client breaks.
# Commenting lines 290 and 291 in the events_v1_event.py file of the Kubernetes Client
# bypasses the problem.
events = api["events"].list_namespaced_event(namespace="gatekeeper-system")
except NewConnectionError as e:
return {
"error": "Could not connect to Kubernetes Cluster",
"action": "Is the current Kubeconfig context valid?",
"description": str(e),
}, 500
except MaxRetryError as e:
return {
"error": "Could not connect to Kubernetes Cluster",
"action": "Is the current Kubeconfig context valid?",
"description": str(e),
}, 500
except ApiException as e:
if e.status == 404:
return jsonify([])
else:
return {
"error": "We had a problem while asking the API for Gatekeeper Configuration objects",
"action": "Is Gatekeeper deployed in the cluster?",
"description": str(e),
}, 500
except ConfigException as e:
return {
"error": "Can't connect to cluster due to an invalid kubeconfig file",
"action": "Please verify your kubeconfig file and location",
"description": str(e),
}, 500
else:
events_formatted = []
for e in events.items:
# FIXME: I'm not sure the reporting_controller field is the right one.
# It is not being set in my tests.
if (
e.deprecated_source.component == "gatekeeper-webhook"
or e.reporting_controller == "gatekeeper-webhook"
):
events_formatted.append(
{
"time": e.event_time or e.deprecated_first_timestamp,
"type": e.type,
"reason": e.reason,
"annotations": e.metadata.annotations,
"note": e.note,
# not needed because we have the same information in teh annotations
# "regarding": str(e.regarding),
}
)
return jsonify(events_formatted)


@app.route("/health")
def health():
"""Health check endpoint for probes"""
Expand Down

0 comments on commit 14d84f1

Please sign in to comment.