Squashed 'acm-hub-bootstrap/' content from commit aea23ee
git-subtree-dir: acm-hub-bootstrap git-subtree-split: aea23ee88fafd5cab0e2d9189f872159c5f16b8e
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
sealed-secrets-key.yaml
|
||||||
|
slack-token-key.yaml
|
||||||
|
*-private.yaml
|
||||||
|
eso-token-*.yaml
|
||||||
38
README.md
Normal file
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
### Introduction
|
||||||
|
|
||||||
|
This repository is used to bootstrap the RHACM Hub cluster as well as hold the ACM configuration
|
||||||
|
I use in my homelab environment. It is referenced by the [cluster-config](https://github.com/gnunn-gitops/cluster-config) repo for the `local.hub` cluster's ACM applications (Hub, Policies and Observerability).
|
||||||
|
|
||||||
|
From the perspective of bootstrapping the Hub there are a couple of different ways to go. You could
|
||||||
|
manually install OpenShift GitOps and have it bootstrap everything on the Hub including RHACM. However while
|
||||||
|
I did consider that approach I'm using ACM to bootstrap my managed clusters and I wanted to use the exact same workflow
|
||||||
|
if I could for the Hub. This is because I wanted to avoid having to create a tweaked workflow just for the Hub.
|
||||||
|
|
||||||
|
### Bootstrap Process
|
||||||
|
|
||||||
|
The bootstrap process, encapsulated in the `bootstrap.sh` script, is as follows:
|
||||||
|
|
||||||
|
1. Install the RHACM operator and wait for it to complete
|
||||||
|
2. Install the MultiClusterHub custom resource and wait for it to be in the Running phase
|
||||||
|
3. Deploy all of the RHACM policies including the policy that deploys the OpenShift
|
||||||
|
GitOps operator with the bootstrap application
|
||||||
|
4. Label the Hub cluster, `local-cluster`, with the label `gitops=local.hub`. This trigger the
|
||||||
|
GitOps policy we deployed in step #3 to install OpenShift GitOps on the Hub cluster and
|
||||||
|
deploy the bootstrap application pointing to the repo and path needed for this cluster, i.e.
|
||||||
|
`local.home`
|
||||||
|
|
||||||
|
At this point the GitOps operator deploys everything the Hub cluster requires including storage, operators, etc
|
||||||
|
as well as other ACM components. In particular, the components that the script deployed (Hub + Policies) have
|
||||||
|
Argo applications that will take over managing these.
|
||||||
|
|
||||||
|
With the script bootstrapping the Hub because a one command affair. Once the command completes successfully
|
||||||
|
I walk away for 20-30 minutes while everything gets sorted out.
|
||||||
|
|
||||||
|
### Side-note on LVM Operator
|
||||||
|
|
||||||
|
If you are running a SNO cluster like I am and using the LVM Operator make sure that whatever device you are
|
||||||
|
using for storage with it is free. For example, if you are doing a reinstall of the hub (or other cluster), after
|
||||||
|
the cluster is provisioned but before you provision Day 2 ops ssh to the cluster and run `lsblk` to make sure
|
||||||
|
the device is empty with no partitions.
|
||||||
|
|
||||||
|
A reminder for future me. :)
|
||||||
45
bootstrap.sh
Executable file
45
bootstrap.sh
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LANG=C
|
||||||
|
SLEEP_SECONDS=30
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Installing RHACM Operator."
|
||||||
|
|
||||||
|
kustomize build github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.9 | oc apply -f -
|
||||||
|
|
||||||
|
echo "Pause $SLEEP_SECONDS seconds for the creation of the rhacm-operator..."
|
||||||
|
sleep $SLEEP_SECONDS
|
||||||
|
|
||||||
|
echo "Waiting for operator to start"
|
||||||
|
until oc get deployment multiclusterhub-operator -n open-cluster-management
|
||||||
|
do
|
||||||
|
sleep 10;
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Installing the MultiClusterHub"
|
||||||
|
|
||||||
|
kustomize build github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/base | oc apply -f -
|
||||||
|
|
||||||
|
echo "Waiting for hub to be installed"
|
||||||
|
|
||||||
|
until [[ $(oc get multiclusterhub multiclusterhub -n open-cluster-management -o jsonpath='{.status.phase}') == 'Running' ]]
|
||||||
|
do
|
||||||
|
echo "Waiting for hub, current status:"
|
||||||
|
oc get multiclusterhub multiclusterhub -n open-cluster-management
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Installing policies and initial secrets"
|
||||||
|
|
||||||
|
kustomize build bootstrap/secrets/base | oc apply -f -
|
||||||
|
kustomize build bootstrap/policies/overlays/default --enable-alpha-plugins | oc apply -f -
|
||||||
|
|
||||||
|
echo "Labeling cluster with 'gitops: local.home'"
|
||||||
|
oc label managedcluster local-cluster gitops=local.hub --overwrite=true
|
||||||
|
|
||||||
|
echo "Check policy compliance with the following command:"
|
||||||
|
echo " oc get policy -A"
|
||||||
|
|
||||||
|
echo "Once GitOps configuration is complete you may need to run the following to fix Unknown status\n"
|
||||||
|
echo " oc delete secret local-cluster-import -n local-cluster\n"
|
||||||
1
bootstrap/install-gitops/README.md
Normal file
1
bootstrap/install-gitops/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Experimental, not used at the momentgit add
|
||||||
58
bootstrap/install-gitops/setup.sh
Normal file
58
bootstrap/install-gitops/setup.sh
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LANG=C
|
||||||
|
SLEEP_SECONDS=45
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Installing GitOps Operator."
|
||||||
|
|
||||||
|
kustomize build ../../components/policies/gitops/base/manifests/gitops-subscription | oc apply -f -
|
||||||
|
|
||||||
|
echo "Pause $SLEEP_SECONDS seconds for the creation of the gitops-operator..."
|
||||||
|
sleep $SLEEP_SECONDS
|
||||||
|
|
||||||
|
echo "Waiting for operator to start"
|
||||||
|
until oc get deployment gitops-operator-controller-manager -n openshift-operators
|
||||||
|
do
|
||||||
|
sleep 5;
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Waiting for openshift-gitops namespace to be created"
|
||||||
|
until oc get ns openshift-gitops
|
||||||
|
do
|
||||||
|
sleep 5;
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Waiting for deployments to start"
|
||||||
|
until oc get deployment cluster -n openshift-gitops
|
||||||
|
do
|
||||||
|
sleep 5;
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Waiting for all pods to be created"
|
||||||
|
deployments=(cluster kam openshift-gitops-applicationset-controller openshift-gitops-redis openshift-gitops-repo-server openshift-gitops-server)
|
||||||
|
for i in "${deployments[@]}";
|
||||||
|
do
|
||||||
|
echo "Waiting for deployment $i";
|
||||||
|
oc rollout status deployment $i -n openshift-gitops
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Apply overlay to override default instance"
|
||||||
|
# echo "Create default instance of gitops operator"
|
||||||
|
kustomize build ../../components/policies/gitops/base/manifests/gitops-instance/base |
|
||||||
|
yq -y ".spec.repo.env |= map(select(.name == \"INFRASTRUCTURE_ID\").value=\"$INFRASTRUCTURE_ID\")" |
|
||||||
|
yq -y ".spec.repo.env |= map(select(.name == \"CLUSTER_ID\").value=\"$CLUSTER_ID\")" |
|
||||||
|
yq -y ".spec.repo.env |= map(select(.name == \"CLUSTER_NAME\").value=\"$CLUSTER_NAME\")" |
|
||||||
|
yq -y ".spec.repo.env |= map(select(.name == \"SUB_DOMAIN\").value=\"$SUB_DOMAIN\")" |
|
||||||
|
oc apply -f -
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
echo "Waiting for all pods to redeploy"
|
||||||
|
deployments=(cluster kam openshift-gitops-applicationset-controller openshift-gitops-redis openshift-gitops-repo-server openshift-gitops-server)
|
||||||
|
for i in "${deployments[@]}";
|
||||||
|
do
|
||||||
|
echo "Waiting for deployment $i";
|
||||||
|
oc rollout status deployment $i -n openshift-gitops
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "GitOps Operator ready"
|
||||||
8
bootstrap/policies/overlays/default/kustomization.yaml
Normal file
8
bootstrap/policies/overlays/default/kustomization.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace: acm-policies
|
||||||
|
|
||||||
|
namespace: acm-policies
|
||||||
|
|
||||||
|
resources:
|
||||||
|
# - ../../../../components/policies/compliance/base
|
||||||
|
- ../../../../components/policies/cert-expiration/base
|
||||||
|
- ../../../../components/policies/gitops/base
|
||||||
1
bootstrap/secrets/base/README.md
Normal file
1
bootstrap/secrets/base/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Bootstrap tokens for ESO to access Doppler projects, note that these secrets are not in git.
|
||||||
4
bootstrap/secrets/base/hub-secrets-namespace.yaml
Normal file
4
bootstrap/secrets/base/hub-secrets-namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: hub-secrets
|
||||||
10
bootstrap/secrets/base/kustomization.yaml
Normal file
10
bootstrap/secrets/base/kustomization.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- hub-secrets-namespace.yaml
|
||||||
|
# Note these secrets are not stored in git and only applied during bootstrap process
|
||||||
|
# They are the tokens for accessing the Doppler secrets SaaS service where secrets are stored
|
||||||
|
- eso-token-cluster-push-secret.yaml
|
||||||
|
- eso-token-cluster-home-secret.yaml
|
||||||
|
- eso-token-cluster-hub-secret.yaml
|
||||||
|
- eso-token-cluster-rhdp-secret.yaml
|
||||||
|
- eso-token-cluster-microshift-secret.yaml
|
||||||
8
bootstrap/secrets/base/namespace.yaml
Normal file
8
bootstrap/secrets/base/namespace.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
openshift.io/description: ACM Policies
|
||||||
|
openshift.io/display-name: ACM Policies
|
||||||
|
labels:
|
||||||
|
name: acm-policies
|
||||||
12
components/apps/acm/overlays/hub/kustomization.yaml
Normal file
12
components/apps/acm/overlays/hub/kustomization.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
resources:
|
||||||
|
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.12
|
||||||
|
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/base
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/channel
|
||||||
|
value: 'release-2.13'
|
||||||
|
target:
|
||||||
|
kind: Subscription
|
||||||
|
name: advanced-cluster-management
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: observability-metrics-custom-allowlist
|
||||||
|
namespace: open-cluster-management-observability
|
||||||
|
data:
|
||||||
|
metrics_list.yaml: |
|
||||||
|
names:
|
||||||
|
- argocd_cluster_info
|
||||||
|
- argocd-server-metrics
|
||||||
|
- argocd_app_info
|
||||||
|
- argocd_app_sync_total
|
||||||
|
- argocd_app_reconcile_count
|
||||||
|
- argocd_app_reconcile_bucket
|
||||||
|
- argocd_app_k8s_request_total
|
||||||
|
- argocd_kubectl_exec_pending
|
||||||
|
- argocd-metrics
|
||||||
|
- argocd_cluster_api_resource_objects
|
||||||
|
- argocd_cluster_api_resources
|
||||||
|
- argocd_cluster_events_total
|
||||||
|
- argocd_git_request_total
|
||||||
|
- argocd_git_request_duration_seconds_bucket
|
||||||
|
- argocd-repo-server
|
||||||
|
- argocd_redis_request_total
|
||||||
|
- process_start_time_seconds
|
||||||
|
- workqueue_depth
|
||||||
|
- go_memstats_heap_alloc_bytes
|
||||||
|
- process_cpu_seconds_total
|
||||||
|
- go_goroutines
|
||||||
|
- go_gc_duration_seconds
|
||||||
|
- grpc_server_handled_total
|
||||||
4212
components/apps/acm/overlays/observability/gitops-dashboard.json
Normal file
4212
components/apps/acm/overlays/observability/gitops-dashboard.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
|||||||
|
namespace: open-cluster-management-observability
|
||||||
|
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
labels:
|
||||||
|
grafana-custom-dashboard: "true"
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/observability
|
||||||
|
- custom-metrics-allowlist.yaml
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: gitops-dashboard
|
||||||
|
files:
|
||||||
|
- gitops.json=gitops-dashboard.json
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/storageConfig/storageClass
|
||||||
|
value: lvms-vg1
|
||||||
|
- op: replace
|
||||||
|
path: /spec/observabilityAddonSpec/interval
|
||||||
|
value: 60
|
||||||
|
- op: add
|
||||||
|
path: /spec/advanced
|
||||||
|
value:
|
||||||
|
alertmanager:
|
||||||
|
replicas: 1
|
||||||
|
grafana:
|
||||||
|
replicas: 1
|
||||||
|
observatoriumAPI:
|
||||||
|
replicas: 1
|
||||||
|
query:
|
||||||
|
replicas: 1
|
||||||
|
queryFrontend:
|
||||||
|
replicas: 1
|
||||||
|
queryFrontendMemcached:
|
||||||
|
replicas: 1
|
||||||
|
rbacQueryProxy:
|
||||||
|
replicas: 1
|
||||||
|
receive:
|
||||||
|
replicas: 1
|
||||||
|
target:
|
||||||
|
kind: MultiClusterObservability
|
||||||
|
name: observability
|
||||||
3
components/clusters/base/kustomization.yaml
Normal file
3
components/clusters/base/kustomization.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
resources:
|
||||||
|
- local-home.yaml
|
||||||
|
- local-hub.yaml
|
||||||
18
components/clusters/base/local-home.yaml
Normal file
18
components/clusters/base/local-home.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: cluster.open-cluster-management.io/v1
|
||||||
|
kind: ManagedCluster
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
open-cluster-management/created-via: other
|
||||||
|
labels:
|
||||||
|
cloud: Other
|
||||||
|
cluster.open-cluster-management.io/clusterset: dev
|
||||||
|
gitops: local.home
|
||||||
|
color: "0066CC"
|
||||||
|
name: home
|
||||||
|
vendor: OpenShift
|
||||||
|
name: home
|
||||||
|
spec:
|
||||||
|
hubAcceptsClient: true
|
||||||
|
leaseDurationSeconds: 60
|
||||||
|
managedClusterClientConfigs:
|
||||||
|
- url: https://api.home.ocplab.com:6443
|
||||||
20
components/clusters/base/local-hub.yaml
Normal file
20
components/clusters/base/local-hub.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: cluster.open-cluster-management.io/v1
|
||||||
|
kind: ManagedCluster
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
open-cluster-management/created-via: other
|
||||||
|
labels:
|
||||||
|
cloud: Other
|
||||||
|
cluster.open-cluster-management.io/clusterset: default
|
||||||
|
gitops: local.hub
|
||||||
|
color: "3E8635"
|
||||||
|
local-cluster: "true"
|
||||||
|
name: local-cluster
|
||||||
|
velero.io/exclude-from-backup: "true"
|
||||||
|
vendor: OpenShift
|
||||||
|
name: local-cluster
|
||||||
|
spec:
|
||||||
|
hubAcceptsClient: true
|
||||||
|
leaseDurationSeconds: 60
|
||||||
|
managedClusterClientConfigs:
|
||||||
|
- url: https://api.hub.ocplab.com:6443
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
resources:
|
||||||
|
- policy-cert-expiration.yaml
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: certificate-expiration
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/categories: SC System and Communications Protection
|
||||||
|
policy.open-cluster-management.io/standards: NIST SP 800-53
|
||||||
|
policy.open-cluster-management.io/controls: SC-8 Transmission Confidentiality and Integrity
|
||||||
|
spec:
|
||||||
|
disabled: false
|
||||||
|
remediationAction: inform
|
||||||
|
policy-templates:
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: CertificatePolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-certificate
|
||||||
|
spec:
|
||||||
|
namespaceSelector:
|
||||||
|
include:
|
||||||
|
- default
|
||||||
|
exclude:
|
||||||
|
- kube-*
|
||||||
|
remediationAction: inform
|
||||||
|
severity: low
|
||||||
|
minimumDuration: 300h
|
||||||
|
---
|
||||||
|
apiVersion: apps.open-cluster-management.io/v1
|
||||||
|
kind: PlacementRule
|
||||||
|
metadata:
|
||||||
|
name: certificate-expiration-placement
|
||||||
|
spec:
|
||||||
|
clusterSelector:
|
||||||
|
matchExpressions: []
|
||||||
|
clusterConditions:
|
||||||
|
- status: "True"
|
||||||
|
type: ManagedClusterConditionAvailable
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: certificate-expiration-placement
|
||||||
|
placementRef:
|
||||||
|
name: certificate-expiration-placement
|
||||||
|
apiGroup: apps.open-cluster-management.io
|
||||||
|
kind: PlacementRule
|
||||||
|
subjects:
|
||||||
|
- name: certificate-expiration
|
||||||
|
apiGroup: policy.open-cluster-management.io
|
||||||
|
kind: Policy
|
||||||
2
components/policies/compliance/base/kustomization.yaml
Normal file
2
components/policies/compliance/base/kustomization.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
resources:
|
||||||
|
- scan-nist-800-53-policy.yaml
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: scan-nist-800-53
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/standards: NIST-CSF
|
||||||
|
policy.open-cluster-management.io/categories: PR.IP Information Protection Processes and Procedures
|
||||||
|
policy.open-cluster-management.io/controls: PR.IP-1 Baseline Configuration
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
disabled: false
|
||||||
|
policy-templates:
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: scan-nist-800-53
|
||||||
|
spec:
|
||||||
|
remediationAction: inform
|
||||||
|
severity: high
|
||||||
|
object-templates:
|
||||||
|
- complianceType: mustnothave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: compliance.openshift.io/v1alpha1
|
||||||
|
kind: ComplianceCheckResult
|
||||||
|
metadata:
|
||||||
|
namespace: openshift-compliance
|
||||||
|
labels:
|
||||||
|
compliance.openshift.io/check-status: FAIL
|
||||||
|
compliance.openshift.io/suite: cis-compliance
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: binding-scan-nist-800-53
|
||||||
|
placementRef:
|
||||||
|
name: placement-scan-nist-800-53
|
||||||
|
kind: PlacementRule
|
||||||
|
apiGroup: apps.open-cluster-management.io
|
||||||
|
subjects:
|
||||||
|
- name: scan-nist-800-53
|
||||||
|
kind: Policy
|
||||||
|
apiGroup: policy.open-cluster-management.io
|
||||||
|
---
|
||||||
|
apiVersion: apps.open-cluster-management.io/v1
|
||||||
|
kind: PlacementRule
|
||||||
|
metadata:
|
||||||
|
name: placement-scan-nist-800-53
|
||||||
|
spec:
|
||||||
|
clusterConditions:
|
||||||
|
- status: 'True'
|
||||||
|
type: ManagedClusterConditionAvailable
|
||||||
|
clusterSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- {key: vendor, operator: In, values: ["OpenShift"]}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
openshift.io/description: ACM Configuration Policies
|
||||||
|
openshift.io/display-name: ACM Configuration Policies
|
||||||
|
name: acm-config-policies
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
# Sample policy to configure gatekeeper to exclude namespaces from certain processes for all constraints in the cluster
|
||||||
|
# See: https://github.com/open-policy-agent/gatekeeper/tree/release-3.3#exempting-namespaces-from-gatekeeper
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-config-exclude-namespaces
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/standards: NIST SP 800-53
|
||||||
|
policy.open-cluster-management.io/categories: CM Configuration Management
|
||||||
|
policy.open-cluster-management.io/controls: CM-2 Baseline Configuration
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
disabled: false
|
||||||
|
policy-templates:
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-config-exclude-namespaces
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce # will be overridden by remediationAction in parent policy
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: mustonlyhave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: config.gatekeeper.sh/v1alpha1
|
||||||
|
kind: Config
|
||||||
|
metadata:
|
||||||
|
name: config
|
||||||
|
namespace: openshift-gatekeeper-system
|
||||||
|
spec:
|
||||||
|
match:
|
||||||
|
- excludedNamespaces:
|
||||||
|
- hive
|
||||||
|
- kube-node-lease
|
||||||
|
- kube-public
|
||||||
|
- kube-storage-version-migrator-operator
|
||||||
|
- kube-system
|
||||||
|
- open-cluster-management
|
||||||
|
- open-cluster-management-hub
|
||||||
|
- open-cluster-management-agent
|
||||||
|
- open-cluster-management-agent-addon
|
||||||
|
- openshift
|
||||||
|
- openshift-apiserver
|
||||||
|
- openshift-apiserver-operator
|
||||||
|
- openshift-authentication
|
||||||
|
- openshift-authentication-operator
|
||||||
|
- openshift-cloud-credential-operator
|
||||||
|
- openshift-cluster-csi-drivers
|
||||||
|
- openshift-cluster-machine-approver
|
||||||
|
- openshift-cluster-node-tuning-operator
|
||||||
|
- openshift-cluster-samples-operator
|
||||||
|
- openshift-cluster-storage-operator
|
||||||
|
- openshift-cluster-version
|
||||||
|
- openshift-compliance
|
||||||
|
- openshift-config
|
||||||
|
- openshift-config-managed
|
||||||
|
- openshift-config-operator
|
||||||
|
- openshift-console
|
||||||
|
- openshift-console-operator
|
||||||
|
- openshift-console-user-settings
|
||||||
|
- openshift-controller-manager
|
||||||
|
- openshift-controller-manager-operator
|
||||||
|
- openshift-dns
|
||||||
|
- openshift-dns-operator
|
||||||
|
- openshift-etcd
|
||||||
|
- openshift-etcd-operator
|
||||||
|
- openshift-gatekeeper-operator
|
||||||
|
- openshift-gatekeeper-system
|
||||||
|
- openshift-image-registry
|
||||||
|
- openshift-infra
|
||||||
|
- openshift-ingress
|
||||||
|
- openshift-ingress-canary
|
||||||
|
- openshift-ingress-operator
|
||||||
|
- openshift-insights
|
||||||
|
- openshift-kni-infra
|
||||||
|
- openshift-kube-apiserver
|
||||||
|
- openshift-kube-apiserver-operator
|
||||||
|
- openshift-kube-controller-manager
|
||||||
|
- openshift-kube-controller-manager-operator
|
||||||
|
- openshift-kube-scheduler
|
||||||
|
- openshift-kube-scheduler-operator
|
||||||
|
- openshift-kube-storage-version-migrator
|
||||||
|
- openshift-kube-storage-version-migrator-operator
|
||||||
|
- openshift-kubevirt-infra
|
||||||
|
- openshift-machine-api
|
||||||
|
- openshift-machine-config-operator
|
||||||
|
- openshift-marketplace
|
||||||
|
- openshift-monitoring
|
||||||
|
- openshift-multus
|
||||||
|
- openshift-network-diagnostics
|
||||||
|
- openshift-network-operator
|
||||||
|
- openshift-node
|
||||||
|
- openshift-oauth-apiserver
|
||||||
|
- openshift-openstack-infra
|
||||||
|
- openshift-operators
|
||||||
|
- openshift-operator-lifecycle-manager
|
||||||
|
- openshift-ovirt-infra
|
||||||
|
- openshift-ovn-kubernetes
|
||||||
|
- openshift-sdn
|
||||||
|
- openshift-service-ca
|
||||||
|
- openshift-service-ca-operator
|
||||||
|
- openshift-user-workload-monitoring
|
||||||
|
- openshift-vsphere-infra
|
||||||
|
processes:
|
||||||
|
- '*'
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: binding-policy-gatekeeper-config-exclude-namespaces
|
||||||
|
placementRef:
|
||||||
|
name: placement-policy-gatekeeper-config-exclude-namespaces
|
||||||
|
kind: PlacementRule
|
||||||
|
apiGroup: apps.open-cluster-management.io
|
||||||
|
subjects:
|
||||||
|
- name: policy-gatekeeper-config-exclude-namespaces
|
||||||
|
kind: Policy
|
||||||
|
apiGroup: policy.open-cluster-management.io
|
||||||
|
---
|
||||||
|
apiVersion: apps.open-cluster-management.io/v1
|
||||||
|
kind: PlacementRule
|
||||||
|
metadata:
|
||||||
|
name: placement-policy-gatekeeper-config-exclude-namespaces
|
||||||
|
spec:
|
||||||
|
clusterConditions:
|
||||||
|
- status: "True"
|
||||||
|
type: ManagedClusterConditionAvailable
|
||||||
|
clusterSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- {key: policy, operator: In, values: ["opa"]}
|
||||||
139
components/policies/gatekeeper/gatekeeper-install-policy.yaml
Normal file
139
components/policies/gatekeeper/gatekeeper-install-policy.yaml
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-operator
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/standards: NIST SP 800-53
|
||||||
|
policy.open-cluster-management.io/categories: CM Configuration Management
|
||||||
|
policy.open-cluster-management.io/controls: CM-2 Baseline Configuration
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
disabled: false
|
||||||
|
policy-templates:
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator-ns
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: high
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: openshift-gatekeeper-operator
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator-catalog-source
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: high
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: operators.coreos.com/v1alpha1
|
||||||
|
kind: CatalogSource
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator
|
||||||
|
namespace: openshift-gatekeeper-operator
|
||||||
|
spec:
|
||||||
|
displayName: Gatekeeper Operator Upstream
|
||||||
|
publisher: github.com/font/gatekeeper-operator
|
||||||
|
sourceType: grpc
|
||||||
|
image: 'quay.io/gatekeeper/gatekeeper-operator-bundle-index:v0.2.1'
|
||||||
|
updateStrategy:
|
||||||
|
registryPoll:
|
||||||
|
interval: 45m
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator-group
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: high
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: operators.coreos.com/v1
|
||||||
|
kind: OperatorGroup
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator
|
||||||
|
namespace: openshift-gatekeeper-operator
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator-subscription
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: high
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: operators.coreos.com/v1alpha1
|
||||||
|
kind: Subscription
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper-operator-sub
|
||||||
|
namespace: openshift-gatekeeper-operator
|
||||||
|
spec:
|
||||||
|
channel: stable
|
||||||
|
name: gatekeeper-operator
|
||||||
|
source: gatekeeper-operator
|
||||||
|
sourceNamespace: openshift-gatekeeper-operator
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: high
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: operator.gatekeeper.sh/v1alpha1
|
||||||
|
kind: Gatekeeper
|
||||||
|
metadata:
|
||||||
|
name: gatekeeper
|
||||||
|
spec:
|
||||||
|
audit:
|
||||||
|
auditChunkSize: 500
|
||||||
|
logLevel: INFO
|
||||||
|
replicas: 1
|
||||||
|
validatingWebhook: Enabled
|
||||||
|
mutatingWebhook: Disabled
|
||||||
|
webhook:
|
||||||
|
emitAdmissionEvents: Enabled
|
||||||
|
logLevel: INFO
|
||||||
|
replicas: 2
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: binding-policy-gatekeeper-operator
|
||||||
|
placementRef:
|
||||||
|
name: placement-policy-gatekeeper-operator
|
||||||
|
kind: PlacementRule
|
||||||
|
apiGroup: apps.open-cluster-management.io
|
||||||
|
subjects:
|
||||||
|
- name: policy-gatekeeper-operator
|
||||||
|
kind: Policy
|
||||||
|
apiGroup: policy.open-cluster-management.io
|
||||||
|
---
|
||||||
|
apiVersion: apps.open-cluster-management.io/v1
|
||||||
|
kind: PlacementRule
|
||||||
|
metadata:
|
||||||
|
name: placement-policy-gatekeeper-operator
|
||||||
|
spec:
|
||||||
|
clusterConditions:
|
||||||
|
- status: "True"
|
||||||
|
type: ManagedClusterConditionAvailable
|
||||||
|
clusterSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- {key: policy, operator: In, values: ["opa"]}
|
||||||
8
components/policies/gitops/base/kustomization.yaml
Normal file
8
components/policies/gitops/base/kustomization.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace: acm-policies
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- placement.yaml
|
||||||
|
- managedclustersetbinding.yaml
|
||||||
|
|
||||||
|
generators:
|
||||||
|
- policy-generator-config.yaml
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: cluster.open-cluster-management.io/v1beta2
|
||||||
|
kind: ManagedClusterSetBinding
|
||||||
|
metadata:
|
||||||
|
name: global
|
||||||
|
namespace: acm-policies
|
||||||
|
spec:
|
||||||
|
clusterSet: global
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: eso-token-cluster
|
||||||
|
namespace: external-secrets
|
||||||
|
data:
|
||||||
|
dopplerToken: '{{hub (fromSecret "acm-policies" (printf "eso-token-cluster-%s" .ManagedClusterName) "dopplerToken") hub}}'
|
||||||
|
---
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
metadata:
|
||||||
|
name: doppler-cluster
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
doppler:
|
||||||
|
auth:
|
||||||
|
secretRef:
|
||||||
|
dopplerToken:
|
||||||
|
name: eso-token-cluster
|
||||||
|
key: dopplerToken
|
||||||
|
namespace: external-secrets
|
||||||
|
|
||||||
|
conditions:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
openshift.io/cluster-monitoring: "true"
|
||||||
|
|
||||||
|
- namespaces:
|
||||||
|
- "cert-manager"
|
||||||
|
- "dev-tools"
|
||||||
|
- "gitops"
|
||||||
|
- "openshift-config"
|
||||||
|
- "openshift-gitops"
|
||||||
|
- "openshift-monitoring"
|
||||||
|
- "openshift-pipelines"
|
||||||
|
- "stackrox"
|
||||||
|
- "stackrox-secured-cluster-service"
|
||||||
|
- "tenant-secrets"
|
||||||
|
- "trusted-profile-analyzer"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace: openshift-gitops
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- prometheus-rules.yaml
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: PrometheusRule
|
||||||
|
metadata:
|
||||||
|
name: argocd-health-alerts
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/disable-templates: "true"
|
||||||
|
spec:
|
||||||
|
groups:
|
||||||
|
- name: ArgoCD
|
||||||
|
rules:
|
||||||
|
- alert: ArgoCDHealthAlert
|
||||||
|
annotations:
|
||||||
|
message: ArgoCD application {{ $labels.name }} is not healthy
|
||||||
|
expr: argocd_app_info{namespace="openshift-gitops", health_status!~"Healthy|Suspended|Progressing|Degraded"} > 0
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
- alert: ArgoCDDegradedAlert
|
||||||
|
annotations:
|
||||||
|
message: ArgoCD application {{ $labels.name }} is degraded
|
||||||
|
expr: argocd_app_info{namespace="openshift-gitops", health_status="Degraded"} > 0
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
- alert: ArgoCDStuckAlert
|
||||||
|
annotations:
|
||||||
|
message: ArgoCD application {{ $labels.name }} is stuck in progressing for more than 10m
|
||||||
|
expr: argocd_app_info{namespace="openshift-gitops", health_status="Progressing"} > 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: cluster-config-bootstrap
|
||||||
|
namespace: openshift-gitops
|
||||||
|
labels:
|
||||||
|
gitops.ownedBy: cluster-config
|
||||||
|
spec:
|
||||||
|
destination:
|
||||||
|
namespace: openshift-gitops
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
project: bootstrap
|
||||||
|
source:
|
||||||
|
path: bootstrap/overlays/{{ fromClusterClaim "gitops" }}
|
||||||
|
repoURL: https://github.com/gnunn-gitops/cluster-config-pins.git
|
||||||
|
targetRevision: 'HEAD'
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: false
|
||||||
|
selfHeal: false
|
||||||
|
ignoreDifferences:
|
||||||
|
- group: argoproj.io
|
||||||
|
kind: Application
|
||||||
|
managedFieldsManagers:
|
||||||
|
- argocd-server
|
||||||
|
jsonPointers:
|
||||||
|
- /spec/syncPolicy/automated
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: AppProject
|
||||||
|
metadata:
|
||||||
|
name: bootstrap
|
||||||
|
namespace: openshift-gitops
|
||||||
|
spec:
|
||||||
|
clusterResourceWhitelist:
|
||||||
|
- group: '*'
|
||||||
|
kind: '*'
|
||||||
|
description: Project for bootstrap cluster app
|
||||||
|
destinations:
|
||||||
|
- namespace: '*'
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
sourceRepos:
|
||||||
|
- https://github.com/gnunn-gitops/cluster-config
|
||||||
|
- https://github.com/gnunn-gitops/cluster-config-pins
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
resources:
|
||||||
|
- bootstrap-appproject.yaml
|
||||||
|
- bootstrap-app.yaml
|
||||||
@@ -0,0 +1,389 @@
|
|||||||
|
apiVersion: argoproj.io/v1beta1
|
||||||
|
kind: ArgoCD
|
||||||
|
metadata:
|
||||||
|
name: openshift-gitops
|
||||||
|
namespace: openshift-gitops
|
||||||
|
spec:
|
||||||
|
resourceTrackingMethod: annotation
|
||||||
|
applicationSet: {}
|
||||||
|
extraConfig:
|
||||||
|
exec.enabled: "true"
|
||||||
|
resource.respectRBAC: "normal"
|
||||||
|
resource.ignoreResourceUpdatesEnabled: 'true'
|
||||||
|
resource.compareoptions: |
|
||||||
|
ignoreAggregatedRoles: true
|
||||||
|
resource.customizations.ignoreResourceUpdates.external-secrets.io_ExternalSecret: |
|
||||||
|
jsonPointers:
|
||||||
|
- /status/refreshTime
|
||||||
|
resource.customizations.ignoreResourceUpdates.ocs.openshift.io_StorageCluster: |
|
||||||
|
jsonPointers:
|
||||||
|
- /status
|
||||||
|
- /metadata/resourceVersion
|
||||||
|
resource.customizations.ignoreResourceUpdates.ocs.openshift.io_StorageSystem: |
|
||||||
|
jsonPointers:
|
||||||
|
- /status
|
||||||
|
- /metadata/resourceVersion
|
||||||
|
resource.customizations.ignoreResourceUpdates.noobaa.io_Noobaa: |
|
||||||
|
jsonPointers:
|
||||||
|
- /status
|
||||||
|
- /metadata/resourceVersion
|
||||||
|
resource.customizations.ignoreResourceUpdates.noobaa.io_BackingStore: |
|
||||||
|
jsonPointers:
|
||||||
|
- /status
|
||||||
|
- /metadata/resourceVersion
|
||||||
|
accounts.admin: apiKey, login
|
||||||
|
ui.cssurl: 'https://gnunn-gitops.github.io/cluster-config/themes/{{ fromClusterClaim "gitops" }}/custom-cluster.css'
|
||||||
|
kustomizeBuildOptions: "--enable-helm --enable-alpha-plugins"
|
||||||
|
oidcConfig: |
|
||||||
|
name: Keycloak
|
||||||
|
issuer: https://sso.ocplab.com/realms/ocplab
|
||||||
|
clientID: argocd
|
||||||
|
clientSecret: $oidc.keycloak.clientSecret
|
||||||
|
requestedScopes: ["openid", "profile", "email", "groups"]
|
||||||
|
controller:
|
||||||
|
extraCommandArgs:
|
||||||
|
- '--persist-resource-health=false'
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 3Gi
|
||||||
|
monitoring:
|
||||||
|
enabled: true
|
||||||
|
repo:
|
||||||
|
sidecarContainers:
|
||||||
|
- name: setenv-cmp-plugin
|
||||||
|
command: [/var/run/argocd/argocd-cmp-server]
|
||||||
|
env:
|
||||||
|
- name: KUSTOMIZE_PLUGIN_HOME
|
||||||
|
value: /etc/kustomize/plugin
|
||||||
|
- name: INFRASTRUCTURE_ID
|
||||||
|
value: '{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").status.infrastructureName }}'
|
||||||
|
- name: CLUSTER_ID
|
||||||
|
value: '{{ (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").spec.clusterID }}'
|
||||||
|
- name: CLUSTER_GITOPS_NAME
|
||||||
|
value: '{{ fromClusterClaim "gitops" }}'
|
||||||
|
- name: CLUSTER_NAME
|
||||||
|
value: '{{ fromClusterClaim "name" }}'
|
||||||
|
- name: SUB_DOMAIN
|
||||||
|
value: '{{ (lookup "config.openshift.io/v1" "Ingress" "openshift-ingress" "cluster").spec.domain }}'
|
||||||
|
- name: BASE_DOMAIN
|
||||||
|
value: '{{ (lookup "config.openshift.io/v1" "DNS" "" "cluster").spec.baseDomain }}'
|
||||||
|
- name: COLOR
|
||||||
|
value: '{{ default "0066CC" (fromClusterClaim "color") }}'
|
||||||
|
image: quay.io/gnunn/tools:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/run/argocd
|
||||||
|
name: var-files
|
||||||
|
- mountPath: /home/argocd/cmp-server/plugins
|
||||||
|
name: plugins
|
||||||
|
- mountPath: /tmp
|
||||||
|
name: tmp
|
||||||
|
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
|
||||||
|
subPath: plugin.yaml
|
||||||
|
name: setenv-cmp-plugin
|
||||||
|
volumes:
|
||||||
|
- configMap:
|
||||||
|
name: setenv-cmp-plugin
|
||||||
|
name: setenv-cmp-plugin
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: '1'
|
||||||
|
memory: 1.5Gi
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 768Mi
|
||||||
|
redis:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 256Mi
|
||||||
|
server:
|
||||||
|
insecure: true
|
||||||
|
# host: 'openshift-gitops-server-openshift-gitops.{{ (lookup "config.openshift.io/v1" "Ingress" "openshift-ingress" "cluster").spec.domain }}'
|
||||||
|
route:
|
||||||
|
enabled: true
|
||||||
|
tls:
|
||||||
|
termination: edge
|
||||||
|
insecureEdgeTerminationPolicy: Redirect
|
||||||
|
notifications:
|
||||||
|
enabled: true
|
||||||
|
resourceActions:
|
||||||
|
- group: compliance.openshift.io
|
||||||
|
kind: ComplianceScan
|
||||||
|
action: |
|
||||||
|
discovery.lua: |
|
||||||
|
local actions = {}
|
||||||
|
local enabled = false
|
||||||
|
if obj.status ~= nil and obj.status.phase == "DONE" then
|
||||||
|
enabled = true
|
||||||
|
end
|
||||||
|
actions["rescan"] = {["disabled"] = not(enabled)}
|
||||||
|
return actions
|
||||||
|
definitions:
|
||||||
|
- name: rescan
|
||||||
|
action.lua: |
|
||||||
|
if obj.metadata.annotations == nil then
|
||||||
|
obj.metadata.annotations = {}
|
||||||
|
end
|
||||||
|
obj.metadata.annotations["compliance.openshift.io/rescan"] = ""
|
||||||
|
return obj
|
||||||
|
resourceHealthChecks:
|
||||||
|
- group: argoproj.io
|
||||||
|
kind: Application
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = ""
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.health ~= nil then
|
||||||
|
hs.status = obj.status.health.status
|
||||||
|
hs.message = obj.status.health.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return hs
|
||||||
|
- group: argoproj.io
|
||||||
|
kind: RolloutManager
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.conditions ~= nil then
|
||||||
|
for _, condition in ipairs(obj.status.conditions) do
|
||||||
|
hs.message = condition.message
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if obj.status.phase ~= nil then
|
||||||
|
if obj.status.phase == "Failure" then
|
||||||
|
hs.status = "Degraded"
|
||||||
|
return hs
|
||||||
|
elseif obj.status.phase == "Available" then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
return hs
|
||||||
|
elseif obj.status.phase == "Pending" then
|
||||||
|
hs.status = "Progressing"
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = "Waiting for operator to update status"
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
- group: operators.coreos.com
|
||||||
|
kind: Subscription
|
||||||
|
check: |
|
||||||
|
health_status = {}
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.conditions ~= nil then
|
||||||
|
numDegraded = 0
|
||||||
|
numPending = 0
|
||||||
|
numSuspended = 0
|
||||||
|
msg = ""
|
||||||
|
for i, condition in pairs(obj.status.conditions) do
|
||||||
|
msg = msg .. i .. ": " .. condition.type .. " | " .. condition.status .. " | " .. (condition.reason and condition.reason or '') .. "\n"
|
||||||
|
if condition.type == "InstallPlanPending" and condition.status == "True" then
|
||||||
|
if condition.reason == "RequiresApproval" then
|
||||||
|
numSuspended = numSuspended + 1
|
||||||
|
else
|
||||||
|
numPending = numPending + 1
|
||||||
|
end
|
||||||
|
elseif (condition.type == "InstallPlanMissing" and condition.reason ~= "ReferencedInstallPlanNotFound") then
|
||||||
|
numDegraded = numDegraded + 1
|
||||||
|
elseif (condition.type == "CatalogSourcesUnhealthy" or condition.type == "InstallPlanFailed") and condition.status == "True" then
|
||||||
|
numDegraded = numDegraded + 1
|
||||||
|
elseif (condition.type == "ResolutionFailed" and condition.reason ~= "ConstraintsNotSatisfiable") then
|
||||||
|
numDegraded = numDegraded + 1
|
||||||
|
elseif (condition.type == 'ChannelDeprecated' and condition.status == "True") then
|
||||||
|
numDegraded = numDegraded + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if numDegraded > 0 then
|
||||||
|
health_status.status = "Degraded"
|
||||||
|
health_status.message = msg
|
||||||
|
return health_status
|
||||||
|
elseif numSuspended > 0 then
|
||||||
|
health_status.status = "Suspended"
|
||||||
|
health_status.message = msg
|
||||||
|
return health_status
|
||||||
|
elseif numPending > 0 then
|
||||||
|
health_status.status = "Progressing"
|
||||||
|
health_status.message = "An install plan for a subscription is pending installation"
|
||||||
|
return health_status
|
||||||
|
else
|
||||||
|
health_status.status = "Healthy"
|
||||||
|
health_status.message = msg
|
||||||
|
return health_status
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
health_status.status = "Progressing"
|
||||||
|
health_status.message = "An install plan for a subscription is pending installation"
|
||||||
|
return health_status
|
||||||
|
- group: operators.coreos.com
|
||||||
|
kind: InstallPlan
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.phase ~= nil then
|
||||||
|
if obj.status.phase == "Complete" then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
hs.message = obj.status.phase
|
||||||
|
return hs
|
||||||
|
elseif obj.status.phase == "RequiresApproval" then
|
||||||
|
hs.status = "Suspended"
|
||||||
|
hs.message = obj.status.phase
|
||||||
|
return hs
|
||||||
|
else
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = obj.status.phase
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = "Waiting for InstallPlan to complete"
|
||||||
|
return hs
|
||||||
|
- group: platform.stackrox.io
|
||||||
|
kind: Central
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
if obj.status ~= nil and obj.status.conditions ~= nil then
|
||||||
|
for i, condition in ipairs(obj.status.conditions) do
|
||||||
|
if condition.status == "True" or condition.reason == "InstallSuccessful" or condition.reason == "UpgradeSuccessful" then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
hs.message = "Install Successful"
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = "Waiting for Central to deploy."
|
||||||
|
return hs
|
||||||
|
- group: image.openshift.io
|
||||||
|
kind: ImageStream
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = ""
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.tags ~= nil then
|
||||||
|
numTags = 0
|
||||||
|
for _ , item in pairs(obj.status.tags) do
|
||||||
|
numTags = numTags + 1
|
||||||
|
numItems = 0
|
||||||
|
if item.tags ~= nil then
|
||||||
|
for _ , item in pairs(item.tags) do
|
||||||
|
numItems = numItems + 1
|
||||||
|
end
|
||||||
|
if numItems == 0 then
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if numTags > 0 then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
hs.message = "ImageStream has tags resolved"
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return hs
|
||||||
|
- group: build.openshift.io
|
||||||
|
kind: Build
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.phase ~= nil then
|
||||||
|
if obj.status.phase == "Complete" then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
hs.message = obj.status.phase
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = "Waiting for Build to complete"
|
||||||
|
return hs
|
||||||
|
- kind: PersistentVolumeClaim
|
||||||
|
check: |
|
||||||
|
hs = {}
|
||||||
|
if obj.status ~= nil then
|
||||||
|
if obj.status.phase ~= nil then
|
||||||
|
if obj.status.phase == "Pending" then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
hs.message = obj.status.phase
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
if obj.status.phase == "Bound" then
|
||||||
|
hs.status = "Healthy"
|
||||||
|
hs.message = obj.status.phase
|
||||||
|
return hs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hs.status = "Progressing"
|
||||||
|
hs.message = "Waiting for PVC"
|
||||||
|
return hs
|
||||||
|
resourceIgnoreDifferences:
|
||||||
|
resourceIdentifiers:
|
||||||
|
- group: route.openshift.io
|
||||||
|
kind: Route
|
||||||
|
customization:
|
||||||
|
jsonPointers:
|
||||||
|
- /status/ingress
|
||||||
|
- /metadata/annotations
|
||||||
|
- group: quay.redhat.com
|
||||||
|
kind: QuayRegistry
|
||||||
|
customization:
|
||||||
|
jsonPointers:
|
||||||
|
- /status/ingress
|
||||||
|
- group: cluster.open-cluster-management.io
|
||||||
|
kind: ManagedCluster
|
||||||
|
customization:
|
||||||
|
jsonPointers:
|
||||||
|
- /spec/managedClusterClientConfigs
|
||||||
|
resourceExclusions: |
|
||||||
|
- apiGroups:
|
||||||
|
- tekton.dev
|
||||||
|
clusters:
|
||||||
|
- '*'
|
||||||
|
kinds:
|
||||||
|
- TaskRun
|
||||||
|
- PipelineRun
|
||||||
|
- apiGroups:
|
||||||
|
- operator.tekton.dev
|
||||||
|
clusters:
|
||||||
|
- '*'
|
||||||
|
kinds:
|
||||||
|
- TektonAddon
|
||||||
|
- TektonInstallerSet
|
||||||
|
- apiGroups:
|
||||||
|
- compliance.openshift.io
|
||||||
|
kinds:
|
||||||
|
- ComplianceCheckResult
|
||||||
|
- ComplianceRemediation
|
||||||
|
- apiGroups:
|
||||||
|
- policy.open-cluster-management.io
|
||||||
|
kinds:
|
||||||
|
- ConfigurationPolicy
|
||||||
|
- apiGroups:
|
||||||
|
- noobaa.io
|
||||||
|
kinds:
|
||||||
|
- NooBaa
|
||||||
|
- BucketClass
|
||||||
|
ha:
|
||||||
|
enabled: false
|
||||||
|
rbac:
|
||||||
|
defaultPolicy: 'role:none'
|
||||||
|
policy: |
|
||||||
|
p, role:none, *, *, */*, deny
|
||||||
|
g, system:cluster-admins, role:admin
|
||||||
|
g, cluster-admins, role:admin
|
||||||
|
scopes: "[groups]"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
resources:
|
||||||
|
- setenv-cmp-plugin-cm.yaml
|
||||||
|
- argocd.yaml
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: setenv-cmp-plugin
|
||||||
|
namespace: openshift-gitops
|
||||||
|
data:
|
||||||
|
plugin.yaml: |
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: ConfigManagementPlugin
|
||||||
|
metadata:
|
||||||
|
name: setenv-cmp-plugin
|
||||||
|
spec:
|
||||||
|
init:
|
||||||
|
command: [sh, -c, 'echo "Initializing setenv-plugin-cmp..."']
|
||||||
|
generate:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- "-c"
|
||||||
|
- "set -o pipefail && kustomize build --enable-helm --enable-alpha-plugins . | envsub"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
resources:
|
||||||
|
- notifications-config.yaml
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
# No longer needed with NotificationsConfig introduced in 1.12
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/managed-by: openshift-gitops
|
||||||
|
app.kubernetes.io/name: argocd-notifications-cm
|
||||||
|
app.kubernetes.io/part-of: argocd
|
||||||
|
annotation:
|
||||||
|
policy.open-cluster-management.io/disable-templates: "true"
|
||||||
|
name: argocd-notifications-cm
|
||||||
|
namespace: openshift-gitops
|
||||||
|
data:
|
||||||
|
service.slack: |
|
||||||
|
token: $slack-token
|
||||||
|
template.app-deployed: |-
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#18be52",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Revision",
|
||||||
|
"value": "{{.app.status.sync.revision}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
template.app-health-degraded: |-
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#f4c030",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Health Status",
|
||||||
|
"value": "{{.app.status.health.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
template.app-sync-failed: |-
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#E96D76",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
template.app-sync-running: |-
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#0DADEA",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
template.app-sync-status-unknown: |-
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#E96D76",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
template.app-sync-succeeded: |-
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#18be52",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
# trigger.on-created: |-
|
||||||
|
# - description: Application is created.
|
||||||
|
# oncePer: app.metadata.name
|
||||||
|
# send:
|
||||||
|
# - app-created
|
||||||
|
# when: "true"
|
||||||
|
# trigger.on-deleted: |-
|
||||||
|
# - description: Application is deleted.
|
||||||
|
# oncePer: app.metadata.name
|
||||||
|
# send:
|
||||||
|
# - app-deleted
|
||||||
|
# when: app.metadata.deletionTimestamp != nil
|
||||||
|
trigger.on-deployed: |-
|
||||||
|
- description: Application is synced and healthy. Triggered once per commit.
|
||||||
|
oncePer: app.status.operationState.syncResult.revision
|
||||||
|
send:
|
||||||
|
- app-deployed
|
||||||
|
when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status
|
||||||
|
== 'Healthy'
|
||||||
|
trigger.on-health-degraded: |-
|
||||||
|
- description: Application has degraded
|
||||||
|
send:
|
||||||
|
- app-health-degraded
|
||||||
|
when: app.status.health.status == 'Degraded'
|
||||||
|
trigger.on-sync-failed: |-
|
||||||
|
- description: Application syncing has failed
|
||||||
|
send:
|
||||||
|
- app-sync-failed
|
||||||
|
when: app.status.operationState.phase in ['Error', 'Failed']
|
||||||
|
trigger.on-sync-running: |-
|
||||||
|
- description: Application is being synced
|
||||||
|
send:
|
||||||
|
- app-sync-running
|
||||||
|
when: app.status.operationState.phase in ['Running']
|
||||||
|
trigger.on-sync-status-unknown: |-
|
||||||
|
- description: Application status is 'Unknown'
|
||||||
|
end:
|
||||||
|
- app-sync-status-unknown
|
||||||
|
when: app.status.sync.status == 'Unknown'
|
||||||
|
trigger.on-sync-succeeded: |-
|
||||||
|
- description: Application syncing has succeeded
|
||||||
|
send:
|
||||||
|
- app-sync-succeeded
|
||||||
|
when: app.status.operationState.phase in ['Succeeded']
|
||||||
@@ -0,0 +1,540 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: NotificationsConfiguration
|
||||||
|
metadata:
|
||||||
|
name: default-notifications-configuration
|
||||||
|
namespace: openshift-gitops
|
||||||
|
spec:
|
||||||
|
services:
|
||||||
|
service.slack: |
|
||||||
|
token: $slack-token
|
||||||
|
templates:
|
||||||
|
template.app-created: |-
|
||||||
|
email:
|
||||||
|
subject: Application {{.app.metadata.name}} has been created.
|
||||||
|
message: Application {{.app.metadata.name}} has been created.
|
||||||
|
teams:
|
||||||
|
title: Application {{.app.metadata.name}} has been created.
|
||||||
|
template.app-deleted: |-
|
||||||
|
email:
|
||||||
|
subject: Application {{.app.metadata.name}} has been deleted.
|
||||||
|
message: Application {{.app.metadata.name}} has been deleted.
|
||||||
|
teams:
|
||||||
|
title: Application {{.app.metadata.name}} has been deleted.
|
||||||
|
template.app-deployed: |-
|
||||||
|
email:
|
||||||
|
subject: New version of an application {{.app.metadata.name}} is up and running.
|
||||||
|
message: |
|
||||||
|
{{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} is now running new version of deployments manifests.
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#18be52",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Revision",
|
||||||
|
"value": "{{.app.status.sync.revision}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
teams:
|
||||||
|
facts: |
|
||||||
|
[{
|
||||||
|
"name": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Revision",
|
||||||
|
"value": "{{.app.status.sync.revision}}"
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"name": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}"
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
potentialAction: |-
|
||||||
|
[{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Operation Application",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Repository",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
themeColor: '#000080'
|
||||||
|
title: New version of an application {{.app.metadata.name}} is up and running.
|
||||||
|
template.app-health-degraded: |-
|
||||||
|
email:
|
||||||
|
subject: Application {{.app.metadata.name}} has degraded.
|
||||||
|
message: |
|
||||||
|
{{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} has degraded.
|
||||||
|
Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#f4c030",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Health Status",
|
||||||
|
"value": "{{.app.status.health.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
teams:
|
||||||
|
facts: |
|
||||||
|
[{
|
||||||
|
"name": "Health Status",
|
||||||
|
"value": "{{.app.status.health.status}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}"
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"name": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}"
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
potentialAction: |
|
||||||
|
[{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Application",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Repository",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
themeColor: '#FF0000'
|
||||||
|
title: Application {{.app.metadata.name}} has degraded.
|
||||||
|
template.app-sync-failed: |-
|
||||||
|
email:
|
||||||
|
subject: Failed to sync application {{.app.metadata.name}}.
|
||||||
|
message: |
|
||||||
|
{{if eq .serviceType "slack"}}:exclamation:{{end}} The sync operation of application {{.app.metadata.name}} has failed at {{.app.status.operationState.finishedAt}} with the following error: {{.app.status.operationState.message}}
|
||||||
|
Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true .
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#E96D76",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
teams:
|
||||||
|
facts: |
|
||||||
|
[{
|
||||||
|
"name": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Failed at",
|
||||||
|
"value": "{{.app.status.operationState.finishedAt}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}"
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"name": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}"
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
potentialAction: |-
|
||||||
|
[{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Operation",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Repository",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
themeColor: '#FF0000'
|
||||||
|
title: Failed to sync application {{.app.metadata.name}}.
|
||||||
|
template.app-sync-running: |-
|
||||||
|
email:
|
||||||
|
subject: Start syncing application {{.app.metadata.name}}.
|
||||||
|
message: |
|
||||||
|
The sync operation of application {{.app.metadata.name}} has started at {{.app.status.operationState.startedAt}}.
|
||||||
|
Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true .
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#0DADEA",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
teams:
|
||||||
|
facts: |
|
||||||
|
[{
|
||||||
|
"name": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Started at",
|
||||||
|
"value": "{{.app.status.operationState.startedAt}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}"
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"name": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}"
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
potentialAction: |-
|
||||||
|
[{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Operation",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Repository",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
title: Start syncing application {{.app.metadata.name}}.
|
||||||
|
template.app-sync-status-unknown: |-
|
||||||
|
email:
|
||||||
|
subject: Application {{.app.metadata.name}} sync status is 'Unknown'
|
||||||
|
message: |
|
||||||
|
{{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} sync is 'Unknown'.
|
||||||
|
Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
|
||||||
|
{{if ne .serviceType "slack"}}
|
||||||
|
{{range $c := .app.status.conditions}}
|
||||||
|
* {{$c.message}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#E96D76",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
teams:
|
||||||
|
facts: |
|
||||||
|
[{
|
||||||
|
"name": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}"
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"name": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}"
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
potentialAction: |-
|
||||||
|
[{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Application",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Repository",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
title: Application {{.app.metadata.name}} sync status is 'Unknown'
|
||||||
|
template.app-sync-succeeded: |-
|
||||||
|
email:
|
||||||
|
subject: Application {{.app.metadata.name}} has been successfully synced.
|
||||||
|
message: |
|
||||||
|
{{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} has been successfully synced at {{.app.status.operationState.finishedAt}}.
|
||||||
|
Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true .
|
||||||
|
slack:
|
||||||
|
attachments: |
|
||||||
|
[{
|
||||||
|
"title": "{{ .app.metadata.name}}",
|
||||||
|
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
|
||||||
|
"color": "#18be52",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"title": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}",
|
||||||
|
"short": true
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
deliveryPolicy: Post
|
||||||
|
groupingKey: ""
|
||||||
|
notifyBroadcast: false
|
||||||
|
teams:
|
||||||
|
facts: |
|
||||||
|
[{
|
||||||
|
"name": "Sync Status",
|
||||||
|
"value": "{{.app.status.sync.status}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Synced at",
|
||||||
|
"value": "{{.app.status.operationState.finishedAt}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repository",
|
||||||
|
"value": "{{.app.spec.source.repoURL}}"
|
||||||
|
}
|
||||||
|
{{range $index, $c := .app.status.conditions}}
|
||||||
|
{{if not $index}},{{end}}
|
||||||
|
{{if $index}},{{end}}
|
||||||
|
{
|
||||||
|
"name": "{{$c.type}}",
|
||||||
|
"value": "{{$c.message}}"
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
]
|
||||||
|
potentialAction: |-
|
||||||
|
[{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Operation Details",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type":"OpenUri",
|
||||||
|
"name":"Open Repository",
|
||||||
|
"targets":[{
|
||||||
|
"os":"default",
|
||||||
|
"uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
themeColor: '#000080'
|
||||||
|
title: Application {{.app.metadata.name}} has been successfully synced
|
||||||
|
triggers:
|
||||||
|
trigger.on-created: |-
|
||||||
|
- description: Application is created.
|
||||||
|
oncePer: app.metadata.name
|
||||||
|
send:
|
||||||
|
- app-created
|
||||||
|
when: "true"
|
||||||
|
trigger.on-deleted: |-
|
||||||
|
- description: Application is deleted.
|
||||||
|
oncePer: app.metadata.name
|
||||||
|
send:
|
||||||
|
- app-deleted
|
||||||
|
when: app.metadata.deletionTimestamp != nil
|
||||||
|
trigger.on-deployed: |-
|
||||||
|
- description: Application is synced and healthy. Triggered once per commit.
|
||||||
|
oncePer: app.status.operationState.syncResult.revision
|
||||||
|
send:
|
||||||
|
- app-deployed
|
||||||
|
when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status
|
||||||
|
== 'Healthy'
|
||||||
|
trigger.on-health-degraded: |-
|
||||||
|
- description: Application has degraded
|
||||||
|
send:
|
||||||
|
- app-health-degraded
|
||||||
|
when: app.status.health.status == 'Degraded'
|
||||||
|
trigger.on-sync-failed: |-
|
||||||
|
- description: Application syncing has failed
|
||||||
|
send:
|
||||||
|
- app-sync-failed
|
||||||
|
when: app.status.operationState.phase in ['Error', 'Failed']
|
||||||
|
trigger.on-sync-running: |-
|
||||||
|
- description: Application is being synced
|
||||||
|
send:
|
||||||
|
- app-sync-running
|
||||||
|
when: app.status.operationState.phase in ['Running']
|
||||||
|
trigger.on-sync-status-unknown: |-
|
||||||
|
- description: Application status is 'Unknown'
|
||||||
|
send:
|
||||||
|
- app-sync-status-unknown
|
||||||
|
when: app.status.sync.status == 'Unknown'
|
||||||
|
trigger.on-sync-succeeded: |-
|
||||||
|
- description: Application syncing has succeeded
|
||||||
|
send:
|
||||||
|
- app-sync-succeeded
|
||||||
|
when: app.status.operationState.phase in ['Succeeded']
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: argocd-secret
|
||||||
|
namespace: openshift-gitops
|
||||||
|
spec:
|
||||||
|
data:
|
||||||
|
- remoteRef:
|
||||||
|
conversionStrategy: Default
|
||||||
|
decodingStrategy: None
|
||||||
|
key: OIDC_ARGOCD
|
||||||
|
secretKey: oidc.keycloak.clientSecret
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
name: doppler-cluster
|
||||||
|
target:
|
||||||
|
creationPolicy: Merge
|
||||||
|
deletionPolicy: Retain
|
||||||
|
name: argocd-secret
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
resources:
|
||||||
|
- argocd-external-secret.yaml
|
||||||
|
- notifications-secret.yaml
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: argocd-notifications-secret
|
||||||
|
namespace: openshift-gitops
|
||||||
|
spec:
|
||||||
|
secretStoreRef:
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
name: doppler-cluster
|
||||||
|
target:
|
||||||
|
name: argocd-notifications-secret
|
||||||
|
creationPolicy: Merge
|
||||||
|
deletionPolicy: Retain
|
||||||
|
data:
|
||||||
|
- secretKey: slack-token
|
||||||
|
remoteRef:
|
||||||
|
key: GITOPS_SLACK_TOKEN
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: argocd-application-controller-cluster-admin
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: openshift-gitops-argocd-application-controller
|
||||||
|
namespace: openshift-gitops
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-admin
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
rbac.authorization.kubernetes.io/autoupdate: "true"
|
||||||
|
name: gitops-controller
|
||||||
|
aggregationRule:
|
||||||
|
clusterRoleSelectors:
|
||||||
|
- matchLabels:
|
||||||
|
gitops/aggregate-to-controller: "true"
|
||||||
|
rules: []
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: gitops-controller-admin
|
||||||
|
labels:
|
||||||
|
gitops/aggregate-to-controller: "true"
|
||||||
|
aggregationRule:
|
||||||
|
clusterRoleSelectors:
|
||||||
|
- matchLabels:
|
||||||
|
rbac.authorization.k8s.io/aggregate-to-admin: "true"
|
||||||
|
rules: []
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: gitops-controller-view
|
||||||
|
labels:
|
||||||
|
gitops/aggregate-to-controller: "true"
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- '*'
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: gitops-server
|
||||||
|
rules:
|
||||||
|
- verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- '*'
|
||||||
|
- verbs:
|
||||||
|
- create
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
apiGroups:
|
||||||
|
- ''
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
- configmaps
|
||||||
|
- verbs:
|
||||||
|
- create
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- update
|
||||||
|
- delete
|
||||||
|
- patch
|
||||||
|
apiGroups:
|
||||||
|
- argoproj.io
|
||||||
|
resources:
|
||||||
|
- applications
|
||||||
|
- appprojects
|
||||||
|
- applicationsets
|
||||||
|
- verbs:
|
||||||
|
- create
|
||||||
|
- list
|
||||||
|
apiGroups:
|
||||||
|
- ''
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods/exec
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
resources:
|
||||||
|
- sub-namespace.yaml
|
||||||
|
- sub-operatorgroup.yaml
|
||||||
|
- subscription.yaml
|
||||||
|
- namespace.yaml
|
||||||
|
- gitops-controller-rbac.yaml
|
||||||
|
- gitops-server-rbac.yaml
|
||||||
|
- cluster-admin-rolebinding.yaml
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
openshift.io/cluster-monitoring: "true"
|
||||||
|
name: openshift-gitops
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
openshift.io/cluster-monitoring: "true"
|
||||||
|
name: openshift-gitops-operator
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: operators.coreos.com/v1
|
||||||
|
kind: OperatorGroup
|
||||||
|
metadata:
|
||||||
|
name: gitops-operators
|
||||||
|
namespace: openshift-gitops-operator
|
||||||
|
spec:
|
||||||
|
upgradeStrategy: Default
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: operators.coreos.com/v1alpha1
|
||||||
|
kind: Subscription
|
||||||
|
metadata:
|
||||||
|
name: openshift-gitops-operator
|
||||||
|
namespace: openshift-gitops-operator
|
||||||
|
spec:
|
||||||
|
config:
|
||||||
|
env:
|
||||||
|
- name: ARGOCD_CLUSTER_CONFIG_NAMESPACES
|
||||||
|
value: openshift-gitops, gitops
|
||||||
|
- name: CONTROLLER_CLUSTER_ROLE
|
||||||
|
value: gitops-controller
|
||||||
|
- name: SERVER_CLUSTER_ROLE
|
||||||
|
value: gitops-server
|
||||||
|
channel: gitops-1.15
|
||||||
|
installPlanApproval: Automatic
|
||||||
|
name: openshift-gitops-operator
|
||||||
|
source: redhat-operators
|
||||||
|
sourceNamespace: openshift-marketplace
|
||||||
28
components/policies/gitops/base/placement.yaml
Normal file
28
components/policies/gitops/base/placement.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
apiVersion: cluster.open-cluster-management.io/v1beta1
|
||||||
|
kind: Placement
|
||||||
|
metadata:
|
||||||
|
name: placement-policy-gitops
|
||||||
|
namespace: acm-policies
|
||||||
|
spec:
|
||||||
|
clusterSets:
|
||||||
|
- global
|
||||||
|
predicates:
|
||||||
|
- requiredClusterSelector:
|
||||||
|
labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: gitops
|
||||||
|
operator: Exists
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: binding-policy-gitops
|
||||||
|
namespace: acm-policies
|
||||||
|
placementRef:
|
||||||
|
apiGroup: cluster.open-cluster-management.io
|
||||||
|
kind: Placement
|
||||||
|
name: placement-policy-gitops
|
||||||
|
subjects:
|
||||||
|
- apiGroup: policy.open-cluster-management.io
|
||||||
|
kind: PolicySet
|
||||||
|
name: gitops
|
||||||
60
components/policies/gitops/base/policy-generator-config.yaml
Normal file
60
components/policies/gitops/base/policy-generator-config.yaml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PolicyGenerator
|
||||||
|
metadata:
|
||||||
|
name: gitops-policy-generator
|
||||||
|
policyDefaults:
|
||||||
|
namespace: acm-policies
|
||||||
|
remediationAction: enforce
|
||||||
|
placementBindingDefaults:
|
||||||
|
name: "binding-policy-gitops"
|
||||||
|
policies:
|
||||||
|
- name: policy-eso-secret-store
|
||||||
|
configurationPolicyAnnotations:
|
||||||
|
apps.open-cluster-management.io/reconcile-option: replace
|
||||||
|
manifests:
|
||||||
|
- path: manifests/eso/base/
|
||||||
|
- name: policy-gitops-subscription
|
||||||
|
remediationAction: enforce
|
||||||
|
manifests:
|
||||||
|
- path: manifests/gitops-subscription/base/
|
||||||
|
- name: policy-gitops-instance
|
||||||
|
# Needed to fix issue with merging lists resulting in duplicates
|
||||||
|
configurationPolicyAnnotations:
|
||||||
|
apps.open-cluster-management.io/reconcile-option: replace
|
||||||
|
complianceType: "mustonlyhave"
|
||||||
|
manifests:
|
||||||
|
- path: manifests/gitops-instance/base/
|
||||||
|
- name: policy-gitops-bootstrap
|
||||||
|
manifests:
|
||||||
|
- path: manifests/gitops-bootstrap/base/
|
||||||
|
- name: policy-gitops-notifications
|
||||||
|
remediationAction: enforce
|
||||||
|
manifests:
|
||||||
|
- path: manifests/gitops-notifications/base/
|
||||||
|
configurationPolicyAnnotations:
|
||||||
|
policy.open-cluster-management.io/disable-templates: "true"
|
||||||
|
- name: policy-gitops-alerting
|
||||||
|
remediationAction: enforce
|
||||||
|
manifests:
|
||||||
|
- path: manifests/gitops-alerting/base/
|
||||||
|
configurationPolicyAnnotations:
|
||||||
|
policy.open-cluster-management.io/disable-templates: "true"
|
||||||
|
# Put ESO secrets into separate policy since it's chicken and egg
|
||||||
|
# Not being used since I have a global policy that does this but included for example
|
||||||
|
# - name: policy-gitops-secrets
|
||||||
|
# remediationAction: enforce
|
||||||
|
# manifests:
|
||||||
|
# - path: manifests/gitops-secrets/base/
|
||||||
|
policySets:
|
||||||
|
- name: "gitops"
|
||||||
|
description: "Policy for bootstrapping cluster with gitops"
|
||||||
|
policies:
|
||||||
|
- policy-eso-secret-store
|
||||||
|
- policy-gitops-subscription
|
||||||
|
- policy-gitops-instance
|
||||||
|
- policy-gitops-bootstrap
|
||||||
|
- policy-gitops-notifications
|
||||||
|
- policy-gitops-alerting
|
||||||
|
generatePolicySetPlacement: false
|
||||||
|
placement:
|
||||||
|
name: placement-policy-gitops
|
||||||
459
components/policies/opa/gatekeeper-probes-livenessnotset.yaml
Normal file
459
components/policies/opa/gatekeeper-probes-livenessnotset.yaml
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-livenessprobe
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/standards: NIST SP 800-53
|
||||||
|
policy.open-cluster-management.io/categories: CM Configuration Management
|
||||||
|
policy.open-cluster-management.io/controls: CM-2 Baseline Configuration
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
disabled: false
|
||||||
|
policy-templates:
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-containerlivenessprobenotset
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: templates.gatekeeper.sh/v1beta1
|
||||||
|
kind: ConstraintTemplate
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: containerlivenessprobenotset
|
||||||
|
spec:
|
||||||
|
crd:
|
||||||
|
spec:
|
||||||
|
names:
|
||||||
|
kind: ContainerLivenessprobeNotset
|
||||||
|
targets:
|
||||||
|
- libs:
|
||||||
|
- |
|
||||||
|
package lib.konstraint
|
||||||
|
|
||||||
|
default is_gatekeeper = false
|
||||||
|
|
||||||
|
is_gatekeeper {
|
||||||
|
has_field(input, "review")
|
||||||
|
has_field(input.review, "object")
|
||||||
|
}
|
||||||
|
|
||||||
|
object = input {
|
||||||
|
not is_gatekeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
object = input.review.object {
|
||||||
|
is_gatekeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
format(msg) = gatekeeper_format {
|
||||||
|
is_gatekeeper
|
||||||
|
gatekeeper_format = {"msg": msg}
|
||||||
|
}
|
||||||
|
|
||||||
|
format(msg) = msg {
|
||||||
|
not is_gatekeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
name = object.metadata.name
|
||||||
|
|
||||||
|
kind = object.kind
|
||||||
|
|
||||||
|
has_field(obj, field) {
|
||||||
|
obj[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_field(obj, field) = true {
|
||||||
|
obj[field] == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_field(obj, field) = true {
|
||||||
|
not has_field(obj, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
is_service {
|
||||||
|
lower(kind) == "service"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_statefulset {
|
||||||
|
lower(kind) == "statefulset"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_daemonset {
|
||||||
|
lower(kind) == "daemonset"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_deployment {
|
||||||
|
lower(kind) == "deployment"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_pod {
|
||||||
|
lower(kind) == "pod"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_namespace {
|
||||||
|
lower(kind) == "namespace"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload {
|
||||||
|
containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
pod_containers(pod) = all_containers {
|
||||||
|
keys = {"containers", "initContainers"}
|
||||||
|
all_containers = [c | keys[k]; c = pod.spec[k][_]]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
pods[pod]
|
||||||
|
all_containers = pod_containers(pod)
|
||||||
|
container = all_containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
all_containers = pod_containers(object)
|
||||||
|
container = all_containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
container_images[image] {
|
||||||
|
containers[container]
|
||||||
|
image = container.image
|
||||||
|
}
|
||||||
|
|
||||||
|
container_images[image] {
|
||||||
|
image = object.spec.image
|
||||||
|
}
|
||||||
|
|
||||||
|
split_image(image) = [image, "latest"] {
|
||||||
|
not contains(image, ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
split_image(image) = [image_name, tag] {
|
||||||
|
[image_name, tag] = split(image, ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_statefulset
|
||||||
|
pod = object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_daemonset
|
||||||
|
pod = object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_deployment
|
||||||
|
pod = object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_pod
|
||||||
|
pod = object
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes[volume] {
|
||||||
|
pods[pod]
|
||||||
|
volume = pod.spec.volumes[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_multiple("E") = 1000000000000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("P") = 1000000000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("T") = 1000000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("G") = 1000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("M") = 1000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("k") = 1000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("") = 1000 { true }
|
||||||
|
|
||||||
|
mem_multiple("m") = 1 { true }
|
||||||
|
|
||||||
|
mem_multiple("Ki") = 1024000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Mi") = 1048576000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Gi") = 1073741824000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Ti") = 1099511627776000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Pi") = 1125899906842624000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Ei") = 1152921504606846976000 { true }
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
not is_string(mem)
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) > 0
|
||||||
|
suffix := substring(mem, count(mem) - 1, -1)
|
||||||
|
mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) > 1
|
||||||
|
suffix := substring(mem, count(mem) - 2, -1)
|
||||||
|
mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) > 1
|
||||||
|
not mem_multiple(substring(mem, count(mem) - 1, -1))
|
||||||
|
not mem_multiple(substring(mem, count(mem) - 2, -1))
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) == 1
|
||||||
|
not mem_multiple(substring(mem, count(mem) - 1, -1))
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) == 0
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_mem(orig) = new {
|
||||||
|
is_number(orig)
|
||||||
|
new := orig * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_mem(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
suffix := get_suffix(orig)
|
||||||
|
raw := replace(orig, suffix, "")
|
||||||
|
re_match("^[0-9]+$", raw)
|
||||||
|
new := to_number(raw) * mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_storage(orig) = new {
|
||||||
|
is_number(orig)
|
||||||
|
new := orig
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_storage(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
suffix := get_suffix(orig)
|
||||||
|
raw := replace(orig, suffix, "")
|
||||||
|
re_match("^[0-9]+$", raw)
|
||||||
|
new := to_number(raw) * mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_cpu(orig) = new {
|
||||||
|
is_number(orig)
|
||||||
|
new := orig * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_cpu(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
endswith(orig, "m")
|
||||||
|
new := to_number(replace(orig, "m", ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_cpu(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
not endswith(orig, "m")
|
||||||
|
re_match("^[0-9]+$", orig)
|
||||||
|
new := to_number(orig) * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
dropped_capability(container, cap) {
|
||||||
|
container.securityContext.capabilities.drop[_] == cap
|
||||||
|
}
|
||||||
|
|
||||||
|
added_capability(container, cap) {
|
||||||
|
container.securityContext.capabilities.add[_] == cap
|
||||||
|
}
|
||||||
|
|
||||||
|
no_read_only_filesystem(c) {
|
||||||
|
not has_field(c, "securityContext")
|
||||||
|
}
|
||||||
|
|
||||||
|
no_read_only_filesystem(c) {
|
||||||
|
has_field(c, "securityContext")
|
||||||
|
not has_field(c.securityContext, "readOnlyRootFilesystem")
|
||||||
|
}
|
||||||
|
|
||||||
|
priviledge_escalation_allowed(c) {
|
||||||
|
not has_field(c, "securityContext")
|
||||||
|
}
|
||||||
|
|
||||||
|
priviledge_escalation_allowed(c) {
|
||||||
|
has_field(c, "securityContext")
|
||||||
|
has_field(c.securityContext, "allowPrivilegeEscalation")
|
||||||
|
}
|
||||||
|
- |-
|
||||||
|
package lib.openshift
|
||||||
|
|
||||||
|
import data.lib.konstraint
|
||||||
|
|
||||||
|
is_deploymentconfig {
|
||||||
|
lower(konstraint.object.apiVersion) == "apps.openshift.io/v1"
|
||||||
|
lower(konstraint.object.kind) == "deploymentconfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_route {
|
||||||
|
lower(konstraint.object.apiVersion) == "route.openshift.io/v1"
|
||||||
|
lower(konstraint.object.kind) == "route"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
is_deploymentconfig
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
konstraint.is_statefulset
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
konstraint.is_daemonset
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
konstraint.is_deployment
|
||||||
|
}
|
||||||
|
|
||||||
|
is_all_kind {
|
||||||
|
is_workload_kind
|
||||||
|
}
|
||||||
|
|
||||||
|
is_all_kind {
|
||||||
|
konstraint.is_service
|
||||||
|
}
|
||||||
|
|
||||||
|
is_all_kind {
|
||||||
|
is_route
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_deploymentconfig
|
||||||
|
pod = konstraint.object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
pod = konstraint.pods[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
pods[pod]
|
||||||
|
all_containers = konstraint.pod_containers(pod)
|
||||||
|
container = all_containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
container = konstraint.containers[_]
|
||||||
|
}
|
||||||
|
rego: |-
|
||||||
|
package ocp.bestpractices.container_livenessprobe_notset
|
||||||
|
|
||||||
|
import data.lib.konstraint
|
||||||
|
import data.lib.openshift
|
||||||
|
|
||||||
|
violation[msg] {
|
||||||
|
openshift.is_workload_kind
|
||||||
|
|
||||||
|
container := openshift.containers[_]
|
||||||
|
|
||||||
|
konstraint.missing_field(container, "livenessProbe")
|
||||||
|
obj := konstraint.object
|
||||||
|
|
||||||
|
msg := konstraint.format(sprintf("%s/%s: container '%s' has no livenessProbe. See: https://docs.openshift.com/container-platform/latest/applications/application-health.html", [obj.kind, obj.metadata.name, container.name]))
|
||||||
|
}
|
||||||
|
target: admission.k8s.gatekeeper.sh
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||||
|
kind: ContainerLivenessprobeNotset
|
||||||
|
metadata:
|
||||||
|
name: containerlivenessprobenotset
|
||||||
|
spec:
|
||||||
|
enforcementAction: dryrun
|
||||||
|
match:
|
||||||
|
kinds:
|
||||||
|
- apiGroups:
|
||||||
|
- apps.openshift.io
|
||||||
|
- apps
|
||||||
|
kinds:
|
||||||
|
- DeploymentConfig
|
||||||
|
- DaemonSet
|
||||||
|
- Deployment
|
||||||
|
- StatefulSet
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-audit-liveness
|
||||||
|
spec:
|
||||||
|
remediationAction: inform # will be overridden by remediationAction in parent policy
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||||
|
kind: ContainerLivenessprobeNotset
|
||||||
|
metadata:
|
||||||
|
name: containerlivenessprobenotset
|
||||||
|
status:
|
||||||
|
totalViolations: 0
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-admission-liveness
|
||||||
|
spec:
|
||||||
|
remediationAction: inform # will be overridden by remediationAction in parent policy
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: mustnothave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Event
|
||||||
|
metadata:
|
||||||
|
namespace: openshift-gatekeeper-system # set it to the actual namespace where gatekeeper is running if different
|
||||||
|
annotations:
|
||||||
|
constraint_action: deny
|
||||||
|
constraint_kind: ContainerLivenessprobeNotset
|
||||||
|
constraint_name: containerlivenessprobenotset
|
||||||
|
event_type: violation
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: binding-policy-gatekeeper-containerlivenessprobenotset
|
||||||
|
placementRef:
|
||||||
|
name: placement-policy-gatekeeper-containerlivenessprobenotset
|
||||||
|
kind: PlacementRule
|
||||||
|
apiGroup: apps.open-cluster-management.io
|
||||||
|
subjects:
|
||||||
|
- name: policy-gatekeeper-livenessprobe
|
||||||
|
kind: Policy
|
||||||
|
apiGroup: policy.open-cluster-management.io
|
||||||
|
---
|
||||||
|
apiVersion: apps.open-cluster-management.io/v1
|
||||||
|
kind: PlacementRule
|
||||||
|
metadata:
|
||||||
|
name: placement-policy-gatekeeper-containerlivenessprobenotset
|
||||||
|
spec:
|
||||||
|
clusterConditions:
|
||||||
|
- status: "True"
|
||||||
|
type: ManagedClusterConditionAvailable
|
||||||
|
clusterSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- { key: policy, operator: In, values: ["opa"] }
|
||||||
459
components/policies/opa/gatekeeper-probes-readinessnotset.yaml
Normal file
459
components/policies/opa/gatekeeper-probes-readinessnotset.yaml
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-readinessprobe
|
||||||
|
annotations:
|
||||||
|
policy.open-cluster-management.io/standards: NIST SP 800-53
|
||||||
|
policy.open-cluster-management.io/categories: CM Configuration Management
|
||||||
|
policy.open-cluster-management.io/controls: CM-2 Baseline Configuration
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
disabled: false
|
||||||
|
policy-templates:
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-containerreadinessprobenotset
|
||||||
|
spec:
|
||||||
|
remediationAction: enforce
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: templates.gatekeeper.sh/v1beta1
|
||||||
|
kind: ConstraintTemplate
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: containerreadinessprobenotset
|
||||||
|
spec:
|
||||||
|
crd:
|
||||||
|
spec:
|
||||||
|
names:
|
||||||
|
kind: ContainerReadinessprobeNotset
|
||||||
|
targets:
|
||||||
|
- libs:
|
||||||
|
- |
|
||||||
|
package lib.konstraint
|
||||||
|
|
||||||
|
default is_gatekeeper = false
|
||||||
|
|
||||||
|
is_gatekeeper {
|
||||||
|
has_field(input, "review")
|
||||||
|
has_field(input.review, "object")
|
||||||
|
}
|
||||||
|
|
||||||
|
object = input {
|
||||||
|
not is_gatekeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
object = input.review.object {
|
||||||
|
is_gatekeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
format(msg) = gatekeeper_format {
|
||||||
|
is_gatekeeper
|
||||||
|
gatekeeper_format = {"msg": msg}
|
||||||
|
}
|
||||||
|
|
||||||
|
format(msg) = msg {
|
||||||
|
not is_gatekeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
name = object.metadata.name
|
||||||
|
|
||||||
|
kind = object.kind
|
||||||
|
|
||||||
|
has_field(obj, field) {
|
||||||
|
obj[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_field(obj, field) = true {
|
||||||
|
obj[field] == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_field(obj, field) = true {
|
||||||
|
not has_field(obj, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
is_service {
|
||||||
|
lower(kind) == "service"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_statefulset {
|
||||||
|
lower(kind) == "statefulset"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_daemonset {
|
||||||
|
lower(kind) == "daemonset"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_deployment {
|
||||||
|
lower(kind) == "deployment"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_pod {
|
||||||
|
lower(kind) == "pod"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_namespace {
|
||||||
|
lower(kind) == "namespace"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload {
|
||||||
|
containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
pod_containers(pod) = all_containers {
|
||||||
|
keys = {"containers", "initContainers"}
|
||||||
|
all_containers = [c | keys[k]; c = pod.spec[k][_]]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
pods[pod]
|
||||||
|
all_containers = pod_containers(pod)
|
||||||
|
container = all_containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
all_containers = pod_containers(object)
|
||||||
|
container = all_containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
container_images[image] {
|
||||||
|
containers[container]
|
||||||
|
image = container.image
|
||||||
|
}
|
||||||
|
|
||||||
|
container_images[image] {
|
||||||
|
image = object.spec.image
|
||||||
|
}
|
||||||
|
|
||||||
|
split_image(image) = [image, "latest"] {
|
||||||
|
not contains(image, ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
split_image(image) = [image_name, tag] {
|
||||||
|
[image_name, tag] = split(image, ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_statefulset
|
||||||
|
pod = object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_daemonset
|
||||||
|
pod = object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_deployment
|
||||||
|
pod = object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_pod
|
||||||
|
pod = object
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes[volume] {
|
||||||
|
pods[pod]
|
||||||
|
volume = pod.spec.volumes[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_multiple("E") = 1000000000000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("P") = 1000000000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("T") = 1000000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("G") = 1000000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("M") = 1000000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("k") = 1000000 { true }
|
||||||
|
|
||||||
|
mem_multiple("") = 1000 { true }
|
||||||
|
|
||||||
|
mem_multiple("m") = 1 { true }
|
||||||
|
|
||||||
|
mem_multiple("Ki") = 1024000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Mi") = 1048576000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Gi") = 1073741824000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Ti") = 1099511627776000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Pi") = 1125899906842624000 { true }
|
||||||
|
|
||||||
|
mem_multiple("Ei") = 1152921504606846976000 { true }
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
not is_string(mem)
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) > 0
|
||||||
|
suffix := substring(mem, count(mem) - 1, -1)
|
||||||
|
mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) > 1
|
||||||
|
suffix := substring(mem, count(mem) - 2, -1)
|
||||||
|
mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) > 1
|
||||||
|
not mem_multiple(substring(mem, count(mem) - 1, -1))
|
||||||
|
not mem_multiple(substring(mem, count(mem) - 2, -1))
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) == 1
|
||||||
|
not mem_multiple(substring(mem, count(mem) - 1, -1))
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_suffix(mem) = suffix {
|
||||||
|
is_string(mem)
|
||||||
|
count(mem) == 0
|
||||||
|
suffix := ""
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_mem(orig) = new {
|
||||||
|
is_number(orig)
|
||||||
|
new := orig * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_mem(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
suffix := get_suffix(orig)
|
||||||
|
raw := replace(orig, suffix, "")
|
||||||
|
re_match("^[0-9]+$", raw)
|
||||||
|
new := to_number(raw) * mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_storage(orig) = new {
|
||||||
|
is_number(orig)
|
||||||
|
new := orig
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_storage(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
suffix := get_suffix(orig)
|
||||||
|
raw := replace(orig, suffix, "")
|
||||||
|
re_match("^[0-9]+$", raw)
|
||||||
|
new := to_number(raw) * mem_multiple(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_cpu(orig) = new {
|
||||||
|
is_number(orig)
|
||||||
|
new := orig * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_cpu(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
endswith(orig, "m")
|
||||||
|
new := to_number(replace(orig, "m", ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
canonify_cpu(orig) = new {
|
||||||
|
not is_number(orig)
|
||||||
|
not endswith(orig, "m")
|
||||||
|
re_match("^[0-9]+$", orig)
|
||||||
|
new := to_number(orig) * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
dropped_capability(container, cap) {
|
||||||
|
container.securityContext.capabilities.drop[_] == cap
|
||||||
|
}
|
||||||
|
|
||||||
|
added_capability(container, cap) {
|
||||||
|
container.securityContext.capabilities.add[_] == cap
|
||||||
|
}
|
||||||
|
|
||||||
|
no_read_only_filesystem(c) {
|
||||||
|
not has_field(c, "securityContext")
|
||||||
|
}
|
||||||
|
|
||||||
|
no_read_only_filesystem(c) {
|
||||||
|
has_field(c, "securityContext")
|
||||||
|
not has_field(c.securityContext, "readOnlyRootFilesystem")
|
||||||
|
}
|
||||||
|
|
||||||
|
priviledge_escalation_allowed(c) {
|
||||||
|
not has_field(c, "securityContext")
|
||||||
|
}
|
||||||
|
|
||||||
|
priviledge_escalation_allowed(c) {
|
||||||
|
has_field(c, "securityContext")
|
||||||
|
has_field(c.securityContext, "allowPrivilegeEscalation")
|
||||||
|
}
|
||||||
|
- |-
|
||||||
|
package lib.openshift
|
||||||
|
|
||||||
|
import data.lib.konstraint
|
||||||
|
|
||||||
|
is_deploymentconfig {
|
||||||
|
lower(konstraint.object.apiVersion) == "apps.openshift.io/v1"
|
||||||
|
lower(konstraint.object.kind) == "deploymentconfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_route {
|
||||||
|
lower(konstraint.object.apiVersion) == "route.openshift.io/v1"
|
||||||
|
lower(konstraint.object.kind) == "route"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
is_deploymentconfig
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
konstraint.is_statefulset
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
konstraint.is_daemonset
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workload_kind {
|
||||||
|
konstraint.is_deployment
|
||||||
|
}
|
||||||
|
|
||||||
|
is_all_kind {
|
||||||
|
is_workload_kind
|
||||||
|
}
|
||||||
|
|
||||||
|
is_all_kind {
|
||||||
|
konstraint.is_service
|
||||||
|
}
|
||||||
|
|
||||||
|
is_all_kind {
|
||||||
|
is_route
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
is_deploymentconfig
|
||||||
|
pod = konstraint.object.spec.template
|
||||||
|
}
|
||||||
|
|
||||||
|
pods[pod] {
|
||||||
|
pod = konstraint.pods[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
pods[pod]
|
||||||
|
all_containers = konstraint.pod_containers(pod)
|
||||||
|
container = all_containers[_]
|
||||||
|
}
|
||||||
|
|
||||||
|
containers[container] {
|
||||||
|
container = konstraint.containers[_]
|
||||||
|
}
|
||||||
|
rego: |-
|
||||||
|
package ocp.bestpractices.container_readinessprobe_notset
|
||||||
|
|
||||||
|
import data.lib.konstraint
|
||||||
|
import data.lib.openshift
|
||||||
|
|
||||||
|
violation[msg] {
|
||||||
|
openshift.is_workload_kind
|
||||||
|
|
||||||
|
container := openshift.containers[_]
|
||||||
|
|
||||||
|
konstraint.missing_field(container, "readinessProbe")
|
||||||
|
obj := konstraint.object
|
||||||
|
|
||||||
|
msg := konstraint.format(sprintf("%s/%s: container '%s' has no readinessProbe. See: https://docs.openshift.com/container-platform/4.4/applications/application-health.html", [obj.kind, obj.metadata.name, container.name]))
|
||||||
|
}
|
||||||
|
target: admission.k8s.gatekeeper.sh
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||||
|
kind: ContainerReadinessprobeNotset
|
||||||
|
metadata:
|
||||||
|
name: containerreadinessprobenotset
|
||||||
|
spec:
|
||||||
|
enforcementAction: dryrun
|
||||||
|
match:
|
||||||
|
kinds:
|
||||||
|
- apiGroups:
|
||||||
|
- apps.openshift.io
|
||||||
|
- apps
|
||||||
|
kinds:
|
||||||
|
- DeploymentConfig
|
||||||
|
- DaemonSet
|
||||||
|
- Deployment
|
||||||
|
- StatefulSet
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-audit-readiness
|
||||||
|
spec:
|
||||||
|
remediationAction: inform # will be overridden by remediationAction in parent policy
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: musthave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||||
|
kind: ContainerReadinessprobeNotset
|
||||||
|
metadata:
|
||||||
|
name: containerreadinessprobenotset
|
||||||
|
status:
|
||||||
|
totalViolations: 0
|
||||||
|
- objectDefinition:
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: ConfigurationPolicy
|
||||||
|
metadata:
|
||||||
|
name: policy-gatekeeper-admission-readiness
|
||||||
|
spec:
|
||||||
|
remediationAction: inform # will be overridden by remediationAction in parent policy
|
||||||
|
severity: low
|
||||||
|
object-templates:
|
||||||
|
- complianceType: mustnothave
|
||||||
|
objectDefinition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Event
|
||||||
|
metadata:
|
||||||
|
namespace: openshift-gatekeeper-system # set it to the actual namespace where gatekeeper is running if different
|
||||||
|
annotations:
|
||||||
|
constraint_action: deny
|
||||||
|
constraint_kind: ContainerReadinessprobeNotset
|
||||||
|
constraint_name: containerreadinessprobenotset
|
||||||
|
event_type: violation
|
||||||
|
---
|
||||||
|
apiVersion: policy.open-cluster-management.io/v1
|
||||||
|
kind: PlacementBinding
|
||||||
|
metadata:
|
||||||
|
name: binding-policy-gatekeeper-containerreadinessprobenotset
|
||||||
|
placementRef:
|
||||||
|
name: placement-policy-gatekeeper-containerreadinessprobenotset
|
||||||
|
kind: PlacementRule
|
||||||
|
apiGroup: apps.open-cluster-management.io
|
||||||
|
subjects:
|
||||||
|
- name: policy-gatekeeper-readinessprobe
|
||||||
|
kind: Policy
|
||||||
|
apiGroup: policy.open-cluster-management.io
|
||||||
|
---
|
||||||
|
apiVersion: apps.open-cluster-management.io/v1
|
||||||
|
kind: PlacementRule
|
||||||
|
metadata:
|
||||||
|
name: placement-policy-gatekeeper-containerreadinessprobenotset
|
||||||
|
spec:
|
||||||
|
clusterConditions:
|
||||||
|
- status: "True"
|
||||||
|
type: ManagedClusterConditionAvailable
|
||||||
|
clusterSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- { key: policy, operator: In, values: ["opa"] }
|
||||||
Reference in New Issue
Block a user