mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-06 20:09:44 +00:00
Merge pull request #8735 from microsoft/danmihai1/set-policy
agent: hold lock while setting new policy
This commit is contained in:
commit
b18f269ccf
@ -4,11 +4,15 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use protobuf::MessageDyn;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use slog::Drain;
|
use slog::Drain;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::time::{sleep, Duration};
|
use tokio::time::{sleep, Duration};
|
||||||
|
|
||||||
|
use crate::rpc::ttrpc_error;
|
||||||
|
use crate::AGENT_POLICY;
|
||||||
|
|
||||||
static EMPTY_JSON_INPUT: &str = "{\"input\":{}}";
|
static EMPTY_JSON_INPUT: &str = "{\"input\":{}}";
|
||||||
|
|
||||||
static OPA_DATA_PATH: &str = "/data";
|
static OPA_DATA_PATH: &str = "/data";
|
||||||
@ -23,6 +27,34 @@ macro_rules! sl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn allow_request(policy: &mut AgentPolicy, ep: &str, request: &str) -> ttrpc::Result<()> {
|
||||||
|
if !policy.allow_request(ep, request).await {
|
||||||
|
warn!(sl!(), "{ep} is blocked by policy");
|
||||||
|
Err(ttrpc_error(
|
||||||
|
ttrpc::Code::PERMISSION_DENIED,
|
||||||
|
format!("{ep} is blocked by policy"),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_allowed(req: &(impl MessageDyn + serde::Serialize)) -> ttrpc::Result<()> {
|
||||||
|
let request = serde_json::to_string(req).unwrap();
|
||||||
|
let mut policy = AGENT_POLICY.lock().await;
|
||||||
|
allow_request(&mut policy, req.descriptor_dyn().name(), &request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn do_set_policy(req: &protocols::agent::SetPolicyRequest) -> ttrpc::Result<()> {
|
||||||
|
let request = serde_json::to_string(req).unwrap();
|
||||||
|
let mut policy = AGENT_POLICY.lock().await;
|
||||||
|
allow_request(&mut policy, "SetPolicyRequest", &request).await?;
|
||||||
|
policy
|
||||||
|
.set_policy(&req.policy)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ttrpc_error(ttrpc::Code::INVALID_ARGUMENT, e))
|
||||||
|
}
|
||||||
|
|
||||||
/// Example of HTTP response from OPA: {"result":true}
|
/// Example of HTTP response from OPA: {"result":true}
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct AllowResponse {
|
struct AllowResponse {
|
||||||
@ -127,7 +159,7 @@ impl AgentPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ask OPA to check if an API call should be allowed or not.
|
/// Ask OPA to check if an API call should be allowed or not.
|
||||||
pub async fn is_allowed_endpoint(&mut self, ep: &str, request: &str) -> bool {
|
pub async fn allow_request(&mut self, ep: &str, request: &str) -> bool {
|
||||||
let post_input = format!("{{\"input\":{request}}}");
|
let post_input = format!("{{\"input\":{request}}}");
|
||||||
self.log_opa_input(ep, &post_input).await;
|
self.log_opa_input(ep, &post_input).await;
|
||||||
match self.post_query(ep, &post_input).await {
|
match self.post_query(ep, &post_input).await {
|
||||||
|
@ -23,7 +23,7 @@ use ttrpc::{
|
|||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use cgroups::freezer::FreezerState;
|
use cgroups::freezer::FreezerState;
|
||||||
use oci::{LinuxNamespace, Root, Spec};
|
use oci::{LinuxNamespace, Root, Spec};
|
||||||
use protobuf::{MessageDyn, MessageField};
|
use protobuf::MessageField;
|
||||||
use protocols::agent::{
|
use protocols::agent::{
|
||||||
AddSwapRequest, AgentDetails, CopyFileRequest, GetIPTablesRequest, GetIPTablesResponse,
|
AddSwapRequest, AgentDetails, CopyFileRequest, GetIPTablesRequest, GetIPTablesResponse,
|
||||||
GuestDetailsResponse, Interfaces, Metrics, OOMEvent, ReadStreamResponse, Routes,
|
GuestDetailsResponse, Interfaces, Metrics, OOMEvent, ReadStreamResponse, Routes,
|
||||||
@ -69,7 +69,7 @@ use crate::trace_rpc_call;
|
|||||||
use crate::tracer::extract_carrier_from_ttrpc;
|
use crate::tracer::extract_carrier_from_ttrpc;
|
||||||
|
|
||||||
#[cfg(feature = "agent-policy")]
|
#[cfg(feature = "agent-policy")]
|
||||||
use crate::AGENT_POLICY;
|
use crate::policy::{do_set_policy, is_allowed};
|
||||||
|
|
||||||
use opentelemetry::global;
|
use opentelemetry::global;
|
||||||
use tracing::span;
|
use tracing::span;
|
||||||
@ -123,33 +123,15 @@ fn sl() -> slog::Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convenience function to wrap an error and response to ttrpc client
|
// Convenience function to wrap an error and response to ttrpc client
|
||||||
fn ttrpc_error(code: ttrpc::Code, err: impl Debug) -> ttrpc::Error {
|
pub fn ttrpc_error(code: ttrpc::Code, err: impl Debug) -> ttrpc::Error {
|
||||||
get_rpc_status(code, format!("{:?}", err))
|
get_rpc_status(code, format!("{:?}", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "agent-policy"))]
|
#[cfg(not(feature = "agent-policy"))]
|
||||||
async fn is_allowed(_req: &(impl MessageDyn + serde::Serialize)) -> ttrpc::Result<()> {
|
async fn is_allowed(_req: &impl serde::Serialize) -> ttrpc::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "agent-policy")]
|
|
||||||
async fn is_allowed(req: &(impl MessageDyn + serde::Serialize)) -> ttrpc::Result<()> {
|
|
||||||
let request = serde_json::to_string(req).unwrap();
|
|
||||||
let mut policy = AGENT_POLICY.lock().await;
|
|
||||||
if !policy
|
|
||||||
.is_allowed_endpoint(req.descriptor_dyn().name(), &request)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
warn!(sl(), "{} is blocked by policy", req.descriptor_dyn().name());
|
|
||||||
Err(ttrpc_error(
|
|
||||||
ttrpc::Code::PERMISSION_DENIED,
|
|
||||||
format!("{} is blocked by policy", req.descriptor_dyn().name()),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn same<E>(e: E) -> E {
|
fn same<E>(e: E) -> E {
|
||||||
e
|
e
|
||||||
}
|
}
|
||||||
@ -1439,14 +1421,8 @@ impl agent_ttrpc::AgentService for AgentService {
|
|||||||
req: protocols::agent::SetPolicyRequest,
|
req: protocols::agent::SetPolicyRequest,
|
||||||
) -> ttrpc::Result<Empty> {
|
) -> ttrpc::Result<Empty> {
|
||||||
trace_rpc_call!(ctx, "set_policy", req);
|
trace_rpc_call!(ctx, "set_policy", req);
|
||||||
is_allowed(&req).await?;
|
|
||||||
|
|
||||||
AGENT_POLICY
|
do_set_policy(&req).await?;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.set_policy(&req.policy)
|
|
||||||
.await
|
|
||||||
.map_ttrpc_err(same)?;
|
|
||||||
|
|
||||||
Ok(Empty::new())
|
Ok(Empty::new())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user