agent: clear log pipes if denied by policy

Container logs are forwarded to the agent through a unix pipe. These
pipes have limited capacity and block the writer when full. If reading
logs is blocked by policy, a common setup for confidential containers,
the pipes fill up and eventually block the container.

This commit changes the implementation of ReadStream such that it
returns empty log messages instead of a policy failure (in case reading
log messages is forbidden by policy). As long as the runtime does not
encounter a failure, it keeps pulling logs periodically. In turn, this
triggers the agent to flush the pipes.

Fixes: #10680

Co-Authored-By: Aurélien Bombo <abombo@microsoft.com>
Signed-off-by: Markus Rudy <mr@edgeless.systems>
This commit is contained in:
Markus Rudy 2024-12-20 08:42:38 +01:00
parent 95c63f4982
commit 937fd90779

View File

@ -649,11 +649,11 @@ impl AgentService {
async fn do_read_stream( async fn do_read_stream(
&self, &self,
req: protocols::agent::ReadStreamRequest, req: &protocols::agent::ReadStreamRequest,
stdout: bool, stdout: bool,
) -> Result<protocols::agent::ReadStreamResponse> { ) -> Result<protocols::agent::ReadStreamResponse> {
let cid = req.container_id; let cid = &req.container_id;
let eid = req.exec_id; let eid = &req.exec_id;
let term_exit_notifier; let term_exit_notifier;
let reader = { let reader = {
@ -900,8 +900,12 @@ impl agent_ttrpc::AgentService for AgentService {
_ctx: &TtrpcContext, _ctx: &TtrpcContext,
req: protocols::agent::ReadStreamRequest, req: protocols::agent::ReadStreamRequest,
) -> ttrpc::Result<ReadStreamResponse> { ) -> ttrpc::Result<ReadStreamResponse> {
is_allowed(&req).await?; let mut response = self.do_read_stream(&req, true).await.map_ttrpc_err(same)?;
self.do_read_stream(req, true).await.map_ttrpc_err(same) if is_allowed(&req).await.is_err() {
// Policy does not allow reading logs, so we redact the log messages.
response.clear_data();
}
Ok(response)
} }
async fn read_stderr( async fn read_stderr(
@ -909,8 +913,12 @@ impl agent_ttrpc::AgentService for AgentService {
_ctx: &TtrpcContext, _ctx: &TtrpcContext,
req: protocols::agent::ReadStreamRequest, req: protocols::agent::ReadStreamRequest,
) -> ttrpc::Result<ReadStreamResponse> { ) -> ttrpc::Result<ReadStreamResponse> {
is_allowed(&req).await?; let mut response = self.do_read_stream(&req, false).await.map_ttrpc_err(same)?;
self.do_read_stream(req, false).await.map_ttrpc_err(same) if is_allowed(&req).await.is_err() {
// Policy does not allow reading logs, so we redact the log messages.
response.clear_data();
}
Ok(response)
} }
async fn close_stdin( async fn close_stdin(