|
Este documento ha sido traducido utilizando tecnología de traducción automática. Si bien nos esforzamos por proporcionar traducciones precisas, no ofrecemos garantías sobre la integridad, precisión o confiabilidad del contenido traducido. En caso de discrepancia, la versión original en inglés prevalecerá y constituirá el texto autorizado. |
|
Esta es documentación inédita para Admission Controller 1.34-dev. |
Creando una nueva política de mutación
Las políticas de mutación son similares a las de validación, pero también tienen la capacidad de mutar un objeto entrante.
Pueden:
-
Rechazar una solicitud
-
Aceptar una solicitud sin cambiar el objeto entrante
-
Mutar el objeto entrante según sea necesario y aceptar la solicitud
Escribir una SUSE Security Admission Controller política de mutación es sencillo. Utilizarás la política de validación creada en las secciones anteriores, y con algunos cambios, la convertirás en una política de mutación.
Tu política utiliza la misma lógica de validación definida anteriormente, pero también añade una anotación a todos los Pods que tienen un nombre válido.
Intentando crear un Pod como este:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
Conduce a la creación de este Pod:
apiVersion: v1
kind: Pod
metadata:
name: nginx
annotations:
kubewarden.policy.demo/inspected: true
spec:
containers:
- name: nginx
image: nginx:latest
Escribe el código de mutación
El código de mutación está en la validate función.
Deberías cambiar esta función para aprobar la solicitud utilizando mutate_request en lugar de accept_request.
Así es como debería verse la función validate en lib.rs:
fn validate(payload: &[u8]) -> CallResult {
let validation_request: ValidationRequest<Settings> = ValidationRequest::new(payload)?;
info!(LOG_DRAIN, "starting validation");
if validation_request.request.kind.kind != apicore::Pod::KIND {
warn!(LOG_DRAIN, "Policy validates Pods only. Accepting resource"; "kind" => &validation_request.request.kind.kind);
return kubewarden::accept_request();
}
match serde_json::from_value::<apicore::Pod>(validation_request.request.object) {
// NOTE 1
Ok(mut pod) => {
let pod_name = pod.metadata.name.clone().unwrap_or_default();
if validation_request
.settings
.invalid_names
.contains(&pod_name)
{
kubewarden::reject_request(
Some(format!("pod name {:?} is not accepted", pod_name)),
None,
None,
None,
)
} else {
// NOTE 2
let mut new_annotations = pod.metadata.annotations.clone().unwrap_or_default();
new_annotations.insert(
String::from("kubewarden.policy.demo/inspected"),
String::from("true"),
);
pod.metadata.annotations = Some(new_annotations);
// NOTE 3
let mutated_object = serde_json::to_value(pod)?;
kubewarden::mutate_request(mutated_object)
}
}
Err(_) => {
// We were forwarded a request we cannot unmarshal or
// understand, just accept it
kubewarden::accept_request()
}
}
}
Comparado con el código anterior, has realizado tres cambios:
-
Definimos el objeto
podcomo mutable, observa la palabra clavemut. Esto es necesario porque vamos a extender su atributometadata.annotations. -
Este es el código que toma el
annotationsexistente, añade el nuevo y finalmente coloca el objetoannotationsactualizado de nuevo en la instancia originalpod. -
Serializa el objeto
poden unserde_json::Valuegenérico y luego devuelve una respuesta de mutación.
Habiendo realizado estos cambios, es hora de ejecutar de nuevo las pruebas unitarias:
$ cargo test
Compiling demo-a v0.1.0 (/home/jhk/projects/suse/tmp/demo)
Finished test [unoptimized + debuginfo] target(s) in 0.95s
Running unittests src/lib.rs (target/debug/deps/demo_a-634b88b0dcb6e707)
running 5 tests
test settings::tests::reject_settings_without_a_list_of_invalid_names ... ok
test settings::tests::accept_settings_with_a_list_of_invalid_names ... ok
test tests::accept_request_with_non_pod_resource ... ok
test tests::reject_pod_with_invalid_name ... ok
test tests::accept_pod_with_valid_name ... FAILED
failures:
---- tests::accept_pod_with_valid_name stdout ----
{"column":5,"file":"src/lib.rs","level":"info","line":34,"message":"starting validation","policy":"sample-policy"}
thread 'tests::accept_pod_with_valid_name' panicked at src/lib.rs:98:9:
Something mutated with test case: Pod creation with valid name
note: run with `+RUST_BACKTRACE=1+` environment variable to display a backtrace
failures:
tests::accept_pod_with_valid_name
test result: FAILED. 4 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Como puedes ver, el accept_pod_with_valid_name falla porque la respuesta contiene un objeto mutado.
Parece que nuestro código está funcionando.
Actualiza las pruebas unitarias
Puedes actualizar el accept_pod_with_valid_name en lib.rs para que se vea así:
#[test]
fn accept_pod_with_valid_name() -> Result<(), ()> {
let mut invalid_names = HashSet::new();
invalid_names.insert(String::from("bad_name1"));
let settings = Settings { invalid_names };
let request_file = "test_data/pod_creation.json";
let tc = Testcase {
name: String::from("Pod creation with valid name"),
fixture_file: String::from(request_file),
expected_validation_result: true,
settings,
};
let res = tc.eval(validate).unwrap();
// NOTE 1
assert!(
res.mutated_object.is_some(),
"Expected accepted object to be mutated",
);
// NOTE 2
let final_pod =
serde_json::from_value::<apicore::Pod>(res.mutated_object.unwrap()).unwrap();
let final_annotations = final_pod.metadata.annotations.unwrap();
assert_eq!(
final_annotations.get_key_value("kubewarden.policy.demo/inspected"),
Some((
&String::from("kubewarden.policy.demo/inspected"),
&String::from("true")
)),
);
Ok(())
}
En comparación con la primera prueba, hay dos cambios:
-
Cambia la declaración
assert!para que la solicitud siga siendo aceptada, pero también incluya un objeto mutado. -
Se creó una instancia de
Poda partir del objeto mutado que forma parte de la respuesta. Asegúrate de que el objeto Pod mutado tiene elmetadata.annotationscorrecto.
Ejecuta las pruebas de nuevo, esta vez todas deben pasar:
$ cargo test
Compiling demo-a v0.1.0 (/home/jhk/projects/suse/tmp/demo)
Finished test [unoptimized + debuginfo] target(s) in 1.25s
Running unittests src/lib.rs (target/debug/deps/demo_a-634b88b0dcb6e707)
running 5 tests
test settings::tests::accept_settings_with_a_list_of_invalid_names ... ok
test settings::tests::reject_settings_without_a_list_of_invalid_names ... ok
test tests::accept_request_with_non_pod_resource ... ok
test tests::reject_pod_with_invalid_name ... ok
test tests::accept_pod_with_valid_name ... ok
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Como puedes ver, la creación de una política de mutación es sencilla.