Skip to content

Commit

Permalink
Enable plugin to be run as a transformer
Browse files Browse the repository at this point in the history
Signed-off-by: Justin Kulikauskas <[email protected]>
  • Loading branch information
JustinKuli committed Oct 21, 2022
1 parent 51d7b6c commit b0dbfaf
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 10 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ For more about Open Cluster Management and its Policy Framework:
**NOTE:** This will default to placing the binary in `${HOME}/.config/kustomize/plugin/`. You can
change this by exporting `KUSTOMIZE_PLUGIN_HOME` to a different path.

#### Configuration
#### Configuration and use as a Generator

1. Create a `kustomization.yaml` file that points to `PolicyGenerator` manifest(s), with any
additional desired patches or customizations (see
Expand All @@ -80,6 +80,14 @@ For more about Open Cluster Management and its Policy Framework:
kustomize build --enable-alpha-plugins
```

#### Configuration and use as a Transformer

The plugin can also be used as a transformer, to wrap all incoming `resources` from a
`kustomization.yaml` file into one Policy. This feature is somewhat experimental.

An example configuration as a transformer (and its output) can be found in the
[`examples/generator/`](./examples/generator/) folder.

### As a standalone binary

In order to bypass Kustomize and run the generator binary directly:
Expand Down
4 changes: 4 additions & 0 deletions examples/generator/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resources:
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.5?ref=main
transformers:
- ./policyTransformer.yaml
105 changes: 105 additions & 0 deletions examples/generator/output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
apiVersion: apps.open-cluster-management.io/v1
kind: PlacementRule
metadata:
name: placement-transformed-policy
namespace: default
spec:
clusterSelector:
matchExpressions: []
---
apiVersion: policy.open-cluster-management.io/v1
kind: PlacementBinding
metadata:
name: binding-transformed-policy
namespace: default
placementRef:
apiGroup: apps.open-cluster-management.io
kind: PlacementRule
name: placement-transformed-policy
subjects:
- apiGroup: policy.open-cluster-management.io
kind: Policy
name: transformed-policy
---
apiVersion: policy.open-cluster-management.io/v1
kind: Policy
metadata:
annotations:
policy.open-cluster-management.io/categories: CM Configuration Management
policy.open-cluster-management.io/controls: CM-2 Baseline Configuration
policy.open-cluster-management.io/standards: NIST SP 800-53
name: transformed-policy
namespace: default
spec:
disabled: false
policy-templates:
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: transformed-policy
spec:
evaluationInterval:
compliant: 30m
noncompliant: 45s
object-templates:
- complianceType: musthave
objectDefinition:
apiVersion: v1
kind: Namespace
metadata:
annotations: {}
labels:
openshift.io/cluster-monitoring: "true"
name: open-cluster-management
remediationAction: inform
severity: low
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: transformed-policy2
spec:
evaluationInterval:
compliant: 30m
noncompliant: 45s
object-templates:
- complianceType: musthave
objectDefinition:
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
annotations: {}
name: open-cluster-management
namespace: open-cluster-management
spec:
targetNamespaces:
- open-cluster-management
remediationAction: inform
severity: low
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: transformed-policy3
spec:
evaluationInterval:
compliant: 30m
noncompliant: 45s
object-templates:
- complianceType: musthave
objectDefinition:
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
annotations: {}
name: advanced-cluster-management
namespace: open-cluster-management
spec:
channel: release-2.5
installPlanApproval: Automatic
name: advanced-cluster-management
source: redhat-operators
sourceNamespace: openshift-marketplace
remediationAction: inform
severity: low
16 changes: 16 additions & 0 deletions examples/generator/policyTransformer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: policy.open-cluster-management.io/v1
kind: PolicyGenerator
metadata:
name: policy-transformer

policyDefaults:
namespace: default
consolidateManifests: false
evaluationInterval:
compliant: 30m
noncompliant: 45s

policies:
- name: transformed-policy
manifests:
- path: stdin
20 changes: 11 additions & 9 deletions internal/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,16 +807,18 @@ func (p *Plugin) assertValidConfig() error {
)
}

_, err := os.Stat(manifest.Path)
if err != nil {
return fmt.Errorf(
"could not read the manifest path %s in policy %s", manifest.Path, policy.Name,
)
}
if manifest.Path != "stdin" {
_, err := os.Stat(manifest.Path)
if err != nil {
return fmt.Errorf(
"could not read the manifest path %s in policy %s", manifest.Path, policy.Name,
)
}

err = verifyManifestPath(p.baseDirectory, manifest.Path)
if err != nil {
return err
err = verifyManifestPath(p.baseDirectory, manifest.Path)
if err != nil {
return err
}
}

evalInterval := manifest.EvaluationInterval
Expand Down
23 changes: 23 additions & 0 deletions internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ func getManifests(policyConf *types.PolicyConfig) ([][]map[string]interface{}, e

// Handle when a Kustomization directory is specified
hasKustomize := false

for _, f := range files {
_, filename := path.Split(f.Name())
if filename == "kustomization.yml" || filename == "kustomization.yaml" {
hasKustomize = true
manifestFiles, err = processKustomizeDir(manifest.Path)

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -187,6 +189,27 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]map[string
continue
}

// Annotations with these prefixes might be added to resources by kustomize,
// and should be removed when the resource is wrapped in a policy.
prefixesToDelete := []string{
"config.kubernetes.io/path",
"config.kubernetes.io/index",
"config.k8s.io/id",
"kustomize.config.k8s.io/id",
"internal.config.kubernetes.io",
}
annotations, _, _ := unstructured.NestedStringMap(manifest, "metadata", "annotations")

for key := range annotations {
for _, prefix := range prefixesToDelete {
if strings.HasPrefix(key, prefix) {
delete(annotations, key)
}
}
}

_ = unstructured.SetNestedStringMap(manifest, annotations, "metadata", "annotations")

objTemplate := map[string]interface{}{
"complianceType": complianceType,
"objectDefinition": manifest,
Expand Down

0 comments on commit b0dbfaf

Please sign in to comment.