Skip to content

Latest commit

 

History

History
287 lines (265 loc) · 7.63 KB

README.md

File metadata and controls

287 lines (265 loc) · 7.63 KB

Module Specification

To pass data between the Kubernetes extension (host) and the WASM module we use the capabilities of WASI to read from the standard input and write to the standard output. Specifically the module reads the input data from the standard input (stdin) and writes the result to the standard output (stdout).

In general the data passed over stdin and stdout is JSON encoded and has the following format. The actual inner requestData and responseData depends on the use case (Authentication, Authorization, Admission) and is described in the following sections.

Input (Request):

{
	"request": requestData,
	"settings": {}
}

With the settings object you can pass parameters to your module. The settings, can be omitted if your module does not use them. The settings can have any format (e.g. contain a list, or nested objects, etc.).

Output (Response):

{
	"response": responseData,
	"error": "error message"
}

If the error is set in the output, the action is considered as failed and the response is ignored. Usually you send a result which contains either a response or an error.

If the module returns with a exit code not equal to 0 the action is considered as failed and the output is ignored.

Use cases

To implement one of the uses cases the module has to export the appropriate function name. If the function is called it has to read the input as described above and provide the appropriate output.

Authentication

Example

Input: User uses token magic-token:

{
  "request": {
    "apiVersion": "authentication.k8s.io/v1",
    "kind": "TokenReview",
    "spec": {
      "token": "magic-token",
      "audiences": [
        "https://kubernetes.default.svc.cluster.local"
      ]
    }
  }
}

Output: Token gets authenticated:

{
  "response": {
    "apiVersion": "authentication.k8s.io/v1",
    "kind": "TokenReview",
    "status": {
      "authenticated": true,
      "user": {
        "groups": [
          "magic-group"
        ],
        "uid": "0",
        "username": "magic-user"
      }
    }
  }
}

Authorization

Example

Input: User would like to list pods in the namespace default:

{
  "request": {
    "apiVersion": "authorization.k8s.io/v1",
    "kind": "SubjectAccessReview",
    "spec": {
      "resourceAttributes": {
        "namespace": "default",
        "verb": "list",
        "version": "v1",
        "resource": "pods"
      },
      "uid": "0",
      "user": "magic-user",
      "groups": [
        "magic-group",
        "system:authenticated"
      ]
    }
  }
}

Output: Request is not authorized:

{
  "response": {
    "apiVersion": "authorization.k8s.io/v1",
    "kind": "SubjectAccessReview",
    "status": {
      "allowed": false
    }
  }
}

Admission

Both mutating and validating admissions use the same function name.

If you provide a patch in your response to implement a mutating admission the following difference to the official AdmissionReview applies. The host does not understand the official patch type JSONPatch but it implements its on patch type Full. Instead of a patch you provide the full edited object as patch. This simplifies the module implementation because you don't have to generate a JSONPatch (RFC 6902).

Example

Validating Admission

Input: User wants to create a config map:

{
  "request": {
    "kind": "AdmissionReview",
    "apiVersion": "admission.k8s.io/v1",
    "request": {
      "uid": "678b2f02-0837-4262-95ea-5781b2864ac0",
      "kind": {
        "group": "",
        "version": "v1",
        "kind": "ConfigMap"
      },
      "resource": {
        "group": "",
        "version": "v1",
        "resource": "configmaps"
      },
      "requestKind": {
        "group": "",
        "version": "v1",
        "kind": "ConfigMap"
      },
      "requestResource": {
        "group": "",
        "version": "v1",
        "resource": "configmaps"
      },
      "name": "my-config",
      "namespace": "default",
      "operation": "CREATE",
      "userInfo": {
        "username": "magic-user",
        "uid": "0",
        "groups": [
          "magic-group",
          "system:authenticated"
        ]
      },
      "object": {
        "kind": "ConfigMap",
        "apiVersion": "v1",
        "metadata": {
          "name": "my-config",
          "namespace": "default",
          "uid": "869d6f79-dbe3-4ef0-8255-ef817e6e673e",
          "creationTimestamp": "2022-08-11T05:05:28Z"
        },
        "data": {
          "magic-value": "foobar",
          "not-allowed-value": "bar"
        }
      }
    }
  }
}

Output: Creation of configmap is rejected because it contains a value which is not allowed:

{
  "response": {
    "kind": "AdmissionReview",
    "apiVersion": "admission.k8s.io/v1",
    "response": {
      "uid": "678b2f02-0837-4262-95ea-5781b2864ac0",
      "allowed": false,
      "status": {
        "apiVersion": "v1",
        "kind": "Status",
        "message": "value not-allowed-value not allowed in configmap"
      }
    }
  }
}

Mutating Admission

Input: User creates configmap:

{
  "request": {
    "kind": "AdmissionReview",
    "apiVersion": "admission.k8s.io/v1",
    "request": {
      "uid": "695570da-9d1d-476a-a58a-15e051768042",
      "kind": {
        "group": "",
        "version": "v1",
        "kind": "ConfigMap"
      },
      "resource": {
        "group": "",
        "version": "v1",
        "resource": "configmaps"
      },
      "requestKind": {
        "group": "",
        "version": "v1",
        "kind": "ConfigMap"
      },
      "requestResource": {
        "group": "",
        "version": "v1",
        "resource": "configmaps"
      },
      "name": "my-config",
      "namespace": "default",
      "operation": "CREATE",
      "userInfo": {
        "username": "magic-user",
        "uid": "0",
        "groups": [
          "magic-group",
          "system:authenticated"
        ]
      },
      "object": {
        "kind": "ConfigMap",
        "apiVersion": "v1",
        "metadata": {
          "name": "my-config",
          "namespace": "default"
        },
        "data": {
          "not-allowed-value": "bar"
        }
      }
    }
  }
}

Output: Add magic-value: foobar to the configmap:

{
  "response": {
    "kind": "AdmissionReview",
    "apiVersion": "admission.k8s.io/v1",
    "response": {
      "uid": "695570da-9d1d-476a-a58a-15e051768042",
      "allowed": true,
      "patchType": "Full",
      "patch": "eyJhcGlWZXJzaW9uIjoidjEiLCJraW5kIjoiQ29uZmlnTWFwIiwiZGF0YSI6eyJtYWdpYy12YWx1ZSI6ImZvb2JhciIsIm5vdC1hbGxvd2VkLXZhbHVlIjoiYmFyIn0sIm1ldGFkYXRhIjp7Im5hbWUiOiJteS1jb25maWciLCJuYW1lc3BhY2UiOiJkZWZhdWx0In19Cg=="
    }
  }
}

Develop Modules

Rust

See: https://github.com/dvob/k8s-wasi-rs