The idea is to design a policy-engine package that would include all the logic for processing the policies on the resource, hence decoupling the policy processing logic from kubernetes components like policy-controller & admission-controller. The policy-engine can then be used individually to process the policies and get the results. With the current design, implementing the violation and event handling is difficult to decouple from the policy management.
This would require the policy-engine be decoupled from the kubernetes and policy client, it would expect a runtime.object(resource) and policy object as input, and provide the result in the form of list of events, violations and jsonPatches.
We have the following entry-points to trigger applying of policies:
- Admission Controller
The mutationwebhook configuration defines the β/mutateβ endpoint. The http server would process the incoming mutate url and forward to the handler. The handler gets all the policies and processes them on the incoming request.
- Policy Controller
The controller handler watches policy resource and calls the corresponding create/update/remove handler. Provides the api getPolicies used by mutationwebhook handler.
In the future, we also want to apply policies via a command line test tool.
As the policy application is possible from multiple points, it would be ideal to have a package with all the policy processing logic and decouple the other components.
The proposal is to design a policy-engine package which abstracts all the processing of mutation, validation & generators. This package will provide an interface to process existing and new resources.
This package can also be used for testing policies without going through the policy-controller and admission-controller, for example kubectl extension to verify if the policy is valid or a dry-run.
With this requirement, weβll need re-design and move the code into policy-engine package, with the admission-controller only calling an api like ProcessMutation() and generate the admission-response after. No processing of the policy would be done in the webhook. Similarly, on the policy-controller side each call to the create/update handler will call the ProcessExisting(). The policy-engine will not perform any modifications on the resource or policy, but just return the JSONpatches that need to be applied, events and policy violations to be generated. The policy engine would not have access to any clients(kubeclient or policyclient), but will operate on objects that are passed as arguments.
Interface Proposal
For the policy engine interface, we only expose 2 methods:
type PolicyEngine interface {
// ProcessMutation should be called from admission contoller
// when there is an creation / update of the resource
ProcessMutation(policy types.Policy, rawResource []byte) (patchBytes []byte, events []Events, err error))
// ProcessValidation should be called from admission contoller
// when there is an creation / update of the resource
ProcessValidation(policy types.Policy, rawResource []byte)
// ProcessExisting should be called from policy controller
// when there is an create / update of the policy
// we should process the policy on matched resource, generate violations accordingly
ProcessExisting(policy types.Policy, rawResource []byte) (violations []Violations, events []Events, err error)
}
For ProcessMutation method, we are processing the policy based on the new event of the resource, it returns JsonPatch and the slice of events. The JsonPatch will be added to admission response and then return to API server to create the actual object. Each of the events will be handled properly in admission controller based on the creation of the resource. Currently this function is extracted from mutationWebhook.
For ProcessExisting method, we are processing the policy on the existing resources based on the change of the policy. It can either be the creation or the update. If the policy contains mutate rule and non-nil JsonPatch is returned through Mutate(), the violation will be added to the returned slice, the event will be added accordingly to the events slice. The returned violations and events will be handled in the policy controller.
Once we agree on the package interface, we will need to design the implementation of the above three methods.