Ce document a été traduit à l'aide d'une technologie de traduction automatique. Bien que nous nous efforcions de fournir des traductions exactes, nous ne fournissons aucune garantie quant à l'exhaustivité, l'exactitude ou la fiabilité du contenu traduit. En cas de divergence, la version originale anglaise prévaut et fait foi.

Il s'agit d'une documentation non publiée pour Admission Controller 1.34-dev.

Stratégies brutes

Les stratégies brutes sont des stratégies qui peuvent évaluer des documents JSON arbitraires. Pour plus d’informations sur les stratégies brutes, veuillez vous référer à la page stratégies brutes.

Exemples

Les exemples suivants devraient vous sembler familiers si vous avez complété la page validation de ce didacticiel.

N’oubliez pas de marquer la stratégie comme raw, en utilisant le champ policyType dans la metadata.yml configuration. Veuillez vous référer à la spécification metadata pour plus d’informations.

Validation

Rédigeons une stratégie qui accepte une demande dans le format suivant :

{
  "request": {
    "user": "alice",
    "action": "delete",
    "resource": "products"
  }
}

et valide que :

  • user est dans la liste des utilisateurs valides

  • action est dans la liste des actions valides

  • resource est dans la liste des ressources valides

Commencez par créer la stratégie en utilisant le modèle de stratégie Rust.

Tout d’abord, nous définissons les types qui représentent la charge utile de la demande. Nous allons déclarer un type RawValidationRequest personnalisé qui contient le Request et le Settings, au lieu d’utiliser le type ValidationRequest fourni par le SDK :

/// RawValidationRequest represents the request that is sent to the validate function by the Policy Server.
#[derive(Deserialize)]
pub(crate) struct RawValidationRequest {
    pub(crate) request: Request,
    pub(crate) settings: Settings,
}

#[derive(Serialize, Deserialize)]
/// Request represents the payload of the request.
pub(crate) struct Request {
    pub(crate) user: String,
    pub(crate) resource: String,
    pub(crate) action: String,
}

Ensuite, nous devons définir le type Settings et implémenter le trait Validatable :

/// Settings represents the settings of the policy.
#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(default, rename_all = "camelCase")]
pub(crate) struct Settings {
    pub(crate) valid_users: Vec<String>,
    pub(crate) valid_actions: Vec<String>,
    pub(crate) valid_resources: Vec<String>,
}

impl kubewarden::settings::Validatable for Settings {
    fn validate(&self) -> Result<(), String> {
        info!(LOG_DRAIN, "starting settings validation");

        if self.valid_users.is_empty() {
            return Err("validUsers cannot be empty".to_string());
        }

        if self.valid_actions.is_empty() {
            return Err("validActions cannot be empty".to_string());
        }

        if self.valid_resources.is_empty() {
            return Err("validResources cannot be empty".to_string());
        }

        Ok(())
    }
}

Enfin, nous définissons la fonction validate :

fn validate(payload: &[u8]) -> CallResult {
    let validation_request: RawValidationRequest =
        if let Ok(validation_request) = serde_json::from_slice(payload) {
            validation_request
        } else {
            return kubewarden::reject_request(
                Some("cannot unmarshal request".to_string()),
                None,
                None,
                None,
            );
        };

    info!(LOG_DRAIN, "starting validation");

    let request = validation_request.request;
    let settings = validation_request.settings;

    if settings.valid_users.contains(&request.user)
        && settings.valid_actions.contains(&request.action)
        && settings.valid_resources.contains(&request.resource)
    {
        info!(LOG_DRAIN, "accepting resource");
        kubewarden::accept_request()
    } else {
        kubewarden::reject_request(
            Some("this request is not accepted".to_string()),
            None,
            None,
            None,
        )
    }
}

Mutation

Modifions l’exemple précédent pour modifier la demande au lieu de la rejeter. Dans ce cas, les paramètres contiendront le defaultUser, defaultAction et defaultRequest qui seront utilisés pour modifier la demande si l’utilisateur, l’action ou la ressource n’est pas valide.

Nous devons mettre à jour le type Settings avec les nouveaux champs :

/// Settings represents the settings of the policy.
#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(default, rename_all = "camelCase")]
pub(crate) struct Settings {
    pub(crate) valid_users: Vec<String>,
    pub(crate) valid_actions: Vec<String>,
    pub(crate) valid_resources: Vec<String>,
    pub(crate) default_user: String,
    pub(crate) default_action: String,
    pub(crate) default_resource: String,
}

impl kubewarden::settings::Validatable for Settings {
    fn validate(&self) -> Result<(), String> {
        info!(LOG_DRAIN, "starting settings validation");

        if self.valid_users.is_empty() {
            return Err("validUsers cannot be empty".to_string());
        }

        if self.valid_actions.is_empty() {
            return Err("validActions cannot be empty".to_string());
        }

        if self.valid_resources.is_empty() {
            return Err("validResources cannot be empty".to_string());
        }

        if self.default_user.is_empty() {
            return Err("defaultUser cannot be empty".to_string());
        }

        if self.default_action.is_empty() {
            return Err("defaultAction cannot be empty".to_string());
        }

        if self.default_resource.is_empty() {
            return Err("defaultResource cannot be empty".to_string());
        }

        Ok(())
    }
}

et la fonction validate pour introduire la mutation :

fn validate(payload: &[u8]) -> CallResult {
    let validation_request: RawValidationRequest =
        if let Ok(validation_request) = serde_json::from_slice(payload) {
            validation_request
        } else {
            return kubewarden::reject_request(
                Some("cannot unmarshal request".to_string()),
                None,
                None,
                None,
            );
        };

    info!(LOG_DRAIN, "starting validation");

    let request = validation_request.request;
    let settings = validation_request.settings;

    if settings.valid_users.contains(&request.user)
        && settings.valid_actions.contains(&request.action)
        && settings.valid_resources.contains(&request.resource)
    {
        info!(LOG_DRAIN, "accepting request");
        return kubewarden::accept_request();
    }

    info!(LOG_DRAIN, "mutating request");
    let mut request = request;

    if !settings.valid_users.contains(&request.user) {
        request.user = settings.default_user;
    }

    if !settings.valid_actions.contains(&request.action) {
        request.action = settings.default_action;
    }

    if !settings.valid_resources.contains(&request.resource) {
        request.resource = settings.default_resource;
    }

    let mutated_request = serde_json::to_value(request)?;
    kubewarden::mutate_request(mutated_request)
}