github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/site/book/07-effective-customizations/02-limiting-package-changes.md (about)

     1  ## Scenario:
     2  
     3  I’d like to limit what my package consumers can do with my package and it feels 
     4  safer to just provide a string replacement in one place so they know not to 
     5  alter the configuration outside of the few places that I designated as OK 
     6  places to change.
     7  
     8  Example deployment:
     9  ```yaml
    10  apiVersion: apps/v1
    11  kind: Deployment
    12  metadata: # kpt-merge: /nginx-deploy
    13    name: nginx-deploy
    14  spec:
    15    selector:
    16      matchLabels:
    17        app: nginx
    18    template:
    19      metadata:
    20        labels:
    21          app: nginx
    22      spec:
    23        containers:
    24          - name: backend
    25            image: nginx:1.16.1 # kpt-set: nginx:${tag}
    26  ```
    27  
    28  kpt configuration that uses a setter:
    29  ```yaml
    30  apiVersion: kpt.dev/v1
    31  kind: Kptfile
    32  metadata:
    33    name: dont-change-much
    34  pipeline:
    35    mutators:
    36      - image: gcr.io/kpt-fn/apply-setters:v0.2.0
    37        configMap:
    38          tag: 1.21
    39  ```
    40  
    41  ## Problems:
    42  
    43  1. The limitation by parameters does not guarantee that consumers are in fact 
    44  going to limit their changes to the parameters.  A popular pattern is using 
    45  kustomize to change output of other tools no matter what parameters had.  In 
    46  this particular case I am able to fork or patch this package and add:
    47  
    48  ```yaml
    49  securityContext:
    50      runAsNonRoot: false
    51  ```
    52  
    53  2. String replacements rarely describe the intent of the package author.
    54  When additional resources are added I need additional places where parameters 
    55  need to be applied.  I can easily add other containers to this deployment and
    56  the package author's rules are not clear and not easily validated.
    57  
    58  ## Solutions:
    59  
    60  1. General ways to describe policy already exist.  kpt has a [gatekeeper] 
    61  function that allows the author to describe intended limitations for a class 
    62  of resources or the entire package giving the consumer the freedom to customize 
    63  and get an error or a warning when the policy is violated. 
    64  
    65  In the sample provided by the function we see how to provide a policy that will
    66  clearly describe the intent using rego:
    67  
    68  ```yaml
    69  apiVersion: templates.gatekeeper.sh/v1
    70  kind: ConstraintTemplate
    71  metadata: # kpt-merge: /disallowroot
    72    name: disallowroot
    73  spec:
    74    crd:
    75      spec:
    76        names:
    77          kind: DisallowRoot
    78    targets:
    79      - target: admission.k8s.gatekeeper.sh
    80        rego: |-
    81          package disallowroot
    82          violation[{"msg": msg}] {
    83            not input.review.object.spec.template.spec.securityContext.runAsNonRoot
    84            msg := "Containers must not run as root"
    85          }
    86  ---
    87  apiVersion: constraints.gatekeeper.sh/v1beta1
    88  kind: DisallowRoot
    89  metadata: # kpt-merge: /disallowroot
    90    name: disallowroot
    91  spec:
    92    match:
    93      kinds:
    94        - apiGroups:
    95            - 'apps'
    96          kinds:
    97            - Deployment
    98  ```
    99  
   100  The Kptfile can enforce that resources comply with this policy every time
   101  `kpt fn render` is used:
   102  
   103  ```yaml
   104  apiVersion: kpt.dev/v1
   105  kind: Kptfile
   106  metadata:
   107    name: gatekeeper-disallow-root-user
   108  pipeline:
   109    validators:
   110      - image: gcr.io/kpt-fn/gatekeeper:v0.2
   111  ```
   112  
   113  [gatekeeper]: https://catalog.kpt.dev/gatekeeper/v0.2/