vmware-archive / operator-builder

A Kubebuilder plugin to accelerate the development of Kubernetes operators
MIT License
41 stars 6 forks source link

feat: resource names for rbac #281

Closed scottd018 closed 2 years ago

scottd018 commented 2 years ago

To follow industry standard security best practices for least privileges, we should lock down the controller to only have access to the resources it manages by name. This would look something like this:

// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete,resourceNames=unique-name-from-manifest
const UniqueNameHere = "unique-name-from-manifest"

// CreateDeploymentNamespaceContourDeploy creates the contour-deploy Deployment resource.
func CreateDeploymentNamespaceContourDeployTwo(
    parent *ingressv1alpha1.ContourTwo,
    collection *edgev1alpha1.EdgeCollection,
) ([]client.Object, error) {

    resourceObjs := []client.Object{}
    var resourceObj = &unstructured.Unstructured{
        Object: map[string]interface{}{
            "apiVersion": "apps/v1",
            "kind":       "Deployment",
            "metadata": map[string]interface{}{
                "name":      UniqueNameHere,

This will include a couple other changes as well:

  1. Move the kubebuilder markers from each controllers .go file onto the actual resources. This tells us exactly which resources generated a specific piece of RBAC.
  2. Create a constant with the metadata.name of the resource as an exported value. This allows us to use the value across packages. We must ensure this name is unique.
  3. If the name field has a marker (e.g. parent.Spec.MyName), then we must fall back to not using the resourceNames logic as the name is variable and unpredicatable. A resource marker with a variable name would look something like this:
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete

// CreateDeploymentNamespaceContourDeploy creates the contour-deploy Deployment resource.
func CreateDeploymentNamespaceContourDeployTwo(
    parent *ingressv1alpha1.ContourTwo,
    collection *edgev1alpha1.EdgeCollection,
) ([]client.Object, error) {

    resourceObjs := []client.Object{}
    var resourceObj = &unstructured.Unstructured{
        Object: map[string]interface{}{
            "apiVersion": "apps/v1",
            "kind":       "Deployment",
            "metadata": map[string]interface{}{
                "name":      parent.Spec.MyName,