|
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. |
Escribiendo directivas en bruto
Las directivas en bruto son directivas que pueden evaluar documentos JSON arbitrarios. Para más información sobre las directivas en bruto, consulta la página de directivas en bruto.
Ejemplos
Por favor, consulta Introducción a WASI para obtener una visión general del modo de ejecución de WASI.
|
Marcas la política como |
Validación
Como ejemplo, puedes escribir una política que acepte una solicitud en el siguiente formato:
{
"request": {
"user": "alice",
"action": "delete",
"resource": "products"
}
}
y valida que:
-
userestá en la lista de usuarios válidos -
actionestá en la lista de acciones válidas -
resourceestá en la lista de recursos válidos
Comienza por estructurar la política utilizando la plantilla de política WASI de go.
Primero, necesitas definir los tipos que representan la carga útil de la solicitud.
Deberías declarar un tipo RawValidationRequest personalizado que contenga Request y Settings, en lugar de usar el tipo ValidationRequest proporcionado por el kw_sdk.go:
// RawValidationRequest represents the request that is sent to the validate function by the Policy Server.
type RawValidationRequest struct {
Request Request `+json:"request"+`
// Raw policies can have settings.
Settings Settings `+json:"settings"+`
}
// Request represents the payload of the request.
type Request struct {
User string `+json:"user"+`
Action string `+json:"action"+`
Resource string `+json:"resource"+`
}
Luego defines el tipo Settings y la función validateSettings en el archivo settings.go:
// Settings represents the settings of the policy.
type Settings struct {
ValidUsers []string `+json:"validUsers"+`
ValidActions []string `+json:"validActions"+`
ValidResources []string `+json:"validResources"+`
}
func validateSettings(input []byte) []byte {
var response SettingsValidationResponse
settings := &Settings{}
if err := json.Unmarshal(input, &settings); err != nil {
response = RejectSettings(Message(fmt.Sprintf("cannot unmarshal settings: %v", err)))
} else {
response = validateCliSettings(settings)
}
responseBytes, err := json.Marshal(&response)
if err != nil {
log.Fatalf("can not marshal validation response: %v", err)
}
return responseBytes
}
func validateCliSettings(settings *Settings) SettingsValidationResponse {
if len(settings.ValidUsers) == 0 {
return RejectSettings(Message(
"At least one valid user must be specified"))
}
if len(settings.ValidActions) == 0 {
return RejectSettings(Message(
"At least one valid action must be specified"))
}
if len(settings.ValidResources) == 0 {
return RejectSettings(Message(
"At least one valid resource must be specified"))
}
return AcceptSettings()
}
Finalmente, actualizas la lógica de validación en validate.go:
func validate(input []byte) []byte {
var validationRequest RawValidationRequest
validationRequest.Settings = Settings{}
decoder := json.NewDecoder(strings.NewReader(string(input)))
decoder.DisallowUnknownFields()
err := decoder.Decode(&validationRequest)
if err != nil {
return marshalValidationResponseOrFail(
RejectRequest(
Message(fmt.Sprintf("Error deserializing validation request: %v", err)),
Code(400)))
}
return marshalValidationResponseOrFail(
validateRequest(validationRequest.Settings, validationRequest.Request))
}
func marshalValidationResponseOrFail(response ValidationResponse) []byte {
responseBytes, err := json.Marshal(&response)
if err != nil {
log.Fatalf("cannot marshal validation response: %v", err)
}
return responseBytes
}
func validateRequest(settings Settings, request Request) ValidationResponse {
if slices.Contains(settings.ValidUsers, request.User) &&
slices.Contains(settings.ValidActions, request.Action) &&
slices.Contains(settings.ValidResources, request.Resource) {
return AcceptRequest()
}
return RejectRequest(
Message("The request cannot be accepted."),
Code(403))
}
Mutación
Puedes cambiar el ejemplo anterior para mutar la solicitud en lugar de rechazarla.
En este caso, los ajustes deben contener defaultUser, defaultAction y defaultRequest para usarlos en la mutación de la solicitud si el usuario, la acción o el recurso no son válidos.
Necesitas actualizar el tipo Settings con los nuevos campos:
// Settings represents the settings of the policy.
type Settings struct {
ValidUsers []string `+json:"validUsers"+`
ValidActions []string `+json:"validActions"+`
ValidResources []string `+json:"validResources"+`
DefaultUser string `+json:"defaultUser"+`
DefaultAction string `+json:"defaultAction"+`
DefaultResource string `+json:"defaultResource"+`
}
func validateCliSettings(settings *Settings) SettingsValidationResponse {
if len(settings.ValidUsers) == 0 {
return RejectSettings(Message(
"At least one valid user must be specified"))
}
if len(settings.ValidActions) == 0 {
return RejectSettings(Message(
"At least one valid action must be specified"))
}
if len(settings.ValidResources) == 0 {
return RejectSettings(Message(
"At least one valid resource must be specified"))
}
if settings.DefaultUser == "" {
return RejectSettings(Message(
"Default user must be specified"))
}
if settings.DefaultAction == "" {
return RejectSettings(Message(
"Default action must be specified"))
}
if settings.DefaultResource == "" {
return RejectSettings(Message(
"Default resource must be specified"))
}
return AcceptSettings()
}
También necesitas actualizar la estructura ValidationResponse y la función MutateRequest en kw_sdk.go para eliminar los tipos específicos de Kubernetes y usar tipos Admission Controller en su lugar:
// ValidationResponse defines the response given when validating a request
type ValidationResponse struct {
Accepted bool `+json:"accepted"+`
// Optional - ignored if accepted
Message *string `+json:"message,omitempty"+`
// Optional - ignored if accepted
Code *uint16 `+json:"code,omitempty"+`
// Optional - used only by mutating policies
MutatedObject *Request `+json:"mutated_object,omitempty"+`
}
// MutateRequest accepts the request. The given `+mutatedObject+` is how
// the evaluated object must look once accepted
func MutateRequest(mutatedObject *Request) ValidationResponse {
return ValidationResponse{
Accepted: true,
MutatedObject: mutatedObject,
}
}
Ahora puedes actualizar la función validate para mutar la solicitud si no es válida:
func validateRequest(settings Settings, request Request) ValidationResponse {
if slices.Contains(settings.ValidUsers, request.User) &&
slices.Contains(settings.ValidActions, request.Action) &&
slices.Contains(settings.ValidResources, request.Resource) {
return AcceptRequest()
}
if !slices.Contains(settings.ValidUsers, request.User) {
request.User = settings.DefaultUser
}
if !slices.Contains(settings.ValidActions, request.Action) {
request.Action = settings.DefaultAction
}
if !slices.Contains(settings.ValidResources, request.Resource) {
request.Resource = settings.DefaultResource
}
return MutateRequest(&request)
}