├── .gitignore ├── .helmignore ├── Chart.yaml ├── LICENSE.pdf ├── README.md ├── TERMS.txt ├── THIRDPARTY.txt ├── config ├── customrules │ └── README.md ├── falco-customrules.yaml └── falco.yaml ├── crds ├── cluster.yaml ├── clusterpolicy.yaml ├── oversight.yaml ├── runtimeruleset.yaml ├── usage.yaml └── workloadimage.yaml ├── docs ├── falco-splunk-hec-secret.md ├── oci-artifact-with-falcoctl.md └── policy-as-code.md ├── sample ├── clusterpolicy.yaml └── runtimeruleset.yaml ├── scripts ├── argocd-cleanup.md ├── argocd-cleanup.sh ├── collect-logs.sh └── openshift-cleanup.sh ├── templates ├── _helpers.tpl ├── admission-controller-role.yaml ├── admission-controller.yaml ├── auth.yaml ├── cluster.yaml ├── compliance-scan-job-role.yaml ├── compliance-scan-job-scc.yaml ├── fargate-injector-role.yaml ├── fargate-injector.yaml ├── k8s-metacollector-role.yaml ├── k8s-metacollector-secret.yaml ├── k8s-metacollector.yaml ├── kube-rbac-proxy-cert.yaml ├── malware-scanner-scc.yaml ├── malware-scanner.yaml ├── mutatingwebhook.yaml ├── outbound-proxy.yaml ├── oversight-controller-role.yaml ├── oversight-controller-scc.yaml ├── oversight-controller.yaml ├── oversight.yaml ├── policy-operator-cluster-role.yaml ├── policy-operator-role.yaml ├── policy-operator.yaml ├── scan-job-scc.yaml ├── scan-manager-config.yaml ├── scan-manager-role.yaml ├── scan-manager.yaml ├── scout │ ├── clusterrole.yaml │ ├── clusterrolebinding.yaml │ ├── configmap-falco-customrules-config.yaml │ ├── configmap.yaml │ ├── daemonset.yaml │ ├── securitycontextconstraints.yaml │ └── serviceaccount.yaml ├── securitycontextconstraints.yaml ├── telemetry.yaml ├── usage-controller-role.yaml ├── usage-controller.yaml ├── usage.yaml ├── validatingwebhook.yaml ├── workload-operator-role.yaml └── workload-operator.yaml └── values.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.bak 3 | *.tmp 4 | .idea/ 5 | .DS_Store 6 | overrides.yaml -------------------------------------------------------------------------------- /.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /Chart.yaml: -------------------------------------------------------------------------------- 1 | name: trendmicro-container-security 2 | description: Trend Micro Cloud One Container Security 3 | appVersion: "2.6.8" 4 | version: "2.6.8" 5 | kubeVersion: ">=1.16.0-0" 6 | apiVersion: v1 7 | deprecated: false 8 | home: https://github.com/trendmicro/cloudone-container-security-helm 9 | maintainers: 10 | - name: Trend Micro 11 | -------------------------------------------------------------------------------- /LICENSE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trendmicro/cloudone-container-security-helm/3b986385b0b7031d44e6158c5ddf149098b80125/LICENSE.pdf -------------------------------------------------------------------------------- /config/customrules/README.md: -------------------------------------------------------------------------------- 1 | # Custom Rules Directory 2 | 3 | ## Rule Files Placement 4 | 5 | Please place your custom rule files (either `.yaml` or `.yml` format) in this directory before executing the `helm install` command. This ensures that your custom rules are properly included in the Helm deployment process. 6 | 7 | ## Additional Information 8 | 9 | For more details on writing custom rules for Falco, you can refer to the official documentation here: [Falco Rules](https://falco.org/docs/rules/basic-elements/). 10 | -------------------------------------------------------------------------------- /crds/cluster.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.15.0 7 | name: clusters.visionone.trendmicro.com 8 | spec: 9 | group: visionone.trendmicro.com 10 | names: 11 | kind: Cluster 12 | listKind: ClusterList 13 | plural: clusters 14 | singular: cluster 15 | scope: Cluster 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: Cluster is the Schema for the clusters API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: ClusterSpec defines the desired state of Cluster 41 | properties: 42 | definition: 43 | description: Cluster's definition 44 | x-kubernetes-preserve-unknown-fields: true 45 | type: object 46 | status: 47 | description: ClusterStatus defines the observed state of Cluster 48 | properties: 49 | conditions: 50 | description: |- 51 | Represents the observations of Cluster current state. 52 | "Registered" to indicate if the cluster is registered to VisionOne. 53 | items: 54 | description: Condition contains details for one aspect of the current 55 | state of this API Resource. 56 | properties: 57 | lastTransitionTime: 58 | description: |- 59 | lastTransitionTime is the last time the condition transitioned from one status to another. 60 | This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. 61 | format: date-time 62 | type: string 63 | message: 64 | description: |- 65 | message is a human readable message indicating details about the transition. 66 | This may be an empty string. 67 | maxLength: 32768 68 | type: string 69 | observedGeneration: 70 | description: |- 71 | observedGeneration represents the .metadata.generation that the condition was set based upon. 72 | For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date 73 | with respect to the current state of the instance. 74 | format: int64 75 | minimum: 0 76 | type: integer 77 | reason: 78 | description: |- 79 | reason contains a programmatic identifier indicating the reason for the condition's last transition. 80 | Producers of specific condition types may define expected values and meanings for this field, 81 | and whether the values are considered a guaranteed API. 82 | The value should be a CamelCase string. 83 | This field may not be empty. 84 | maxLength: 1024 85 | minLength: 1 86 | pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ 87 | type: string 88 | status: 89 | description: status of the condition, one of True, False, Unknown. 90 | enum: 91 | - "True" 92 | - "False" 93 | - Unknown 94 | type: string 95 | type: 96 | description: |- 97 | type of condition in CamelCase or in foo.example.com/CamelCase. 98 | --- 99 | Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be 100 | useful (see .node.status.conditions), the ability to deconflict is important. 101 | The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) 102 | maxLength: 316 103 | pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ 104 | type: string 105 | required: 106 | - lastTransitionTime 107 | - message 108 | - reason 109 | - status 110 | - type 111 | type: object 112 | type: array 113 | x-kubernetes-list-map-keys: 114 | - type 115 | x-kubernetes-list-type: map 116 | visiononeclusterid: 117 | description: Visionone Cluster ID 118 | type: string 119 | visiononedevicetokenexpirationtime: 120 | description: Visionone device token expiration time 121 | format: date-time 122 | type: string 123 | type: object 124 | type: object 125 | served: true 126 | storage: true 127 | subresources: 128 | status: {} 129 | -------------------------------------------------------------------------------- /crds/clusterpolicy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.15.0 7 | name: clusterpolicies.visionone.trendmicro.com 8 | spec: 9 | group: visionone.trendmicro.com 10 | names: 11 | kind: ClusterPolicy 12 | listKind: ClusterPolicyList 13 | plural: clusterpolicies 14 | singular: clusterpolicy 15 | scope: Cluster 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: ClusterPolicy is the Schema for the clusterpolicies API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: ClusterPolicySpec defines the desired state of ClusterPolicy 41 | properties: 42 | exceptions: 43 | description: List of exceptions for the policy. The policy will not 44 | be enforced for workloads matching exception rules. 45 | items: 46 | description: PolicyException defines a policy exception 47 | properties: 48 | namespaces: 49 | description: List of namespaces to apply the exception to. The 50 | exception will be applied to all namespaces by default. 51 | items: 52 | type: string 53 | type: array 54 | properties: 55 | description: Exception properties 56 | x-kubernetes-preserve-unknown-fields: true 57 | type: 58 | description: Type of the exception 59 | type: string 60 | required: 61 | - type 62 | type: object 63 | type: array 64 | rules: 65 | description: List of policy rules 66 | items: 67 | description: PolicyRule defines a policy rule 68 | properties: 69 | action: 70 | default: log 71 | description: Action to take when the rule fails during the admission 72 | control 73 | enum: 74 | - log 75 | - block 76 | type: string 77 | mitigation: 78 | default: log 79 | description: Mitigation to take when the rule fails during continuous 80 | compliance 81 | enum: 82 | - log 83 | - isolate 84 | - terminate 85 | type: string 86 | namespaces: 87 | description: List of namespaces to apply the rule to. The rule 88 | will be applied to all namespaces by default. 89 | items: 90 | type: string 91 | type: array 92 | properties: 93 | description: Policy rule properties 94 | x-kubernetes-preserve-unknown-fields: true 95 | type: 96 | description: Type of the rule 97 | type: string 98 | required: 99 | - action 100 | - type 101 | type: object 102 | x-kubernetes-validations: 103 | - message: Continuous mitigation can only be isolate if deployment 104 | action is block 105 | rule: 'self.mitigation == ''isolate'' ? self.action == ''block'' 106 | : true' 107 | - message: Continuous mitigation can only be terminate if deployment 108 | action is block 109 | rule: 'self.mitigation == ''terminate'' ? self.action == ''block'' 110 | : true' 111 | type: array 112 | xdrEnabled: 113 | default: false 114 | description: Enable XDR Telemetry. Requires runtime security to be 115 | enabled. 116 | type: boolean 117 | type: object 118 | status: 119 | description: ClusterPolicyStatus defines the observed state of ClusterPolicy 120 | properties: 121 | conditions: 122 | description: |- 123 | Represents the observations of ClusterPolicy current state. 124 | "Parsed" to indicate if the policy is able to be parsed successfully 125 | "Applied" to indicate if the policy is applied in VisionOne backend 126 | "InUse" to indicate if the policy is assigned to the cluster 127 | "Drifted" to indicate if the ruleset is drifted from the VisionOne backend 128 | items: 129 | description: Condition contains details for one aspect of the current 130 | state of this API Resource. 131 | properties: 132 | lastTransitionTime: 133 | description: |- 134 | lastTransitionTime is the last time the condition transitioned from one status to another. 135 | This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. 136 | format: date-time 137 | type: string 138 | message: 139 | description: |- 140 | message is a human readable message indicating details about the transition. 141 | This may be an empty string. 142 | maxLength: 32768 143 | type: string 144 | observedGeneration: 145 | description: |- 146 | observedGeneration represents the .metadata.generation that the condition was set based upon. 147 | For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date 148 | with respect to the current state of the instance. 149 | format: int64 150 | minimum: 0 151 | type: integer 152 | reason: 153 | description: |- 154 | reason contains a programmatic identifier indicating the reason for the condition's last transition. 155 | Producers of specific condition types may define expected values and meanings for this field, 156 | and whether the values are considered a guaranteed API. 157 | The value should be a CamelCase string. 158 | This field may not be empty. 159 | maxLength: 1024 160 | minLength: 1 161 | pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ 162 | type: string 163 | status: 164 | description: status of the condition, one of True, False, Unknown. 165 | enum: 166 | - "True" 167 | - "False" 168 | - Unknown 169 | type: string 170 | type: 171 | description: |- 172 | type of condition in CamelCase or in foo.example.com/CamelCase. 173 | --- 174 | Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be 175 | useful (see .node.status.conditions), the ability to deconflict is important. 176 | The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) 177 | maxLength: 316 178 | pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ 179 | type: string 180 | required: 181 | - lastTransitionTime 182 | - message 183 | - reason 184 | - status 185 | - type 186 | type: object 187 | type: array 188 | x-kubernetes-list-map-keys: 189 | - type 190 | x-kubernetes-list-type: map 191 | visiononeclusterid: 192 | description: Visionone Cluster ID 193 | type: string 194 | visiononepolicyid: 195 | description: Visionone Policy ID 196 | type: string 197 | type: object 198 | type: object 199 | served: true 200 | storage: true 201 | subresources: 202 | status: {} -------------------------------------------------------------------------------- /crds/oversight.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: oversights.cloudone.trendmicro.com 5 | labels: 6 | app.kubernetes.io/name: oversight-trendmicro-container-security 7 | spec: 8 | group: cloudone.trendmicro.com 9 | names: 10 | kind: Oversight 11 | listKind: OversightList 12 | plural: oversights 13 | singular: oversight 14 | scope: Namespaced 15 | versions: 16 | - name: v1 17 | served: true 18 | storage: true 19 | schema: 20 | openAPIV3Schema: 21 | description: Oversight is the Schema for the oversights API 22 | properties: 23 | apiVersion: 24 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 25 | type: string 26 | kind: 27 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 28 | type: string 29 | metadata: 30 | type: object 31 | spec: 32 | description: OversightSpec defines the desired state of Oversight 33 | type: object 34 | status: 35 | description: OversightStatus defines the observed state of Oversight 36 | type: object 37 | type: object 38 | conversion: 39 | # None conversion assumes the same schema for all versions and only sets the apiVersion 40 | # field of custom resources to the proper value 41 | strategy: None 42 | -------------------------------------------------------------------------------- /crds/runtimeruleset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.15.0 7 | name: runtimerulesets.visionone.trendmicro.com 8 | spec: 9 | group: visionone.trendmicro.com 10 | names: 11 | kind: RuntimeRuleset 12 | listKind: RuntimeRulesetList 13 | plural: runtimerulesets 14 | singular: runtimeruleset 15 | scope: Cluster 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: RuntimeRuleset is the Schema for the runtimerulesets API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | properties: 41 | definition: 42 | x-kubernetes-preserve-unknown-fields: true 43 | type: object 44 | status: 45 | description: RuntimeRulesetStatus defines the observed state of RuntimeRuleset 46 | properties: 47 | conditions: 48 | description: |- 49 | Represents the observations of RuntimeRuleset current state. 50 | "Parsed" to indicate if the ruleset is able to be parsed successfully 51 | "Applied" to indicate if the ruleset is applied in VisionOne backend 52 | "InUse" to indicate if the ruleset is assigned to a policy 53 | "Drifted" to indicate if the ruleset is drifted from the VisionOne backend 54 | items: 55 | description: Condition contains details for one aspect of the current 56 | state of this API Resource. 57 | properties: 58 | lastTransitionTime: 59 | description: |- 60 | lastTransitionTime is the last time the condition transitioned from one status to another. 61 | This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. 62 | format: date-time 63 | type: string 64 | message: 65 | description: |- 66 | message is a human readable message indicating details about the transition. 67 | This may be an empty string. 68 | maxLength: 32768 69 | type: string 70 | observedGeneration: 71 | description: |- 72 | observedGeneration represents the .metadata.generation that the condition was set based upon. 73 | For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date 74 | with respect to the current state of the instance. 75 | format: int64 76 | minimum: 0 77 | type: integer 78 | reason: 79 | description: |- 80 | reason contains a programmatic identifier indicating the reason for the condition's last transition. 81 | Producers of specific condition types may define expected values and meanings for this field, 82 | and whether the values are considered a guaranteed API. 83 | The value should be a CamelCase string. 84 | This field may not be empty. 85 | maxLength: 1024 86 | minLength: 1 87 | pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ 88 | type: string 89 | status: 90 | description: status of the condition, one of True, False, Unknown. 91 | enum: 92 | - "True" 93 | - "False" 94 | - Unknown 95 | type: string 96 | type: 97 | description: |- 98 | type of condition in CamelCase or in foo.example.com/CamelCase. 99 | --- 100 | Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be 101 | useful (see .node.status.conditions), the ability to deconflict is important. 102 | The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) 103 | maxLength: 316 104 | pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ 105 | type: string 106 | required: 107 | - lastTransitionTime 108 | - message 109 | - reason 110 | - status 111 | - type 112 | type: object 113 | type: array 114 | x-kubernetes-list-map-keys: 115 | - type 116 | x-kubernetes-list-type: map 117 | visiononerulesetid: 118 | description: Visionone Ruleset ID 119 | type: string 120 | type: object 121 | type: object 122 | served: true 123 | storage: true 124 | subresources: 125 | status: {} -------------------------------------------------------------------------------- /crds/usage.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: usages.cloudone.trendmicro.com 5 | labels: 6 | app.kubernetes.io/name: oversight-trendmicro-container-security 7 | spec: 8 | group: cloudone.trendmicro.com 9 | names: 10 | kind: Usage 11 | listKind: UsageList 12 | plural: usages 13 | singular: usage 14 | scope: Namespaced 15 | versions: 16 | - name: v1 17 | served: true 18 | storage: true 19 | schema: 20 | openAPIV3Schema: 21 | description: Usage is the Schema for the usages API 22 | properties: 23 | apiVersion: 24 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 25 | type: string 26 | kind: 27 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 28 | type: string 29 | metadata: 30 | type: object 31 | spec: 32 | description: UsageSpec defines the desired state of Usage 33 | type: object 34 | status: 35 | description: UsageStatus defines the observed state of Usage 36 | type: object 37 | type: object 38 | conversion: 39 | # None conversion assumes the same schema for all versions and only sets the apiVersion 40 | # field of custom resources to the proper value 41 | strategy: None 42 | -------------------------------------------------------------------------------- /crds/workloadimage.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.9.2 7 | creationTimestamp: null 8 | name: workloadimages.cloudone.trendmicro.com 9 | labels: 10 | app.kubernetes.io/name: workloadimage-trendmicro-container-security 11 | spec: 12 | group: cloudone.trendmicro.com 13 | names: 14 | kind: WorkloadImage 15 | listKind: WorkloadImageList 16 | plural: workloadimages 17 | singular: workloadimage 18 | scope: Namespaced 19 | versions: 20 | - name: v1 21 | schema: 22 | openAPIV3Schema: 23 | description: WorkloadImage is the Schema for the workloadImages API 24 | properties: 25 | apiVersion: 26 | description: 'APIVersion defines the versioned schema of this representation 27 | of an object. Servers should convert recognized schemas to the latest 28 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 29 | type: string 30 | kind: 31 | description: 'Kind is a string value representing the REST resource this 32 | object represents. Servers may infer this from the endpoint the client 33 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 34 | type: string 35 | metadata: 36 | type: object 37 | spec: 38 | description: WorkloadImageSpec defines the desired state of WorkloadImage 39 | properties: 40 | containerName: 41 | type: string 42 | imageID: 43 | type: string 44 | imageName: 45 | type: string 46 | imagePullSecret: 47 | items: 48 | description: LocalObjectReference contains enough information to 49 | let you locate the referenced object inside the same namespace. 50 | properties: 51 | name: 52 | description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names 53 | TODO: Add other useful fields. apiVersion, kind, uid?' 54 | type: string 55 | type: object 56 | x-kubernetes-map-type: atomic 57 | type: array 58 | namespace: 59 | type: string 60 | required: 61 | - containerName 62 | - imageID 63 | - imageName 64 | - namespace 65 | type: object 66 | required: 67 | - spec 68 | type: object 69 | additionalPrinterColumns: 70 | - name: Image Name 71 | type: string 72 | jsonPath: .spec.imageName 73 | - name: Age 74 | type: date 75 | jsonPath: .metadata.creationTimestamp 76 | - name: Scan Status 77 | type: string 78 | jsonPath: .metadata.labels.scan-status 79 | served: true 80 | storage: true 81 | -------------------------------------------------------------------------------- /docs/falco-splunk-hec-secret.md: -------------------------------------------------------------------------------- 1 | 2 | # Falco http_output with Splunk HEC token in a secret 3 | 4 | ## Preconditions 5 | 6 | ### Splunk HEC token is added as a secret 7 | 8 | A secret *splunk-hec-secret* is added into namespace *trendmicro-system* with key *hec_secret* containing Splunk HEC token: 9 | 10 | > *trendmicro-system* is a default namespace to deploy this chart. 11 | > Normally, it is created during helm chart deployment with *--create-namespace* helm flag. 12 | > If this chart is not deployed yet, the namespace may be missed. 13 | > 14 | > Add the namespace before creating a secret: 15 | > ```sh 16 | > kubectl create namespace trendmicro-system 17 | > ``` 18 | 19 | To create a secret: 20 | ```sh 21 | kubectl create secret \ 22 | generic splunk-hec-secret \ 23 | --from-literal=hec_secret={Splunk HEC token} \ 24 | --namespace trendmicro-system 25 | ``` 26 | 27 | ## Setup 28 | 29 | ### enable runtimeSecurity and custom rules 30 | 31 | *.runtimeSecurity.enabled* 32 | *.runtimeSecurity.customRules.enabled* 33 | 34 | ### set Splunk HEC token authorization secret name 35 | 36 | *customRules.output.splunk.hecTokenSecretName* specify a name of a secret which contains Splunk HEC token 37 | 38 | Example: 39 | ```yaml 40 | runtimeSecurity: 41 | enabled: true 42 | customRules: 43 | enabled: true 44 | output: 45 | json: true 46 | splunk: 47 | url: https://indexer.trend-us-1.c1splunk.trendmicro.com:8088/services/collector/raw?sourcetype=serhiip 48 | headers: 49 | - "X-Splunk-Request-Channel: b2b7e14f-e8a2-4bb5-a422-434611bc6ecb" 50 | # - "Authorization: Splunk 123" 51 | hecTokenSecretName: 'splunk-hec-secret' 52 | ``` 53 | 54 | ### remove existing Authorization header(s) 55 | 56 | Helm chart automatically adds required Splunk Authorization headers , no other auth headers needed. 57 | 58 | ### validate 59 | 60 | ```sh 61 | helm template https://github.com/trendmicro/cloudone-container-security-helm/archive/master.tar.gz --dry-run=server --values overrides_hec_secret.yaml --debug --namespace trendmicro-system > manifest.yaml 62 | ``` 63 | 64 | ## Errors 65 | 66 | ### secret is missing 67 | 68 | Its an error if secret is missing when *runtimeSecurity.customRules.output.splunk.auth_use_hec_token* is true. 69 | Add a secret as described above. 70 | 71 | ### extra Authorization headers for Splunk 72 | 73 | Its an error if other Authorization headers are added when *runtimeSecurity.customRules.output.splunk.auth_use_hec_token* is true. 74 | Remove extra Authorization headers. 75 | -------------------------------------------------------------------------------- /docs/oci-artifact-with-falcoctl.md: -------------------------------------------------------------------------------- 1 | # ruleFiles from OCI repository 2 | 3 | ## Configuration 4 | 5 | TrendMicro helm chart can be configured to automatically download and install ruleFiles from OCI artifacts. 6 | 7 | This functionality is off by default. 8 | 9 | To enable automatic installation of ruleFiles from OCI repositories, add the following sections into overrides: 10 | 11 | ```yaml 12 | cloudOne: 13 | ... 14 | runtimeSecurity: 15 | enabled: true 16 | customRules: 17 | enabled: true 18 | output: 19 | json: true 20 | splunk: 21 | url: {splunk url} 22 | headers: 23 | - "X-Splunk-Request-Channel: {splunk channel id}" 24 | hecTokenSecretName: 'splunk-hec-secret' 25 | ociRepository: 26 | enabled: true 27 | ruleFiles: 28 | - shell_in_container_serhiip_0_0_5.yaml 29 | - falco_rules.yaml 30 | artifactUrls: 31 | - ghcr.io/falcosecurity/rules/falco-rules:latest 32 | - public.ecr.aws/t9h5t7r4/serhiip/falcoctl:0 33 | basicAuthTokenSecretName: customrules-falcoctl-registry-auth-basic-missing-repo 34 | params: 35 | clusterName: "optional cluster name for splunk event field cluster_name" 36 | 37 | ``` 38 | **NOTE: these fields are subject to change** 39 | 40 | Section `cloudOne.runtimeSecurity.customRules.ociRepository.artifactUrls` is a list of OCI repository URLs to pull artifacts from. 41 | For URL format, see [falcoctl push](https://github.com/falcosecurity/falcoctl?tab=readme-ov-file#falcoctl-registry-push). 42 | 43 | Section `cloudOne.runtimeSecurity.customRules.ociRepository.ruleFiles` is a list of filenames, to be continuously monitored as OCI artifacts. 44 | Each file is expected to be a valid falco rulefile. There is no restrictions on how files are distributed between artifacts. A single artifact may contain all listed files or multiple artifacts may contain some of them. falco ignores files not listed by `.ociRepository.ruleFiles`. 45 | 46 | Consult [falcoctl registry](https://github.com/falcosecurity/falcoctl?tab=readme-ov-file#falcoctl-registry) for details how to push artifacts into OCI repo using falcoctl. 47 | 48 | Section `cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName` is a string naming a kubernetes secret inside `trendmicro-system` namespace. The secret is expected to include `falcoctl` key, its value is interpreted as basic auth credentials for private OCI repos. The format is the same as falcoctl env variable `FALCOCTL_REGISTRY_AUTH_BASIC`, described here [falcoctl environment variables](https://github.com/falcosecurity/falcoctl?tab=readme-ov-file#falcoctl-environment-variables). 49 | 50 | Use of this secret: 51 | - with `.artifactUrls` only listing public repos, this field may be empty string or just skipped 52 | - with `.artifactUrls` listing some/all private repos, this field is required, the secret is required in the namespace `trendmicro-system` 53 | 54 | NOTE: its a deployment error if `.basicAuthTokenSecretName` is the secret specified but missed in namespace `trendmicro-system`. 55 | 56 | NOTE: with `.basicAuthTokenSecretName` secret present but contains no key `falcoctl`, the scout pod will fail to start. 57 | 58 | NOTE: with `.basicAuthTokenSecretName` secret present and contains key `falcoctl` but its value represents wrong credentials, falcoctl will not be able to install artifacts from private repos and falco will run with rules defined at deployment. 59 | 60 | Section `cloudOne.runtimeSecurity.customRules.output.splunk` describes endpoint and credentials for `artifacts-accepted` and `artifacts-ignored` events. See [this](falco-splunk-hec-secret.md) for details. 61 | 62 | NOTE: if splunk URL or auth headers are invalid, no events are expected, falco is not affected. 63 | 64 | Optionally, section `.Values.scout.falco.ociRepository.logLevel` can be set to `info` to lower CPU impact. In this case `.output_fields.enabled_rules` will be empty. 65 | 66 | Section `cloudOne.runtimeSecurity.customRules.params.clusterName` is a string, optional, helps to identify which cluster sent splunk event; copied into splunk event `cluster_name` field; if not set, `cloudOne.clusterName` is used instead; if `cloudOne.clusterName` also not set, then `cluster_name` will be empty. 67 | 68 | ## OCI repo 69 | 70 | OCI artifact consists of one or more rulesfiles, packaged, pushed into OCI repo, tagged with versions. 71 | See [artifact push](https://github.com/falcosecurity/falcoctl?tab=readme-ov-file#falcoctl-registry-push) for details. 72 | 73 | ## Artifact Versions 74 | 75 | Falcoctl supports floating versions, i.e. every time version "0.1.0" is pushed, extra tags added "0" and "0.1". It allows `.ociRepository.artifactUrls` to specify major versions only, i.e. "float over" fully qualified tags/versions and pickup the most recent version without reconfiguration. 76 | See [semver](https://semver.org/). 77 | 78 | ## Possible Issues 79 | 80 | ### Issue: help install/upgrade failed with `secret *** is expected` 81 | 82 | Possible reason 1: secret `cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName` 83 | is missing from `trendmicro-system` namespace. 84 | 85 | Solution: follow recommendations in Section `cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName` on how to create the secret. 86 | 87 | Possible reason 2: secret `cloudOne.runtimeSecurity.customRules.output.splunk.hecTokenSecretName` 88 | is missing from `trendmicro-system` namespace. 89 | 90 | Solution: follow [this](./docs/falco-splunk-hec-secret.md) on how to create the secret. 91 | 92 | ### Issue: scout pod status is `CreateContainerConfigError` 93 | 94 | Additional info: cluster events include error `Error: couldn't find key falcoctl in Secret ...` 95 | 96 | Possible reason: secret `cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName` 97 | contains no key `falcoctl`. 98 | 99 | Solution: add key `falcoctl`, follow recommendations in Section `cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName` 100 | 101 | ### Issue: OCI artifacts are not installed 102 | 103 | Additional info: logs of container `falco-customrules` in `scout` pod show errors accessing OCI repo. 104 | 105 | ```sh 106 | ... 107 | an error occurred while fetching descriptor from remote repository 108 | ... 109 | ``` 110 | 111 | or 112 | 113 | ```sh 114 | ... 115 | Unable to pull config layer 116 | ... 117 | ``` 118 | 119 | Possible reason: secret `cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName` is malformed or defines wrong password or defines wrong repo URL. 120 | 121 | Solution: double check the format is the same as falcoctl env variable `FALCOCTL_REGISTRY_AUTH_BASIC`, described here [falcoctl environment variables](https://github.com/falcosecurity/falcoctl?tab=readme-ov-file#falcoctl-environment-variables). 122 | Double check repo URL and password is valid. 123 | 124 | ### Issue: OCI artifacts events are not visible in Splunk 125 | 126 | #### Cause: Splunk HEC channel is not correct 127 | 128 | Additional info: logs of container `falco-customrules` in `scout` pod show HEC messages being sent with no issues. 129 | 130 | ```sh 131 | {"source":"oci artifacts falcoctl","cluster_name": 132 | ... 133 | msg="HTTP response status: 200" 134 | ... 135 | msg="{\"text\":\"Success\",\"code\":0,\"ackId\":11}" 136 | ... 137 | ``` 138 | 139 | Possible reason: section `cloudOne.runtimeSecurity.customRules.output.splunk.headers` includes no or incorrect header `X-Splunk-Request-Channel`. 140 | 141 | Solution: Double check Splunk request channel is valid. 142 | 143 | #### Cause: Splunk HEC token or Splunk URL is invalid 144 | 145 | Additional info: logs of container `falco-customrules` in `scout` pod show HTTP errors while sending events to Splunk. 146 | 147 | ```sh 148 | ... 149 | "unable to post data" error="Post \"https://wrong.url\": dial tcp: lookup wrong.url on {node IP}: no such host" 150 | ... 151 | ``` 152 | 153 | Possible reason: section `cloudOne.runtimeSecurity.customRules.output.splunk` is not correct. 154 | 155 | Solution: Provide valid URL and HTTP auth Bearer token as specified [here](./docs/falco-splunk-hec-secret.md). 156 | 157 | #### Cause: Splunk HEC info is not specified 158 | 159 | Additional info: logs of container `falco-customrules` in `scout` pod show HTTP errors while sending events to Splunk. 160 | 161 | ```sh 162 | ... 163 | invalid value "" for flag -H: header malformed, expect {key}:{value} 164 | ... 165 | ``` 166 | 167 | Possible reason: section `cloudOne.runtimeSecurity.customRules.output.splunk` is missing. 168 | 169 | Solution: Provide Splunk HEC info as specified [here](./docs/falco-splunk-hec-secret.md). 170 | 171 | ### Issue: Rules from certain rulefile are not visible in Splunk event 172 | 173 | Possible reason: section `cloudOne.runtimeSecurity.customRules.ociRepository.ruleFiles` is missing or specify rule files missing from artifact. 174 | 175 | Solution: make sure this section lists rules file actually present in OCI artifact. 176 | 177 | 178 | ## How It Works 179 | 180 | With `runtimeSecurity.enabled` and `customRules.enabled`, additional container `falco-customrules` is spawned. 181 | This container runs falco configured to read ruleFiles `.ociRepository.ruleFiles`, watch for changes in those files and perform "hot restart". 182 | 183 | With `ociRepository.enabled` false, the container `falco-customrules` will use rules configured at deployment. 184 | 185 | With `ociRepository.enabled` true, the container `falco-customrules` will do the following: 186 | - run an instance of falcoctl, configured to watch/download/install OCI artifacts from `.ociRepository.artifactUrls` ( every 6 hours, hardcoded ) 187 | - send messages to splunk when new artifact(s) is installed / accepted / ignored by falco 188 | 189 | When new version of an artifact is available, falcoctl installs it into a directory shared with falco. 190 | Falco detects changes in files listed by `.ociRepository.ruleFiles`, performs "hot restart". Changes on the rest of files are ignored. 191 | 192 | "Hot restart" is performed in 3 steps: 193 | - falco validates a syntax of all rules found in files listed by `.ociRepository.ruleFiles` 194 | - when syntax valid, falco begings to monitor those rules ( assuming artifacts are accepted ) 195 | - when any rule syntax is invalid ( this includes all rules, not limited to most recent change ), falco ignores changes and continues with most recent good configuration ( assuming recently installed artifacts are ignored ) 196 | 197 | `artifacts accepted` and `artifacts ignored` events are emitted accordingly, see below. 198 | 199 | ## Events 200 | 201 | ### Format 202 | 203 | Two kinds of events are generated, determined by `output` field: 204 | - `artifacts accepted` , with `"output":"artifacts accepted"` 205 | - `artifact ignored`, with `"output":"artifacts ignored"` 206 | 207 | ```json 208 | { 209 | "source":"oci artifacts falcoctl", 210 | "cluster_name":"value of {cloudOne.runtimeSecurity.customRules.params.clusterName} or {cloudOne.clusterName}", 211 | "hostname":"{HOSTNAME of container}", 212 | "time":"2025-03-06T16:54:48Z", 213 | "output":"artifacts {accepted|ignored}", 214 | "output_fields":{ 215 | "artifacts":[ 216 | { 217 | "artifactName":"{artifact name including repo and tag}", 218 | "digest":"sha256:{artifact sha}", 219 | "type":"rulesfile" 220 | ... 221 | }, 222 | ... 223 | ], 224 | "enabled_rules":[ 225 | "Clear Log Activities", 226 | "Contact K8S API Server From Container", 227 | "PTRACE attached to process", 228 | ... 229 | ] 230 | } 231 | } 232 | ``` 233 | 234 | ### Logic 235 | 236 | At container startup, event `artifacts accepted` is emitted with empty `output_fields.artifacts` and only rules defined at deployment time. 237 | 238 | When new artifact(s) is installed and the rules are validated by falco during "hot restart", event `artifacts accepted` is emitted with recently installed artifacts listed by `output_fields.artifacts` 239 | and currently monitored rules listed by `.output_fields.enabled_rules` ( a superposition of all good rules installed so far from all artifacts since last container restart and rules configured at deployment ). 240 | 241 | When falco detects some rules are malformed, event `artifacts ignored` is emitted with recently installed artifacts in `output_fields.artifacts` ( any artifact may be a source of a bad rule ) and currently monitored good rules listed by `.output_fields.enabled_rules`. List of recently installed artifacts is preserved until next successful "hot restart". 242 | 243 | NOTE: when falco detects a malformed rule during "hot restart", falco interrupts "hot restart" and continues to run on last known good configuration; this configuration is represented by all `artifacts accepted` events since last container restart; once the error is fixed ( possibly by a new version of the artifact and bad rule is corrected ) , falco performs "hot restart" once again , producing `artifacts ignored` ( more bad rules ) or producing `artifacts accepted` ( all rules are good ). 244 | 245 | NOTE: `output_fields.artifacts` lists all currently monitored rules. It is a superposition of rules from ruleFiles provided at deployment time and all artifacts installed since last container restart. To collect all installed artifacts, collect all `artifacts installed` events since most recent container restart ( this moment is marked by event `artifacts installed` with empty list of artifacts ). 246 | 247 | NOTE: falcoctl never deletes ruleFiles. If a new version of an artifact no longer includes certain rulefile, its last known version ( along with rules it defines ) remains on a filesystem until container restart and still evaluated by falco. To effectively remove a rulefile, include empty file with the same name into the artifact. 248 | 249 | ### Implementation Details around Events 250 | 251 | `falco-customrules` container maintains four lists of artifacts: 252 | - `artifact-installed`, list of artifacts collected from falcoctl activity 253 | - `artifact-accepted`, a snapshot of `artifact-installed` at the moment falco "hot restart" succeeded; content of `artifact-installed` is dropped at this moment to avoid be sent again 254 | - `artifact-ignored`, a snapshot of `artifact-installed` at the moment falco "hot restart" failed; content of `artifact-installed` is preserved, pending next `artifact-accepted` 255 | - `active-rules`, a list of rules reported by falco at the most recent successful startup; always indicates currently monitored rules 256 | 257 | NOTE: `output_fields.artifacts` typically includes 1 artifact, a new version of some recently updated artifact. In case of malformed rules followed by possibly few corrections ( one or more new versions pushed ), multiple artifacts may be reported. 258 | Another case when `output_fields.artifacts` includes multiple entries is at container startup: falcoctl pulls all artifacts simultaneously, causing a waterfall of changes, falco may pick those changes one by one or at once, producing one or more `artifact-installed` events. 259 | 260 | 261 | -------------------------------------------------------------------------------- /docs/policy-as-code.md: -------------------------------------------------------------------------------- 1 | # Managing Container Security policies with Policy as Code 2 | 3 | With **Policy as Code**, define the Container Security policy and runtime ruleset as custom resources. The Container Security policy operator will manage the lifecycle of the policy resources, create and manage the policy in Vision One, and reconcile with the custom resources in the cluster. The policy operator also manages the policy and ruleset assignments to your cluster. 4 | 5 | - **Version Control**: Policy resources can be managed with version control, allowing for easy tracking of changes 6 | - **Access Control**: Policy resources can be managed with Kubernetes RBAC, ensuring that only authorized users can create or modify policies 7 | - **CI/CD Integration**: Policy resources can be deployed using CI/CD or GitOps workflows alongside other Kubernetes manifests 8 | - **Operator Management**: The policy operator handles the creation and management of policies and rulesets in Vision One, ensuring alignment with the policy custom resources in the cluster 9 | 10 | Container Security supports the following policy resource types: 11 | 12 | - **User Managed** - Policies created via the UI or API and managed by the user 13 | - **Cluster Managed** - Policies created as custom resources in the cluster and managed by the policy operator. These policies can be managed through the custom resources in the cluster 14 | - Cluster Managed policy is read-only in Vision One UI and API and can only be managed through the custom resources in the cluster 15 | - Policy can not be deleted or unassigned from the cluster by the user in the Vision One UI or API 16 | - Policy can not be updated in the Vision One UI or API 17 | 18 | ## Getting Started 19 | 20 | The policy operator is disabled by default. To enable, update the overrides.yaml file: 21 | 22 | ```yaml 23 | cloudOne: 24 | policyOperator: 25 | enabled: true 26 | clusterPolicyName: 27 | ``` 28 | 29 | To use policy as code, simply create the cluster policy and runtime ruleset custom resources in your cluster. To disable policy as code, delete the cluster policy and runtime ruleset custom resources. 30 | 31 | Note: Only one cluster policy can be active at a time. The name of the cluster policy custom resource is specified in the overrides.yaml file and the policy operator will only reconcile the policy with the specified name. 32 | 33 | To interact with the custom resources, use the following kind names: 34 | - `clusterpolicy` for Cluster Policy 35 | - `runtimeruleset` for Runtime Ruleset 36 | 37 | ## Policy Custom Resource 38 | 39 | The Cluster Policy defines the rules and exceptions for admission control and continuous oversight.The `ClusterPolicy` specification includes: 40 | 41 | - **xdrEnabled**: Boolean for enabling XDR telemetry runtime rules 42 | - **rules**: An array of deployment/continuous rules with the following attributes: 43 | - **type**: Type of policy rule 44 | - **action**: Action to take on rule match during admission control (one of: `log` or `block`) 45 | - **mitigation**: Action to take on rule match during continuous oversight (one of: `log`, `terminate`, or `isolate`) 46 | - **properties**: Rule properties object to specify additional properties for rule type 47 | - **namespaces**: Array of namespaces to apply the rule to. The rule will be applied to all namespaces if not specified 48 | - **exceptions**: An array of policy exception rules to exclude certain images from policy enforcement. Each exception rule has the following attributes: 49 | - **type**: Type of policy exception rule. Supported types are: 50 | - `imageName` 51 | - `imageTag` 52 | - `imagePath` 53 | - `imageRegistry` 54 | - **properties**: Exception properties object to specify additional properties for exception rule 55 | - **operator**: Conditional operator to apply to the exception values. Supported operators are oneOf `equals`, `notEquals`, `contains`, `notContains` 56 | - **values**: Array of string values to match for the exception rule 57 | - **namespaces**: Array of namespaces to apply the exception rules to. The exceptions will be applied to all namespaces if not specified 58 | 59 | ### Policy Rule Types 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 123 | 124 | 125 | 126 | 137 | 138 | 139 | 140 | 141 | 152 | 153 | 154 | 155 | 156 | 167 | 168 | 169 | 170 | 171 | 182 | 183 | 184 | 185 | 186 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 219 | 220 | 221 | 222 | 223 | 239 | 240 | 241 | 242 | 243 | 258 | 259 | 260 | 261 | 262 | 277 | 278 |
Rule TypeDescriptionRule Properties (Required)
hostIPCContainers with hostIPC set to true
hostNetworkContainers with hostNetwork set to true
hostPIDContainers with hostPID set to true
runAsNonRootSecurity Context with runAsNonRoot set to false
privilegedSecurity Context with privileged set to true
allowPrivilegeEscalationSecurity Context with allowPrivilegeEscalation set to true
readOnlyRootFilesystemSecurity Context with readOnlyRootFilesystem is false
podPortForwardCreating a port-forward on a running pod
podExecExecuting in/attaching to a running pod
containerCapabilitiesContainer capability restrictionscapabilityRestriction - type of container capability restriction to enforce 116 |
    117 |
  • restrict-nondefaults
  • 118 |
  • restrict-all
  • 119 |
  • baseline
  • 120 |
  • restricted
  • 121 |
122 |
imageRegistryContainers running images matching registries 127 | operator - conditional operator to apply to values 128 |
    129 |
  • equals
  • 130 |
  • notEquals
  • 131 |
  • contains
  • 132 |
  • notContains
  • 133 |
  • startsWith
  • 134 |
135 | values - array of string values to match for the rule type 136 |
imageNameContainers running images matching names 142 | operator - conditional operator to apply to values 143 |
    144 |
  • equals
  • 145 |
  • notEquals
  • 146 |
  • contains
  • 147 |
  • notContains
  • 148 |
  • startsWith
  • 149 |
150 | values - array of string values to match for the rule type 151 |
imageTagContainers running images matching tags 157 | operator - conditional operator to apply to values 158 |
    159 |
  • equals
  • 160 |
  • notEquals
  • 161 |
  • contains
  • 162 |
  • notContains
  • 163 |
  • startsWith
  • 164 |
165 | values - array of string values to match for the rule type 166 |
imagePathContainers running images matching paths. The path includes the registry, name and tag 172 | operator - conditional operator to apply to values 173 |
    174 |
  • equals
  • 175 |
  • notEquals
  • 176 |
  • contains
  • 177 |
  • notContains
  • 178 |
  • startsWith
  • 179 |
180 | values - array of string values to match for the rule type 181 |
imagesNotScannedImages that have not been scanned for one of vulnerability, malware or secrets in the given period 187 | scanType - Type of artifact scan 188 |
    189 |
  • vulnerability
  • 190 |
  • malware
  • 191 |
  • secret
  • 192 |
193 | maxScanAge - Maximum age of the scan result in days (Integer value between 0 and 30 days) 194 |
imagesWithMalwareImages with malware
imagesWithSecretsImages with secrets
imagesWithVulnerabilitiesImages with vulnerabilities of severity or higher 210 | severity - severity of the vulnerability 211 |
    212 |
  • critical
  • 213 |
  • high
  • 214 |
  • medium
  • 215 |
  • low
  • 216 |
  • any
  • 217 |
218 |
imagesWithCVSSAttackVectorImages with vulnerabilities with specific attack vector of severity or higher 224 | severity - severity of the vulnerability 225 |
    226 |
  • critical
  • 227 |
  • high
  • 228 |
  • medium
  • 229 |
  • low
  • 230 |
  • any
  • 231 |
232 | attackVector - CVSS attack vector 233 |
    234 |
  • network
  • 235 |
  • physical
  • 236 |
  • adjacent
  • 237 |
238 |
imagesWithCVSSAttackComplexityImages with vulnerabilities with specific attack complexity of severity or higher 244 | severity - severity of the vulnerability 245 |
    246 |
  • critical
  • 247 |
  • high
  • 248 |
  • medium
  • 249 |
  • low
  • 250 |
  • any
  • 251 |
252 | attackComplexity - CVSS attack complexity 253 |
    254 |
  • low
  • 255 |
  • high
  • 256 |
257 |
imagesWithCVSSAvailabilityImpactImages with vulnerabilities with specific availability impacts of severity or higher 263 | severity - severity of the vulnerability 264 |
    265 |
  • critical
  • 266 |
  • high
  • 267 |
  • medium
  • 268 |
  • low
  • 269 |
  • any
  • 270 |
271 | availabilityImpact - CVSS availability impact 272 |
    273 |
  • low
  • 274 |
  • high
  • 275 |
276 |
279 | 280 | ### Sample ClusterPolicy Custom Resource 281 | 282 | You can find a sample `ClusterPolicy` custom resource in [sample/clusterpolicy.yaml](../sample/clusterpolicy.yaml). 283 | 284 | To create the policy, apply the custom resource yaml: 285 | 286 | ```shell 287 | kubectl apply -f clusterpolicy.yaml 288 | ``` 289 | 290 | 291 | ## Runtime Ruleset Custom Resource 292 | 293 | The Runtime Ruleset defines the rules for runtime security. These Falco rules are managed by Trend Micro and referenced with the ruleID. The `RuntimeRuleset` spec contains the runtime definition with two fields: labels and rules. 294 | 295 | - **labels**: array of pod labels to which the rules are applied using label selectors. Without the labels the rules are applied to all pods 296 | - **key**: label key 297 | - **value**: label value 298 | - **rules**: array of rule IDs and mitigation to apply when the rule is triggered 299 | - **ruleID**: The Trend Micro runtime ruleID as `TM-{8 digit id}` (example: TM-00000001) - [List of available rules](https://docs.trendmicro.com/en-us/documentation/article/trend-vision-one-predefined-rules) 300 | - **mitigation**: Action to take on rule match (one of: `log`, `terminate`, or `isolate`) 301 | 302 | ### Sample RuntimeRuleset Custom Resource 303 | 304 | You can find a sample `RuntimeRuleset` custom resource in [sample/runtimeruleset.yaml](../sample/runtimeruleset.yaml). 305 | 306 | To create the runtime ruleset, apply the custom resource yaml: 307 | 308 | ```shell 309 | kubectl apply -f runtimeruleset.yaml 310 | ``` 311 | 312 | ## Understanding the Custom Resource Status 313 | 314 | The policy operator will update the status of the custom resources to reflect the status of the policy resources in Vision One. 315 | 316 | For the `ClusterPolicy` custom resource, the status will include the following fields: 317 | 318 | - **Conditions**: An array of conditions of the following types: 319 | - **Parsed**: The policy has been parsed into a format that can be applied for enforcement 320 | - **Applied**: The policy has been created in Vision One 321 | - **Attached**: The policy has been assigned to the cluster 322 | - **Drifted**: The policy in Vision One has drifted from the custom resource spec 323 | - **VisionOnePolicyID**: The ID of the policy in Vision One 324 | - **VisionOneClusterID**: The ID of the cluster in Vision One 325 | 326 | For the `RuntimeRuleset` custom resource, the status will include the following fields: 327 | 328 | - **Conditions**: An array of conditions of the following types: 329 | - **Parsed**: The ruleset has been parsed into a format that can be applied for enforcement 330 | - **Applied**: The ruleset has been created in Vision One 331 | - **Attached**: The ruleset has been assigned to the policy 332 | - **Drifted**: The ruleset in Vision One has drifted from the custom resource spec 333 | - **VisionOneRulesetID**: The ID of the ruleset in Vision One 334 | 335 | To view the status of the custom resources, use the following command: 336 | 337 | ```shell 338 | kubectl get clusterpolicy -o json | jq .status 339 | kubectl get runtimeruleset -o json | jq .status 340 | ``` 341 | 342 | ### Policy Parsing and Validation 343 | 344 | The policy operator will parse the custom resources and validate the contents. If the policy or ruleset is invalid, the status condition **Parsed** will be updated to reflect the error. The policy operator will continue to create or update the resources but exclude the invalid rules. 345 | 346 | See the **Message** field in the status condition **Parsed** for more information on parsing errors. The rule number and error details will be included in the message field for all invalid rules. 347 | 348 | ## Allow Drift from Custom Resource 349 | 350 | By default, the policy operator will ensure that the policy and ruleset in Vision One match the custom resource spec. Vision One allows Security Admins to make temporary changes to cluster managed policies and their rulesets in the UI by enabling "allow drift" from the custom resource in Container Inventory UI. 351 | 352 | To toggle allow drift settings, admins can update this setting on the cluster in the Vision One UI. The policy operator will respect the allow drift setting and will not attempt to reconcile the policy or ruleset if the allow drift setting is enabled. If the policy or ruleset in Vision One drifts from the custom resource spec, the status condition **Drifted** of the custom resource will be updated to reflect the drift. The contents of the policy and ruleset will not be updated to match the custom resource spec if the allow drift setting is enabled. If the custom resource is deleted, the resource in Vision One will also be deleted. 353 | 354 | ## Resource Cleanup 355 | 356 | Ensure that the custom resources are deleted before disabling the policy operator or uninstalling the Trend Micro release. The policy operator will not delete the policy resources in Vision One when the operator is disabled or uninstalled. 357 | 358 | After un-installing, if the policy resources owned by the cluster remain in Vision One, they will be deleted when the Cluster object that owns those resources are deleted. 359 | 360 | ## Custom Resource Finalizers 361 | 362 | The policy operator will add a finalizer to the custom resources to ensure that the policy and ruleset are not deleted until the operator has removed the policy from Vision One. The finalizer will be removed once the policy has been deleted from Vision One. 363 | 364 | If the policy operator is terminated before the finalizer is removed, the finalizer can be removed manually to allow the custom resource to be deleted. 365 | 366 | To remove the finalizer, edit the custom resource and remove the finalizer from the metadata section: 367 | 368 | ```yaml 369 | metadata: 370 | finalizers: 371 | - clusterpolicy.visionone.trendmicro.com/finalizer 372 | - runtimeruleset.visionone.trendmicro.com/finalizer 373 | ``` 374 | 375 | The custom resource can also be patched to remove the finalizer: 376 | 377 | ```shell 378 | kubectl patch clusterpolicy -p '{"metadata":{"finalizers":null}}' --type=merge 379 | ``` 380 | -------------------------------------------------------------------------------- /sample/clusterpolicy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: visionone.trendmicro.com/v1alpha1 2 | kind: ClusterPolicy 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: init 6 | app.kubernetes.io/managed-by: kustomize 7 | name: trendmicro-cluster-policy 8 | spec: 9 | xdrEnabled: true 10 | rules: 11 | # Pod properties 12 | - type: hostNetwork 13 | action: log 14 | mitigation: log 15 | - type: hostIPC 16 | action: log 17 | mitigation: log 18 | - type: hostPID 19 | action: log 20 | mitigation: log 21 | 22 | # Container properties 23 | - type: runAsNonRoot 24 | action: log 25 | namespaces: 26 | - default 27 | - some-namespace 28 | - type: privileged 29 | action: log 30 | - type: privileged 31 | action: block 32 | namespaces: 33 | - secure-namespace 34 | - type: allowPrivilegeEscalation 35 | action: log 36 | - type: readOnlyRootFilesystem 37 | action: log 38 | - type: containerCapabilities 39 | properties: 40 | capabilityRestriction: baseline 41 | action: log 42 | 43 | # Image properties 44 | - type: imageRegistry 45 | properties: 46 | operator: equals 47 | values: 48 | - docker.io/some-registry 49 | action: log 50 | mitigation: log 51 | - type: imageName 52 | properties: 53 | operator: startsWith 54 | values: 55 | - nginx 56 | - alpine 57 | action: log 58 | mitigation: log 59 | - type: imageTag 60 | properties: 61 | operator: notEquals 62 | values: 63 | - latest 64 | action: log 65 | mitigation: log 66 | - type: imagePath 67 | properties: 68 | operator: contains 69 | values: 70 | - example.com/org/repo 71 | - example.com/image 72 | action: log 73 | mitigation: log 74 | 75 | # Unscanned images 76 | - type: imagesNotScanned 77 | properties: 78 | scanType: vulnerability 79 | maxScanAge: 30 80 | action: block 81 | mitigation: terminate 82 | - type: imagesNotScanned 83 | properties: 84 | scanType: malware 85 | maxScanAge: 30 86 | action: block 87 | mitigation: terminate 88 | - type: imagesNotScanned 89 | properties: 90 | scanType: secret 91 | maxScanAge: 10 92 | action: block 93 | mitigation: terminate 94 | 95 | # Artifact Scanner Scan results 96 | - type: imagesWithMalware 97 | action: log 98 | - type: imagesWithSecrets 99 | action: log 100 | - type: imagesWithVulnerabilities 101 | properties: 102 | severity: critical 103 | action: log 104 | - type: imagesWithCVSSAttackVector 105 | properties: 106 | attackVector: network 107 | severity: high 108 | action: log 109 | - type: imagesWithCVSSAttackComplexity 110 | properties: 111 | attackComplexity: high 112 | severity: high 113 | action: log 114 | - type: imagesWithCVSSAvailabilityImpact 115 | properties: 116 | availabilityImpact: low 117 | severity: high 118 | action: log 119 | 120 | # Kubectl Access 121 | - type: podExec 122 | action: block 123 | mitigation: isolate 124 | - type: podPortForward 125 | action: block 126 | mitigation: isolate 127 | 128 | # Exceptions 129 | exceptions: 130 | - type: imageName 131 | properties: 132 | operator: equals 133 | values: 134 | - admission-controller 135 | - workload-operator 136 | namespaces: 137 | - trendmicro-system 138 | - type: imageRegistry 139 | properties: 140 | operator: equals 141 | values: 142 | - docker.io/some-registry -------------------------------------------------------------------------------- /sample/runtimeruleset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: visionone.trendmicro.com/v1alpha1 2 | kind: RuntimeRuleset 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: init 6 | app.kubernetes.io/managed-by: kustomize 7 | name: trendmicro-ruleset-sample 8 | spec: 9 | definition: 10 | labels: 11 | - key: "app" 12 | value: "nginx" 13 | rules: 14 | - ruleID: TM-00000001 15 | mitigation: log 16 | - ruleID: TM-00000002 17 | mitigation: log 18 | - ruleID: TM-00000003 19 | mitigation: isolate 20 | - ruleID: TM-00000004 21 | mitigation: terminate 22 | -------------------------------------------------------------------------------- /scripts/argocd-cleanup.md: -------------------------------------------------------------------------------- 1 | # Argo CD Cleanup Script for Trend Micro Container Security 2 | 3 | ## Overview 4 | 5 | Argo CD cleanup script helps clean up Trend Micro Container Security resources in your Kubernetes cluster. 6 | ``` 7 | ./argocd-cleanup.sh 8 | ``` 9 | 10 | Run this script in these scenarios: 11 | 1. **Stuck Argo CD Applications**: When you've attempted to uninstall Trend Micro Container Security through Argo CD but the application is stuck in a "Deleting" state 12 | 2. **General Cleanup**: Even if the application is not in a deleting state (i.e., after successful uninstallation), you want to ensure complete cleanup of all related resources 13 | 14 | ## Resources Cleaned Up 15 | 16 | The script handles deletion of Trend Micro Container Security resources including: 17 | 18 | - Argo CD application finalizers that may be preventing complete deletion 19 | - Trend Micro image pull secrets distributed across all namespaces 20 | - Trend Micro custom resource definitions (CRDs), specifically "workloadimages.cloudone.trendmicro.com" 21 | - Service accounts, cluster role bindings, and cluster roles of Trend Micro post-delete hooks 22 | - Cleanup Jobs in the Trend Micro system namespace 23 | 24 | 25 | ## Prerequisites 26 | 27 | - kubectl command-line tool installed and configured to connect to your cluster 28 | - Appropriate permissions to delete cluster-wide resources 29 | 30 | ## Script Usage 31 | 32 | 1. Review and modify the variables at the top of the script if needed (default values mentioned below) 33 | ```bash 34 | RELEASE_SERVICE=${RELEASE_SERVICE:-"Helm"} 35 | CONTAINER_SECURITY_NAME=${CONTAINER_SECURITY_NAME:-"container-security"} 36 | SOURCE_NAMESPACE=${SOURCE_NAMESPACE:-"trendmicro-system"} 37 | ARGOCD_NAMESPACE="argocd" 38 | ``` 39 | 2. Make the script executable: `chmod +x argocd-cleanup.sh` 40 | 3. Run the script: `./argocd-cleanup.sh` 41 | 4. Follow the prompts to confirm cleanup actions 42 | 43 | -------------------------------------------------------------------------------- /scripts/argocd-cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Default values for script execution 4 | # These variables can be changed based on customer environment settings 5 | RELEASE_SERVICE=${RELEASE_SERVICE:-"Helm"} 6 | CONTAINER_SECURITY_NAME=${CONTAINER_SECURITY_NAME:-"trendmicro-container-security"} 7 | SOURCE_NAMESPACE=${SOURCE_NAMESPACE:-"trendmicro-system"} 8 | ARGOCD_NAMESPACE="argocd" 9 | 10 | if ! command -v kubectl &> /dev/null; then 11 | echo "No kubectl command found, exiting..." 12 | exit 1 13 | fi 14 | 15 | check_namespace_exists() { 16 | local namespace="$1" 17 | 18 | if kubectl get namespace "$namespace" &>/dev/null; then 19 | return 0 20 | else 21 | return 1 22 | fi 23 | } 24 | 25 | has_post_delete_finalizers() { 26 | local app_name="$1" 27 | 28 | local finalizers=$(kubectl get application "${app_name}" -n $ARGOCD_NAMESPACE -o jsonpath='{.metadata.finalizers}' 2>/dev/null) 29 | 30 | if [[ "$finalizers" == *"post-delete-finalizer"* ]]; then 31 | return 0 32 | else 33 | return 1 34 | fi 35 | } 36 | 37 | cleanup_image_pull_secrets() { 38 | local success=true 39 | 40 | local label_selector="app.kubernetes.io/managed-by=$RELEASE_SERVICE,app.kubernetes.io/name=$CONTAINER_SECURITY_NAME" 41 | 42 | local namespaces 43 | namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}') 44 | 45 | for namespace in $namespaces; do 46 | if [ "$namespace" = $SOURCE_NAMESPACE ]; then 47 | continue 48 | fi 49 | 50 | local secrets 51 | secrets=$(kubectl get secrets -n "$namespace" -l "$label_selector" -o jsonpath='{.items[*].metadata.name}' 2>/dev/null) 52 | 53 | if [ -n "$secrets" ]; then 54 | for secret in $secrets; do 55 | kubectl delete secret -n "$namespace" "$secret" 56 | 57 | if [ $? -ne 0 ]; then 58 | echo "[Secret] Failed to delete: $secret in namespace: $namespace" 59 | success=false 60 | else 61 | echo "[Secret] Successfully deleted: $secret in namespace: $namespace" 62 | fi 63 | done 64 | else 65 | echo "[Secret] No secrets found in namespace $namespace, nothing to delete" 66 | fi 67 | done 68 | 69 | if [ "$success" = true ]; then 70 | return 0 71 | else 72 | return 1 73 | fi 74 | } 75 | 76 | cleanup_post_delete_resources() { 77 | local success=true 78 | local label_selector="app.kubernetes.io/part-of=trendmicro-container-security" 79 | 80 | if ! check_namespace_exists "$SOURCE_NAMESPACE"; then 81 | echo "Source namespace $SOURCE_NAMESPACE does not exist, nothing to delete" 82 | return 0 83 | fi 84 | 85 | local sa_list=$(kubectl get serviceaccounts -n "$SOURCE_NAMESPACE" -l "$label_selector" -o jsonpath="{.items[*].metadata.name}" 2>/dev/null) 86 | 87 | if [ -n "$sa_list" ]; then 88 | for sa in $sa_list; do 89 | kubectl delete serviceaccount -n "$SOURCE_NAMESPACE" "$sa" 90 | if [ $? -ne 0 ]; then 91 | echo "[ServiceAccount] Failed to delete Service Account: $sa" 92 | success=false 93 | else 94 | echo "[ServiceAccount] Successfully deleted: $sa" 95 | fi 96 | done 97 | else 98 | echo "[ServiceAccount] No service accounts found in namespace $SOURCE_NAMESPACE, nothing to delete" 99 | fi 100 | 101 | local crb_list=$(kubectl get clusterrolebinding -l "$label_selector" -o jsonpath="{.items[*].metadata.name}" 2>/dev/null) 102 | 103 | if [ -n "$crb_list" ]; then 104 | for crb in $crb_list; do 105 | kubectl delete clusterrolebinding "$crb" 106 | if [ $? -ne 0 ]; then 107 | echo "[ClusterRoleBinding] Failed to delete: $crb" 108 | success=false 109 | else 110 | echo "[ClusterRoleBinding] Successfully deleted: $crb" 111 | fi 112 | done 113 | else 114 | echo "[ClusterRoleBinding] No cluster role bindings found, nothing to delete" 115 | fi 116 | 117 | local cr_list=$(kubectl get clusterrole -l "$label_selector" -o jsonpath="{.items[*].metadata.name}" 2>/dev/null) 118 | 119 | if [ -n "$cr_list" ]; then 120 | for cr in $cr_list; do 121 | kubectl delete clusterrole "$cr" 122 | if [ $? -ne 0 ]; then 123 | echo "[ClusterRole] Failed to delete: $cr" 124 | success=false 125 | else 126 | echo "[ClusterRole] Successfully deleted: $cr" 127 | fi 128 | done 129 | else 130 | echo "[ClusterRole] No cluster roles found, nothing to delete" 131 | fi 132 | 133 | if [ "$success" = true ]; then 134 | return 0 135 | else 136 | return 1 137 | fi 138 | } 139 | 140 | delete_crd() { 141 | local CRD_NAME="workloadimages.cloudone.trendmicro.com" 142 | 143 | if kubectl get crd "$CRD_NAME" &>/dev/null; then 144 | kubectl delete crd "$CRD_NAME" 145 | if [ $? -eq 0 ]; then 146 | echo "[CRD] Successfully deleted $CRD_NAME" 147 | else 148 | echo "[CRD] Failed to delete $CRD_NAME" 149 | return 1 150 | fi 151 | else 152 | echo "[CRD] $CRD_NAME not found, nothing to delete" 153 | fi 154 | 155 | return 0 156 | } 157 | 158 | cleanup_jobs() { 159 | local success=true 160 | 161 | if ! check_namespace_exists "$SOURCE_NAMESPACE"; then 162 | echo "Source namespace $SOURCE_NAMESPACE does not exist, skipping cleanup" 163 | return 0 164 | fi 165 | 166 | local jobs=$(kubectl get jobs -n "$SOURCE_NAMESPACE" -o jsonpath='{.items[*].metadata.name}' 2>/dev/null) 167 | 168 | if [ -n "$jobs" ]; then 169 | for job in $jobs; do 170 | kubectl delete job -n "$SOURCE_NAMESPACE" "$job" 171 | 172 | if [ $? -ne 0 ]; then 173 | echo "[Job] Failed to delete job: $job" 174 | success=false 175 | else 176 | echo "[Job] Successfully deleted job: $job" 177 | fi 178 | done 179 | else 180 | echo "[Job] No jobs found in namespace $SOURCE_NAMESPACE, nothing to delete" 181 | fi 182 | 183 | if [ "$success" = true ]; then 184 | return 0 185 | else 186 | return 1 187 | fi 188 | } 189 | 190 | # start 191 | if check_namespace_exists "$ARGOCD_NAMESPACE"; then 192 | echo "ArgoCD namespace found. Checking if applications are stuck in deleting state..." 193 | 194 | app_names=($(kubectl get applications -n $ARGOCD_NAMESPACE -o jsonpath='{.items[*].metadata.name}')) 195 | 196 | if [ ${#app_names[@]} -eq 0 ]; then 197 | echo "No ArgoCD applications found." 198 | else 199 | for app_name in "${app_names[@]}"; do 200 | if has_post_delete_finalizers "$app_name"; then 201 | 202 | finalizers=$(kubectl get application "$app_name" -n $ARGOCD_NAMESPACE -o jsonpath='{.metadata.finalizers}') 203 | 204 | deletion_timestamp=$(kubectl get application "$app_name" -n $ARGOCD_NAMESPACE -o jsonpath='{.metadata.deletionTimestamp}' 2>/dev/null) 205 | 206 | if [ -n "$deletion_timestamp" ]; then 207 | echo -e "\nThe application is stuck in deletion state (has deletionTimestamp)." 208 | echo "Do you want to remove post-delete finalizers for application '$app_name' to allow successful deletion? (y/n)" 209 | read proceed 210 | 211 | if [[ "$proceed" =~ ^[Yy]$ ]]; then 212 | kubectl patch application "$app_name" -n $ARGOCD_NAMESPACE -p '{"metadata":{"finalizers":null}}' --type=merge 213 | 214 | if [ $? -eq 0 ]; then 215 | echo "Successfully removed finalizers from $app_name" 216 | else 217 | echo "Failed to remove finalizers from $app_name" 218 | fi 219 | fi 220 | fi 221 | fi 222 | done 223 | 224 | fi 225 | else 226 | echo "ArgoCD namespace not found. Cannot proceed with ArgoCD application cleanup." 227 | fi 228 | 229 | echo -e "\nStarting Trend Micro Container Security cleanup process...\n" 230 | 231 | echo "This script will attempt to delete the following Trend Micro leftover resources (if they exist):" 232 | echo " - Image pull secrets" 233 | echo " - Custom Resource Definitions (CRDs)" 234 | echo " - Service accounts, Cluster role bindings, and Cluster roles" 235 | echo " - Jobs in the $SOURCE_NAMESPACE namespace" 236 | echo -e "\nProceed with cleanup? (y/n)" 237 | read -r cleanup_confirm 238 | 239 | if [[ ! "$cleanup_confirm" =~ ^[Yy]$ ]]; then 240 | echo -e "\nCleanup cancelled by user." 241 | exit 0 242 | fi 243 | 244 | echo -e "\nProceeding with cleanup...\n" 245 | 246 | echo "Cleaning up image pull secrets..." 247 | cleanup_image_pull_secrets 248 | secret_cleanup_status=$? 249 | 250 | echo -e "\nDeleting custom resource definitions..." 251 | delete_crd 252 | crd_cleanup_status=$? 253 | 254 | echo -e "\nCleaning up service accounts, cluster role bindings, clusterroles...." 255 | cleanup_post_delete_resources 256 | post_delete_cleanup_status=$? 257 | 258 | echo -e "\nCleaning up jobs..." 259 | cleanup_jobs 260 | cleanup_jobs_status=$? 261 | 262 | if [ $secret_cleanup_status -eq 0 ] && [ $crd_cleanup_status -eq 0 ] && [ $post_delete_cleanup_status -eq 0 ] && [ $cleanup_jobs_status -eq 0 ]; then 263 | echo -e "\nArgoCD Cleanup completed successfully!" 264 | else 265 | echo -e "\nArgoCD Cleanup completed with some errors. Please check the logs above." 266 | exit 1 267 | fi 268 | 269 | exit 0 -------------------------------------------------------------------------------- /scripts/collect-logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # a helper script to fetch Kubernetes settings and Trend Micro Cloud One container security logs. 4 | # 5 | 6 | RELEASE=${RELEASE:-trendmicro} 7 | KUBECTL=kubectl 8 | HELM=helm 9 | 10 | ##### 11 | # check prerequisites 12 | ##### 13 | command_exists () { 14 | command -v "$1" >/dev/null 2>&1 15 | } 16 | 17 | if ! command_exists $KUBECTL; then 18 | echo "No kubectl command found, exiting..." 19 | exit 1 20 | fi 21 | 22 | if ! command_exists $HELM; then 23 | echo "No helm command found, exiting..." 24 | exit 1 25 | fi 26 | 27 | CURRENT_NS=$(kubectl config view --minify --output 'jsonpath={..namespace}') 28 | CURRENT_NS=${CURRENT_NS:-trendmicro-system} 29 | NAMESPACE=${NAMESPACE:-$CURRENT_NS} 30 | NAMESPACE_PARAM="--namespace=$NAMESPACE" 31 | 32 | PODS=$($KUBECTL get pods "$NAMESPACE_PARAM" -o=jsonpath='{range .items[*]}{.metadata.name}{";"}{end}' -l app.kubernetes.io/instance=$RELEASE) 33 | if [ -z "${PODS}" ]; then 34 | echo "No container security pods are found in release '$RELEASE' in namespace '$NAMESPACE'. You can use RELEASE and NAMESPACE environment variable to change its default settings." 35 | exit 1 36 | fi 37 | 38 | # Get Helm version since 'helm list' on Helm 3 does not display all namespaces unless specified. However, this flag does not exist in Helm 2 39 | case X`helm version --template="{{.Version}}"` in 40 | Xv3.*) 41 | HELM_COMMAND="$HELM list --all-namespaces";; 42 | *) 43 | echo "Trend Micro Cloud One Container Security only supports Helm 3 or newer version, exiting..." 44 | exit 1 45 | esac 46 | 47 | 48 | # prepare the output folder 49 | TIME=$(date +%s) 50 | RESULTS_DIR="${RESULTS_DIR:-/tmp/container-security-${TIME}}" 51 | MASTER_DIR="${RESULTS_DIR}/master" 52 | mkdir -p "$MASTER_DIR/apps" 53 | echo "Results folder will be: $RESULTS_DIR" 54 | 55 | ##### 56 | # setting logs 57 | ##### 58 | COMMANDS=( "version:$KUBECTL version" 59 | "components:$KUBECTL get componentstatuses" 60 | "events:$KUBECTL get events --all-namespaces" 61 | "storageclass:$KUBECTL describe storageclass" 62 | "helm:$HELM_COMMAND" 63 | "helm-status:$HELM status $RELEASE $NAMESPACE_PARAM" 64 | "nodes:$KUBECTL describe nodes" 65 | "podlist:$KUBECTL get pods --all-namespaces" 66 | "daemonsets: $KUBECTL get ds --all-namespaces" 67 | "container-security-get:$KUBECTL get all --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 68 | "container-security-desc:$KUBECTL describe all --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 69 | "container-security-desc-netpol:$KUBECTL describe networkpolicy --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 70 | "container-security-secrets:$KUBECTL get secrets --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 71 | "container-security-config:$KUBECTL describe configmap --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 72 | "container-security-getvalidatewebhooks:$KUBECTL get ValidatingWebhookConfiguration --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 73 | "container-security-descvalidatewebhooks:$KUBECTL describe ValidatingWebhookConfiguration --all-namespaces -l app.kubernetes.io/instance=$RELEASE" 74 | "workloadimages: $KUBECTL get workloadimages --all-namespaces -o yaml" 75 | "clusterpolicies: $KUBECTL get clusterpolicies --all-namespaces -o yaml" 76 | "runtimerulesets: $KUBECTL get runtimerulesets --all-namespaces -o yaml" 77 | "cluster: $KUBECTL get clusters.visionone.trendmicro.com --all-namespaces -o yaml") 78 | 79 | echo "Fetching setting logs..." 80 | for command in "${COMMANDS[@]}"; do 81 | KEY="${command%%:*}" 82 | VALUE="${command##*:}" 83 | echo "Command:" "$VALUE" > "$MASTER_DIR/$KEY.log" 84 | echo "====================================" >> "$MASTER_DIR/$KEY.log" 85 | $VALUE >> "$MASTER_DIR/$KEY.log" 2>&1 86 | done 87 | 88 | # get values file for current RELEASE and NAMESPACE 89 | VALUES=$($HELM get values $RELEASE -n $NAMESPACE -o yaml) 90 | VALUES=$(echo "$VALUES" | sed 's/apikey: .*/apiKey: xxxxxx/I') # redacting any exposed API keys 91 | VALUES=$(echo "$VALUES" | sed 's/password: .*/password: xxxxxx/I') # redacting any plain-text proxy password 92 | echo "$VALUES" > $MASTER_DIR/$RELEASE-$NAMESPACE-values.yaml 93 | 94 | ##### 95 | # application logs 96 | ##### 97 | for pod in $(echo "$PODS" | tr ";" "\n"); do 98 | CONTAINERS=$($KUBECTL get pods "$NAMESPACE_PARAM" "$pod" -o jsonpath='{.spec.initContainers[*].name}') 99 | for container in $CONTAINERS; do 100 | echo "Fetching container security logs... $pod - $container" 101 | $KUBECTL logs "$NAMESPACE_PARAM" "$pod" -c "$container" > "$MASTER_DIR/apps/$pod-$container.log" 102 | # check for any previous containers, this would indicate a crash 103 | PREV_LOGFILE="$MASTER_DIR/apps/$pod-$container-previous.log" 104 | if ! $KUBECTL logs "$NAMESPACE_PARAM" "$pod" -c "$container" -p > "$PREV_LOGFILE" 2>/dev/null; then 105 | rm -f "$PREV_LOGFILE" 106 | fi 107 | done 108 | 109 | # list containers in pod 110 | CONTAINERS=$($KUBECTL get pods "$NAMESPACE_PARAM" "$pod" -o jsonpath='{.spec.containers[*].name}') 111 | for container in $CONTAINERS; do 112 | echo "Fetching container security logs... $pod - $container" 113 | $KUBECTL logs "$NAMESPACE_PARAM" "$pod" -c "$container" > "$MASTER_DIR/apps/$pod-$container.log" 114 | # check for any previous containers, this would indicate a crash 115 | PREV_LOGFILE="$MASTER_DIR/apps/$pod-$container-previous.log" 116 | if ! $KUBECTL logs "$NAMESPACE_PARAM" "$pod" -c "$container" -p > "$PREV_LOGFILE" 2>/dev/null; then 117 | rm -f "$PREV_LOGFILE" 118 | fi 119 | done 120 | done 121 | 122 | echo "Results folder: $RESULTS_DIR" 123 | -------------------------------------------------------------------------------- /scripts/openshift-cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Define the ServiceAccount name 4 | SA_NAME="scanner-trendmicro-container-security" 5 | # Define the cluster binding name 6 | CLUSTER_ROLE_BINDING_NAME="scan-job-rolebinding" 7 | # Define the user or context for deletion 8 | DELETE_USER="backplane-cluster-admin" 9 | 10 | # List all namespaces 11 | namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}') 12 | 13 | # Delete cluster role binding if it exists 14 | cluster_role_binding_exists=$(kubectl get clusterrolebinding "$CLUSTER_ROLE_BINDING_NAME" --ignore-not-found -o jsonpath='{.metadata.name}') 15 | if [ "$cluster_role_binding_exists" == "$CLUSTER_ROLE_BINDING_NAME" ]; then 16 | echo "Deleting ClusterRoleBinding $CLUSTER_ROLE_BINDING_NAME" 17 | # Delete the ClusterRoleBinding 18 | oc delete clusterrolebinding "$CLUSTER_ROLE_BINDING_NAME" --as "$DELETE_USER" 19 | fi 20 | 21 | # Iterate through each namespace and check for the ServiceAccount 22 | for ns in $namespaces; do 23 | sa_exists=$(kubectl get serviceaccount -n "$ns" "$SA_NAME" --ignore-not-found -o jsonpath='{.metadata.name}') 24 | if [ "$sa_exists" == "$SA_NAME" ]; then 25 | echo "Deleting ServiceAccount $SA_NAME in namespace $ns" 26 | # Delete the ServiceAccount 27 | oc delete sa "$SA_NAME" --as "$DELETE_USER" -n "$ns" 28 | fi 29 | done 30 | -------------------------------------------------------------------------------- /templates/admission-controller-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (eq true .Values.cloudOne.admissionController.enabled) (eq true .Values.cloudOne.vulnerabilityScanning.enabled) }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: admission-controller-role 6 | labels: 7 | {{- include "admissionController.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: 10 | - cloudone.trendmicro.com 11 | resources: 12 | - workloadimages 13 | verbs: 14 | - get 15 | --- 16 | apiVersion: rbac.authorization.k8s.io/v1 17 | kind: ClusterRoleBinding 18 | metadata: 19 | name: admission-controller-rolebinding 20 | labels: 21 | {{- include "admissionController.labels" . | nindent 4 }} 22 | roleRef: 23 | apiGroup: rbac.authorization.k8s.io 24 | kind: ClusterRole 25 | name: admission-controller-role 26 | subjects: 27 | - kind: ServiceAccount 28 | name: {{ include "admissionController.serviceAccountName" . }} 29 | namespace: {{ .Release.Namespace }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /templates/admission-controller.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq true .Values.cloudOne.admissionController.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: trendmicro-admission-controller 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "admissionController.labels" . | nindent 4 }} 9 | spec: 10 | ports: 11 | - port: 443 12 | targetPort: 8443 13 | protocol: TCP 14 | selector: 15 | {{- include "admissionController.selectorLabels" . | nindent 4 }} 16 | 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: trendmicro-admission-controller 22 | namespace: {{ .Release.Namespace }} 23 | labels: 24 | {{- include "admissionController.labels" . | nindent 4 }} 25 | spec: 26 | # We set revisionHistoryLimit to 0 because rollback should be done 27 | # using `helm rollback` rather than with `kubectl rollout undo`, so 28 | # we don't need to keep the old `ReplicaSet`s around. 29 | # https://kubernetes.io/docs/concepts/workloads/controllers/deployment 30 | revisionHistoryLimit: 0 31 | replicas: {{ default 1 .Values.replicas.admissionController }} 32 | selector: 33 | matchLabels: 34 | {{- include "admissionController.selectorLabels" . | nindent 6 }} 35 | template: 36 | metadata: 37 | annotations: 38 | checksum/auth: {{ include "container.security.auth.secret" . | sha256sum }} 39 | # Force the pods to restart when validatingwebhook.yaml is updated. This is to ensure certificate is in sync. 40 | checksum/cert: {{ include (print $.Template.BasePath "/validatingwebhook.yaml") . | sha256sum }} 41 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.admissionController) }} 42 | {{- toYaml . | nindent 8 }} 43 | {{- end }} 44 | labels: 45 | {{- include "admissionController.labels" . | nindent 8 }} 46 | spec: 47 | serviceAccountName: {{ include "admissionController.serviceAccountName" . }} 48 | automountServiceAccountToken: true 49 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 50 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.admissionController }} 51 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 52 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container }} 53 | {{- if $securityContextEnabled }} 54 | securityContext: 55 | {{ toYaml $podSecurityContext | indent 8 }} 56 | {{- end }} 57 | {{- $imageDefaults := .Values.images.defaults }} 58 | {{- with .Values.images.admissionController }} 59 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 60 | {{- if not (eq "" $secret) }} 61 | imagePullSecrets: 62 | - name: {{ $secret | quote }} 63 | {{- end }} 64 | containers: 65 | - name: trendmicro-admission-controller 66 | {{- if $securityContextEnabled }} 67 | securityContext: 68 | {{ toYaml $containerSecurityContext | indent 12 }} 69 | {{- end }} 70 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 71 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 72 | {{- $tag := (default $imageDefaults.tag .tag) }} 73 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 74 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 75 | {{- end }} 76 | ports: 77 | - containerPort: 8443 78 | - containerPort: 8083 79 | name: health 80 | livenessProbe: 81 | httpGet: 82 | path: /health 83 | port: 8083 84 | initialDelaySeconds: 20 85 | timeoutSeconds: 5 86 | periodSeconds: 20 87 | failureThreshold: 6 88 | readinessProbe: 89 | httpGet: 90 | path: /health 91 | port: 8083 92 | initialDelaySeconds: 20 93 | timeoutSeconds: 5 94 | periodSeconds: 20 95 | failureThreshold: 6 96 | volumeMounts: 97 | - name: webhook-certs 98 | mountPath: /etc/webhook/certs 99 | readOnly: true 100 | - name: api-key 101 | mountPath: /secrets 102 | readOnly: true 103 | {{- if .Values.telemetry.publicKey }} 104 | - name: telemetry-secret 105 | mountPath: /telemetry 106 | {{- end }}{{/* .Values.telemetry.publicKey */}} 107 | - name: policy-config 108 | mountPath: /etc/config 109 | {{- include "proxy.selfSignedCertificates.volumeMounts" . | nindent 12 }} 110 | args: 111 | - --zap-devel={{ default "false" .Values.logConfig.devel }} 112 | - --zap-log-level={{ include "logLevel" (list .Values.cloudOne.admissionController.logLevel .) }} 113 | - --zap-encoder={{ default "json" .Values.logConfig.encoder }} 114 | - --zap-stacktrace-level={{ default "error" .Values.logConfig.stacktraceLevel }} 115 | - --zap-time-encoding={{ default "rfc3339" .Values.logConfig.timeEncoding }} 116 | - --tlsCertFile=/etc/webhook/certs/cert.pem 117 | - --tlsKeyFile=/etc/webhook/certs/key.pem 118 | - --tls-min-version={{ include "tlsConfig.minTLSVersion" .Values.tlsConfig }} 119 | - --tls-cipher-suites={{ include "tlsConfig.cipherSuites" .Values.tlsConfig }} 120 | - --cloud-one-endpoint={{ include "container.security.endpoint" . }} 121 | - --exclude-kubernetes-service-host-from-proxy={{ default "false" .Values.proxy.excludeKubernetesServiceHost }} 122 | - --excluded-namespaces 123 | {{- $excludeNS := include "namespaceExclusions" . }} 124 | - {{ $excludeNS | quote }} 125 | - --trusted-scan-operators 126 | {{- $trustedOperators := (default (list) .Values.cloudOne.admissionController.trustedScanOperators) }} 127 | - {{ $trustedOperators | join "," | quote }} 128 | - --application-version=$(APPLICATION_VERSION) 129 | {{- if .Values.telemetry.enabled }} 130 | - --telemetry-endpoint={{ .Values.telemetry.endpoint }} 131 | - --telemetry-interval={{ .Values.telemetry.interval }} 132 | - --telemetry-api-key={{ default "" .Values.telemetry.apiKey }} 133 | {{- if .Values.telemetry.publicKey }} 134 | - --telemetry-key-file=/telemetry/key.pem 135 | {{- end }}{{/* .Values.telemetry.publicKey */}} 136 | {{- end }}{{/* .Values.telemetry.enabled */}} 137 | - --trusted-images={{ include "digest" . }} 138 | {{- if .Values.visionOneFeatureGate }} 139 | - --vision-one-feature-gate=true 140 | {{- end }} 141 | - 2>&1 142 | env: 143 | {{- include "container.security.proxy.env" . | nindent 12 }} 144 | - name: SCAN_MANAGER_SERVICE_ACCOUNT 145 | value: {{ include "scanManager.serviceAccountName" . }} 146 | - name: APPLICATION_VERSION 147 | value: {{ .Chart.AppVersion | quote }} 148 | - name: NAMESPACE 149 | valueFrom: 150 | fieldRef: 151 | fieldPath: metadata.namespace 152 | resources: 153 | {{ toYaml (default .Values.resources.defaults .Values.resources.admissionController) | indent 12 }} 154 | volumes: 155 | - name: api-key 156 | secret: 157 | secretName: {{ template "container.security.fullname" . }}-auth 158 | - name: varrun 159 | emptyDir: 160 | sizeLimit: 1Mi 161 | - name: webhook-certs 162 | secret: 163 | secretName: {{ template "admissionController.fullname" . }}-tls-certificate 164 | {{- if .Values.telemetry.publicKey }} 165 | - name: telemetry-secret 166 | secret: 167 | secretName: {{ template "container.security.fullname" . }}-telemetry 168 | items: 169 | - key: publicKey 170 | path: key.pem 171 | {{- end }}{{/* .Values.telemetry.publicKey */}} 172 | - name: policy-config # Use projected volume to mount all policy config files in a single volume (ie. policy, rulesets) 173 | projected: 174 | sources: 175 | - configMap: 176 | name: {{ template "container.security.name" . }}-policy-config 177 | {{- include "proxy.selfSignedCertificates.volumes" . | nindent 8 }} 178 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.admissionController }} 179 | nodeSelector: 180 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.admissionController) | indent 8 }} 181 | {{- end }} 182 | {{- if or .Values.tolerations.defaults .Values.tolerations.admissionController }} 183 | tolerations: 184 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.admissionController) | indent 8 }} 185 | {{- end }} 186 | {{- if or .Values.affinity.defaults .Values.affinity.admissionController }} 187 | affinity: 188 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.admissionController) | indent 8 }} 189 | {{- end }} 190 | {{- $classname := (default (default "" .Values.priorityClassName.default ) .Values.priorityClassName.admissionController) }} 191 | {{- if not (eq "" $classname) }} 192 | priorityClassName: "{{ $classname }}" 193 | {{- end }} 194 | restartPolicy: Always 195 | --- 196 | {{ if .Values.serviceAccount.create }} 197 | apiVersion: v1 198 | kind: ServiceAccount 199 | metadata: 200 | name: {{ include "admissionController.serviceAccountName" . }} 201 | labels: 202 | {{- include "admissionController.labels" . | nindent 4 }} 203 | {{- with .Values.serviceAccount.admissionController.annotations }} 204 | annotations: 205 | {{- toYaml . | nindent 4 }} 206 | {{- end }} 207 | {{- end }} 208 | {{- end }} 209 | -------------------------------------------------------------------------------- /templates/auth.yaml: -------------------------------------------------------------------------------- 1 | {{ include "container.security.auth.secret" . }} 2 | -------------------------------------------------------------------------------- /templates/cluster.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (.Values.cloudOne.clusterRegistrationKey) (eq (include "container.security.isVisionOneEndpoint" .) "true") }} 2 | apiVersion: visionone.trendmicro.com/v1alpha1 3 | kind: Cluster 4 | metadata: 5 | name: trendmicro-cluster 6 | {{- end}} -------------------------------------------------------------------------------- /templates/compliance-scan-job-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (eq true .Values.cloudOne.complianceScan.enabled) }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "complianceScanJob.serviceAccountName" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "complianceScanJob.labels" . | nindent 4 }} 9 | 10 | --- 11 | 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | kind: ClusterRole 14 | metadata: 15 | name: compliance-scan-job-role 16 | labels: 17 | {{- include "complianceScanJob.labels" $ | nindent 4 }} 18 | rules: 19 | - apiGroups: 20 | - rbac.authorization.k8s.io 21 | resources: 22 | - clusterroles 23 | - clusterrolebindings 24 | - roles 25 | - rolebindings 26 | verbs: 27 | - list 28 | - get 29 | - apiGroups: 30 | - "" 31 | resources: 32 | - nodes 33 | - nodes/proxy 34 | - pods 35 | - pods/log 36 | - services 37 | - replicationcontrollers 38 | - configmaps 39 | - serviceaccounts 40 | - namespaces 41 | - limitranges 42 | - resourcequotas 43 | - services 44 | verbs: 45 | - list 46 | - get 47 | - watch 48 | - apiGroups: 49 | - networking.k8s.io 50 | resources: 51 | - ingresses 52 | verbs: 53 | - list 54 | - get 55 | - apiGroups: 56 | - "" 57 | resources: 58 | - namespaces 59 | verbs: 60 | - create 61 | - apiGroups: 62 | - "" 63 | resources: 64 | - pods/exec 65 | - pods 66 | verbs: 67 | - create 68 | - delete 69 | - apiGroups: 70 | - "apps" 71 | resources: 72 | - daemonsets 73 | - deployments 74 | - replicasets 75 | - statefulsets 76 | verbs: 77 | - list 78 | - get 79 | - apiGroups: 80 | - "autoscaling" 81 | resources: 82 | - horizontalpodautoscalers 83 | verbs: 84 | - list 85 | - get 86 | - apiGroups: 87 | - "batch" 88 | resources: 89 | - cronjobs 90 | - jobs 91 | verbs: 92 | - list 93 | - get 94 | - apiGroups: 95 | - "networking.k8s.io" 96 | resources: 97 | - networkpolicies 98 | verbs: 99 | - list 100 | - get 101 | - verbs: 102 | - use 103 | apiGroups: 104 | - security.openshift.io 105 | resources: 106 | - securitycontextconstraints 107 | resourceNames: 108 | - privileged 109 | - {{ template "container.security.name" . }}-compliance-scanner 110 | 111 | --- 112 | 113 | apiVersion: rbac.authorization.k8s.io/v1 114 | kind: ClusterRoleBinding 115 | metadata: 116 | name: compliance-scan-job-rolebinding 117 | labels: 118 | {{- include "complianceScanJob.labels" $ | nindent 4 }} 119 | subjects: 120 | - kind: ServiceAccount 121 | name: {{ include "complianceScanJob.serviceAccountName" . }} 122 | namespace: {{ .Release.Namespace }} 123 | roleRef: 124 | kind: ClusterRole 125 | name: compliance-scan-job-role 126 | apiGroup: rbac.authorization.k8s.io 127 | {{- end }} -------------------------------------------------------------------------------- /templates/compliance-scan-job-scc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 2 | apiVersion: security.openshift.io/v1 3 | kind: SecurityContextConstraints 4 | metadata: 5 | annotations: 6 | kubernetes.io/description: | 7 | This SCC provides mosted privilege requirement to run the compliance scan job in Openshift. 8 | name: {{ template "container.security.name" . }}-compliance-scanner 9 | namespace: {{ .Release.Namespace }} 10 | labels: 11 | {{- include "container.security.labels" . | nindent 4 }} 12 | allowHostDirVolumePlugin: true 13 | allowHostIPC: true 14 | allowHostNetwork: true 15 | allowHostPID: true 16 | allowHostPorts: true 17 | allowPrivilegeEscalation: true 18 | allowPrivilegedContainer: true 19 | allowedCapabilities: 20 | {{- toYaml .Values.securityContext.scanner.target.capabilities.add | nindent 2}} 21 | allowedUnsafeSysctls: [] 22 | defaultAddCapabilities: [] 23 | fsGroup: 24 | type: RunAsAny 25 | groups: [] 26 | priority: 10 27 | readOnlyRootFilesystem: true 28 | requiredDropCapabilities: [] 29 | runAsUser: 30 | type: RunAsAny 31 | seLinuxContext: 32 | type: RunAsAny 33 | supplementalGroups: 34 | type: RunAsAny 35 | users: 36 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "complianceScanJob.serviceAccountName" . }} 37 | 38 | volumes: 39 | - '*' 40 | {{- end }} 41 | -------------------------------------------------------------------------------- /templates/fargate-injector-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.fargateInjector.enabled) }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: fargate-injector-role 7 | labels: 8 | {{- include "fargateInjector.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - secrets 14 | - configmaps 15 | verbs: 16 | - list 17 | - create 18 | - get 19 | - update 20 | - watch 21 | - apiGroups: 22 | - extensions 23 | - "" 24 | resources: 25 | - nodes 26 | - namespaces 27 | - pods 28 | - replicationcontrollers 29 | - replicasets 30 | - services 31 | - daemonsets 32 | - deployments 33 | - events 34 | - configmaps 35 | verbs: 36 | - get 37 | - list 38 | - watch 39 | - apiGroups: 40 | - apps 41 | resources: 42 | - daemonsets 43 | - deployments 44 | - replicasets 45 | - statefulsets 46 | verbs: 47 | - get 48 | - list 49 | - watch 50 | - nonResourceURLs: 51 | - /healthz 52 | - /healthz/* 53 | verbs: 54 | - get 55 | - apiGroups: 56 | - "rbac.authorization.k8s.io" 57 | resources: 58 | - clusterrolebindings 59 | verbs: 60 | - list 61 | - get 62 | - create 63 | - update 64 | --- 65 | apiVersion: rbac.authorization.k8s.io/v1 66 | kind: ClusterRoleBinding 67 | metadata: 68 | name: fargate-injector-rolebinding 69 | labels: 70 | {{- include "fargateInjector.labels" . | nindent 4 }} 71 | roleRef: 72 | apiGroup: rbac.authorization.k8s.io 73 | kind: ClusterRole 74 | name: fargate-injector-role 75 | subjects: 76 | - kind: ServiceAccount 77 | name: {{ include "fargateInjector.serviceAccountName" . }} 78 | namespace: {{ .Release.Namespace }} 79 | {{- end }} 80 | -------------------------------------------------------------------------------- /templates/fargate-injector.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.fargateInjector.enabled) }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: trendmicro-fargate-injector 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "fargateInjector.labels" . | nindent 4 }} 9 | spec: 10 | ports: 11 | - port: 443 12 | targetPort: 8443 13 | protocol: TCP 14 | selector: 15 | {{- include "fargateInjector.selectorLabels" . | nindent 4 }} 16 | 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: trendmicro-fargate-injector 22 | namespace: {{ .Release.Namespace }} 23 | labels: 24 | {{- include "fargateInjector.labels" . | nindent 4 }} 25 | spec: 26 | # We set revisionHistoryLimit to 0 because rollback should be done 27 | # using `helm rollback` rather than with `kubectl rollout undo`, so 28 | # we don't need to keep the old `ReplicaSet`s around. 29 | # https://kubernetes.io/docs/concepts/workloads/controllers/deployment 30 | revisionHistoryLimit: 0 31 | replicas: {{ default 1 .Values.replicas.fargateInjector }} 32 | selector: 33 | matchLabels: 34 | {{- include "fargateInjector.selectorLabels" . | nindent 6 }} 35 | template: 36 | metadata: 37 | annotations: 38 | checksum/auth: {{ include "container.security.auth.secret" . | sha256sum }} 39 | # Force the pods to restart when mutatingwebhook.yaml is updated. This is to ensure certificate is in sync. 40 | checksum/cert: {{ include (print $.Template.BasePath "/mutatingwebhook.yaml") . | sha256sum }} 41 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.fargateInjector) }} 42 | {{- toYaml . | nindent 8 }} 43 | {{- end }} 44 | labels: 45 | {{- include "fargateInjector.labels" . | nindent 8 }} 46 | spec: 47 | automountServiceAccountToken: true 48 | serviceAccountName: {{ include "fargateInjector.serviceAccountName" . }} 49 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 50 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.fargateInjector }} 51 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 52 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container }} 53 | {{- if $securityContextEnabled }} 54 | securityContext: 55 | {{ toYaml $podSecurityContext | indent 8 }} 56 | {{- end }} 57 | {{- $imageDefaults := .Values.images.defaults }} 58 | {{- with .Values.images.fargateInjector }} 59 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 60 | {{- if not (eq "" $secret) }} 61 | imagePullSecrets: 62 | - name: {{ $secret | quote }} 63 | {{- end }} 64 | containers: 65 | - name: trendmicro-fargate-injector 66 | {{- if $securityContextEnabled }} 67 | securityContext: 68 | {{ toYaml $containerSecurityContext | indent 12 }} 69 | {{- end }} 70 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 71 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 72 | {{- $tag := (default $imageDefaults.tag .tag) }} 73 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 74 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 75 | {{- end }} 76 | ports: 77 | - containerPort: 8443 78 | command: 79 | - /eks-admission-injector 80 | - --cert-file-path 81 | - /etc/webhook/certs/cert.pem 82 | - --key-file-path 83 | - /etc/webhook/certs/key.pem 84 | - --log-level 85 | - {{ .Values.cloudOne.fargateInjector.logLevel }} 86 | - --endpoint 87 | - {{ .Values.cloudOne.endpoint }} 88 | - --auth-secret-name 89 | - {{ template "container.security.fullname" . }}-auth 90 | - --zap-devel={{ default "false" .Values.logConfig.devel }} 91 | - --zap-log-level={{ include "logLevel" (list .Values.cloudOne.fargateInjector.logLevel .) }} 92 | - --zap-encoder={{ default "json" .Values.logConfig.encoder }} 93 | - --zap-stacktrace-level={{ default "error" .Values.logConfig.stacktraceLevel }} 94 | - --zap-time-encoding={{ default "rfc3339" .Values.logConfig.timeEncoding }} 95 | - --excluded-namespaces 96 | {{- $excludeNS := include "namespaceExclusions" . }} 97 | - {{ $excludeNS | quote }} 98 | - --scout-image-uri 99 | {{- with .Values.images.scout }} 100 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 101 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 102 | {{- $tag := (default $imageDefaults.tag .tag) }} 103 | - {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 104 | {{- end }} 105 | - --falco-image-uri 106 | {{- with .Values.images.falco }} 107 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 108 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 109 | {{- $tag := (default $imageDefaults.tag .tag) }} 110 | - {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 111 | {{- end }} 112 | - --pdig-image-uri 113 | {{- with .Values.images.pdig }} 114 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 115 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 116 | {{- $tag := (default $imageDefaults.tag .tag) }} 117 | - {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 118 | {{- end }} 119 | {{- if ne (len .Values.scout.scout.falcoInternalEvent) 0 }} 120 | - --falco-internal-event 121 | - {{ join "," .Values.scout.scout.falcoInternalEvent }} 122 | {{- end}}{{/* if */}} 123 | - --pull-image-auth 124 | {{- $imageDefaults := .Values.images.defaults }} 125 | {{- with .Values.images.fargateInjector }} 126 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 127 | - {{ $secret | quote }} 128 | {{- end }} 129 | livenessProbe: 130 | httpGet: 131 | scheme: HTTPS 132 | path: / 133 | port: 8443 134 | initialDelaySeconds: 20 135 | timeoutSeconds: 5 136 | periodSeconds: 20 137 | failureThreshold: 6 138 | readinessProbe: 139 | httpGet: 140 | scheme: HTTPS 141 | path: / 142 | port: 8443 143 | initialDelaySeconds: 20 144 | timeoutSeconds: 5 145 | periodSeconds: 20 146 | failureThreshold: 6 147 | env: 148 | - name: NAMESPACE 149 | valueFrom: 150 | fieldRef: 151 | fieldPath: metadata.namespace 152 | volumeMounts: 153 | - name: webhook-certs 154 | mountPath: /etc/webhook/certs 155 | readOnly: true 156 | resources: 157 | {{ toYaml (default .Values.resources.defaults .Values.resources.fargateInjector) | indent 12 }} 158 | volumes: 159 | - name: webhook-certs 160 | secret: 161 | secretName: {{ template "fargateInjector.fullname" . }}-tls-certificate 162 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.fargateInjector }} 163 | nodeSelector: 164 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.fargateInjector) | indent 8 }} 165 | {{- end }} 166 | {{- if or .Values.tolerations.defaults .Values.tolerations.fargateInjector }} 167 | tolerations: 168 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.fargateInjector) | indent 8 }} 169 | {{- end }} 170 | {{- if or .Values.affinity.defaults .Values.affinity.fargateInjector }} 171 | affinity: 172 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.fargateInjector) | indent 8 }} 173 | {{- end }} 174 | {{- $classname := (default (default "" .Values.priorityClassName.default ) .Values.priorityClassName.fargateInjector) }} 175 | {{- if not (eq "" $classname) }} 176 | priorityClassName: "{{ $classname }}" 177 | {{- end }} 178 | restartPolicy: Always 179 | {{- end }} 180 | {{ if .Values.serviceAccount.create }} 181 | --- 182 | apiVersion: v1 183 | kind: ServiceAccount 184 | metadata: 185 | name: {{ include "fargateInjector.serviceAccountName" . }} 186 | labels: 187 | {{- include "fargateInjector.labels" . | nindent 4 }} 188 | {{- with .Values.serviceAccount.fargateInjector.annotations }} 189 | annotations: 190 | {{- toYaml . | nindent 4 }} 191 | {{- end }} 192 | {{- end }} 193 | -------------------------------------------------------------------------------- /templates/k8s-metacollector-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.malwareScanning.enabled) }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: k8s-metacollector-role 7 | labels: 8 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - apps 12 | resources: 13 | - daemonsets 14 | - deployments 15 | - replicasets 16 | verbs: 17 | - get 18 | - list 19 | - watch 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - endpoints 24 | - namespaces 25 | - pods 26 | - replicationcontrollers 27 | - services 28 | verbs: 29 | - get 30 | - list 31 | - watch 32 | - apiGroups: 33 | - discovery.k8s.io 34 | resources: 35 | - endpointslices 36 | verbs: 37 | - get 38 | - list 39 | - watch 40 | --- 41 | apiVersion: rbac.authorization.k8s.io/v1 42 | kind: ClusterRoleBinding 43 | metadata: 44 | name: k8s-metacollector-rolebinding 45 | labels: 46 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 47 | roleRef: 48 | apiGroup: rbac.authorization.k8s.io 49 | kind: ClusterRole 50 | name: k8s-metacollector-role 51 | subjects: 52 | - kind: ServiceAccount 53 | name: {{ include "k8sMetaCollector.serviceAccountName" . }} 54 | namespace: {{ .Release.Namespace }} 55 | {{- end }} 56 | -------------------------------------------------------------------------------- /templates/k8s-metacollector-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and ( or (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.malwareScanning.enabled)) (eq "tls" .Values.cloudOne.k8sMetaCollector.grpcAuth.type) }} 2 | 3 | {{- $cn := (include "k8sMetaCollector.svc.url" .) }} 4 | {{- $ca := genCA (printf "%s-ca" (include "k8sMetaCollector.fullname" .)) (default 3650 (int .Values.cloudOne.k8sMetaCollector.grpcAuth.certificate.lifetime)) -}} 5 | {{- $cert := genSignedCert $cn nil (list $cn) (default 3650 (int .Values.cloudOne.k8sMetaCollector.grpcAuth.certificate.lifetime)) $ca -}} 6 | 7 | --- 8 | 9 | apiVersion: v1 10 | kind: Secret 11 | metadata: 12 | name: {{ template "k8sMetaCollector.fullname" . }}-tls-certificate 13 | namespace: {{ .Release.Namespace }} 14 | labels: 15 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 16 | type: Opaque 17 | data: 18 | key.pem: {{ $cert.Key | b64enc | quote }} 19 | cert.pem: {{ $cert.Cert | b64enc | quote }} 20 | ca-cert.pem: {{ $ca.Cert | b64enc | quote }} 21 | 22 | {{- end }} -------------------------------------------------------------------------------- /templates/k8s-metacollector.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.malwareScanning.enabled) }} 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: {{ include "k8sMetaCollector.fullname" . }} 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - name: "metrics" 14 | port: 8080 15 | targetPort: "metrics" 16 | protocol: "TCP" 17 | - name: "health-probe" 18 | port: 8081 19 | targetPort: "health-probe" 20 | protocol: "TCP" 21 | - name: "broker-grpc" 22 | port: 45000 23 | targetPort: "broker-grpc" 24 | protocol: "TCP" 25 | selector: 26 | {{- include "k8sMetaCollector.selectorLabels" . | nindent 4 }} 27 | --- 28 | apiVersion: apps/v1 29 | kind: Deployment 30 | metadata: 31 | name: trendmicro-metacollector 32 | namespace: {{ .Release.Namespace }} 33 | labels: 34 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 35 | spec: 36 | replicas: {{ default 1 .Values.replicas.k8sMetaCollector }} 37 | selector: 38 | matchLabels: 39 | {{- include "k8sMetaCollector.selectorLabels" . | nindent 6 }} 40 | template: 41 | metadata: 42 | annotations: 43 | {{- if eq "tls" .Values.cloudOne.k8sMetaCollector.grpcAuth.type }} 44 | checksum/config: {{ include (print $.Template.BasePath "/k8s-metacollector-secret.yaml") . | sha256sum }} 45 | {{- end }} 46 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.k8sMetaCollector) }} 47 | {{- toYaml . | nindent 8 }} 48 | {{- end }} 49 | labels: 50 | {{- include "k8sMetaCollector.labels" . | nindent 8 }} 51 | spec: 52 | serviceAccountName: {{ include "k8sMetaCollector.serviceAccountName" . }} 53 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 54 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.k8sMetaCollector }} 55 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 56 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container.k8sMetaCollector }} 57 | {{- if $securityContextEnabled }} 58 | securityContext: 59 | {{ toYaml $podSecurityContext | indent 8 }} 60 | {{- end }} 61 | {{- $imageDefaults := .Values.images.defaults }} 62 | {{- with .Values.images.k8sMetaCollector }} 63 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 64 | {{- if not (eq "" $secret) }} 65 | imagePullSecrets: 66 | - name: {{ $secret | quote }} 67 | {{- end }} 68 | containers: 69 | - name: k8s-metacollector 70 | {{- if $securityContextEnabled }} 71 | securityContext: 72 | {{ toYaml $containerSecurityContext | indent 12 }} 73 | {{- end }} 74 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 75 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 76 | {{- $tag := (default $imageDefaults.tag .tag) }} 77 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 78 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 79 | {{- end }} 80 | command: 81 | - /meta-collector 82 | args: 83 | - run 84 | {{- if eq "tls" .Values.cloudOne.k8sMetaCollector.grpcAuth.type }} 85 | - --broker-server-cert 86 | - /etc/metacollector/certs/cert.pem 87 | - --broker-server-key 88 | - /etc/metacollector/certs/key.pem 89 | {{- end }} 90 | - --zap-devel={{ default "false" .Values.logConfig.devel }} 91 | - --zap-log-level={{ include "logLevel" (list .Values.cloudOne.k8sMetaCollector.logLevel .) }} 92 | - --zap-encoder={{ default "json" .Values.logConfig.encoder }} 93 | - --zap-stacktrace-level={{ default "error" .Values.logConfig.stacktraceLevel }} 94 | - --zap-time-encoding={{ default "rfc3339" .Values.logConfig.timeEncoding }} 95 | ports: 96 | - name: "broker-grpc" 97 | containerPort: 45000 98 | livenessProbe: 99 | # -- httpGet specifies that the liveness probe will make an HTTP GET request to check the health of the container. 100 | httpGet: 101 | # -- path is the specific endpoint on which the HTTP GET request will be made. 102 | path: /healthz 103 | # -- port is the port on which the container exposes the "/healthz" endpoint. 104 | port: 8081 105 | # -- initialDelaySeconds tells the kubelet that it should wait X seconds before performing the first probe. 106 | initialDelaySeconds: 15 107 | # -- timeoutSeconds is the number of seconds after which the probe times out. 108 | timeoutSeconds: 5 109 | # -- periodSeconds specifies the interval at which the liveness probe will be repeated. 110 | periodSeconds: 15 111 | readinessProbe: 112 | # -- httpGet specifies that the readiness probe will make an HTTP GET request to check whether the container is ready. 113 | httpGet: 114 | # -- path is the specific endpoint on which the HTTP GET request will be made. 115 | path: /readyz 116 | # -- port is the port on which the container exposes the "/readyz" endpoint. 117 | port: 8081 118 | # -- initialDelaySeconds tells the kubelet that it should wait X seconds before performing the first probe. 119 | initialDelaySeconds: 15 120 | # -- timeoutSeconds is the number of seconds after which the probe times out. 121 | timeoutSeconds: 5 122 | # -- periodSeconds specifies the interval at which the readiness probe will be repeated. 123 | periodSeconds: 15 124 | volumeMounts: 125 | {{- if eq "tls" .Values.cloudOne.k8sMetaCollector.grpcAuth.type }} 126 | - name: grpc-certs 127 | mountPath: /etc/metacollector/certs 128 | readOnly: true 129 | {{- end }} 130 | {{- include "proxy.selfSignedCertificates.volumeMounts" . | nindent 12 }} 131 | resources: 132 | {{ toYaml (default .Values.resources.defaults .Values.resources.k8sMetaCollector) | indent 12 }} 133 | volumes: 134 | {{- if eq "tls" .Values.cloudOne.k8sMetaCollector.grpcAuth.type }} 135 | - name: grpc-certs 136 | secret: 137 | secretName: {{ template "k8sMetaCollector.fullname" . }}-tls-certificate 138 | {{- end }} 139 | {{- include "proxy.selfSignedCertificates.volumes" . | nindent 8 }} 140 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.k8sMetaCollector }} 141 | nodeSelector: 142 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.k8sMetaCollector) | indent 8 }} 143 | {{- end }} 144 | {{- if or .Values.tolerations.defaults .Values.tolerations.k8sMetaCollector }} 145 | tolerations: 146 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.k8sMetaCollector) | indent 8 }} 147 | {{- end }} 148 | {{- if or .Values.affinity.defaults .Values.affinity.k8sMetaCollector }} 149 | affinity: 150 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.k8sMetaCollector) | indent 8 }} 151 | {{- end }} 152 | 153 | --- 154 | {{ if .Values.serviceAccount.create }} 155 | apiVersion: v1 156 | kind: ServiceAccount 157 | metadata: 158 | name: {{ include "k8sMetaCollector.serviceAccountName" . }} 159 | labels: 160 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 161 | {{- with .Values.serviceAccount.k8sMetaCollector.annotations }} 162 | annotations: 163 | {{- toYaml . | nindent 4 }} 164 | {{- end }} 165 | {{- end }} 166 | {{- end }} 167 | 168 | --- 169 | {{- $networkpolicyEnabled := and (hasKey .Values.networkPolicy "k8sMetaCollector") (hasKey .Values.networkPolicy.k8sMetaCollector "enabled") | ternary .Values.networkPolicy.k8sMetaCollector.enabled .Values.networkPolicy.enabled }} 170 | {{ if $networkpolicyEnabled }} 171 | 172 | apiVersion: networking.k8s.io/v1 173 | kind: NetworkPolicy 174 | metadata: 175 | name: k8s-metacollector-networkpolicy 176 | namespace: {{ .Release.Namespace }} 177 | labels: 178 | {{- include "k8sMetaCollector.labels" . | nindent 4 }} 179 | spec: 180 | podSelector: 181 | matchLabels: 182 | {{- include "k8sMetaCollector.selectorLabels" . | nindent 6 }} 183 | policyTypes: 184 | - Ingress 185 | ingress: 186 | - from: # this is for grpc client 187 | - podSelector: {} 188 | ports: 189 | - protocol: TCP 190 | port: 45000 191 | - from: # any -- this is for metrics 192 | ports: 193 | - protocol: TCP 194 | port: 8080 195 | - from: # any -- this should just be kubelet for health probes 196 | ports: 197 | - protocol: TCP 198 | port: 8081 199 | {{- end }} 200 | -------------------------------------------------------------------------------- /templates/kube-rbac-proxy-cert.yaml: -------------------------------------------------------------------------------- 1 | {{- $cn := printf "%s.%s.svc" "trendmicro-kube-rbac-proxy" .Release.Namespace }} 2 | {{- $ca := genCA (printf "%s-ca" "trendmicro-kube-rbac-proxy") (default 3650 (int .Values.cloudOne.kubeRbacProxy.certificate.lifetime)) -}} 3 | {{- $cert := genSignedCert (default $cn .Values.cloudOne.kubeRbacProxy.certificate.commonName) (default nil .Values.cloudOne.kubeRbacProxy.certificate.ipAlternativeNames) (default (list $cn) .Values.cloudOne.kubeRbacProxy.certificate.dnsAlternativeNames) (default 3650 (int .Values.cloudOne.kubeRbacProxy.certificate.lifetime)) $ca -}} 4 | 5 | apiVersion: v1 6 | kind: Secret 7 | metadata: 8 | name: {{ template "kubeRbacProxy.fullname" . }}-tls-certificate 9 | namespace: {{ .Release.Namespace }} 10 | labels: 11 | {{- include "container.security.labels" . | nindent 4 }} 12 | type: Opaque 13 | data: 14 | key.pem: {{ $cert.Key | b64enc | quote }} 15 | cert.pem: {{ $cert.Cert | b64enc | quote }} 16 | -------------------------------------------------------------------------------- /templates/malware-scanner-scc.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq true .Values.cloudOne.malwareScanning.enabled }} 2 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 3 | apiVersion: security.openshift.io/v1 4 | kind: SecurityContextConstraints 5 | metadata: 6 | annotations: 7 | kubernetes.io/description: | 8 | This provides the minimum requirements in Openshift. 9 | name: {{ template "container.security.name" . }}-malware-scanner 10 | namespace: {{ .Release.Namespace }} 11 | labels: 12 | {{- include "container.security.labels" . | nindent 4 }} 13 | allowHostDirVolumePlugin: false 14 | allowHostIPC: false 15 | allowHostNetwork: true 16 | allowHostPID: false 17 | allowHostPorts: false 18 | allowPrivilegeEscalation: false 19 | allowPrivilegedContainer: false 20 | allowedCapabilities: [] 21 | allowedUnsafeSysctls: [] 22 | defaultAddCapabilities: [] 23 | fsGroup: 24 | type: RunAsAny 25 | groups: [] 26 | priority: 0 27 | readOnlyRootFilesystem: false 28 | requiredDropCapabilities: [] 29 | runAsUser: 30 | type: RunAsAny 31 | seLinuxContext: 32 | type: RunAsAny 33 | seccompProfiles: 34 | - '*' 35 | supplementalGroups: 36 | type: RunAsAny 37 | users: 38 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "malwareScanner.serviceAccountName" . }} 39 | volumes: 40 | - emptyDir 41 | - secret 42 | - configMap 43 | {{- end }} 44 | {{- end }} -------------------------------------------------------------------------------- /templates/malware-scanner.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq true .Values.cloudOne.malwareScanning.enabled }} 2 | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: trendmicro-malware-scanner 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | {{- include "malwareScanner.labels" . | nindent 4 }} 10 | spec: 11 | {{- if not .Values.cloudOne.malwareScanning.scanner.autoscaling.enabled }} 12 | replicas: {{ .Values.replicaCount }} 13 | {{- end }} 14 | selector: 15 | matchLabels: 16 | {{- include "malwareScanner.selectorLabels" . | nindent 6 }} 17 | template: 18 | metadata: 19 | annotations: 20 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.malwareScanner) }} 21 | {{- toYaml . | nindent 8 }} 22 | {{- end }} 23 | labels: 24 | {{- include "malwareScanner.labels" . | nindent 8 }} 25 | spec: 26 | serviceAccountName: {{ include "malwareScanner.serviceAccountName" . }} 27 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 28 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.malwareScanner }} 29 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 30 | {{- $scannerSecurityContext := default .Values.securityContext.default.pod $securityContext.scanner }} 31 | {{- if $securityContextEnabled }} 32 | securityContext: 33 | {{ toYaml $podSecurityContext | indent 8 }} 34 | {{- end }}{{/* if $securityContextEnabled */}} 35 | {{- $imageDefaults := .Values.images.defaults }} 36 | {{- with .Values.images.malwareScanner }} 37 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 38 | {{- if not (eq "" $secret) }} 39 | imagePullSecrets: 40 | - name: {{ $secret | quote }} 41 | {{- end }} 42 | containers: 43 | - name: malware-scanner 44 | {{- if $securityContextEnabled }} 45 | securityContext: 46 | {{ toYaml $scannerSecurityContext | indent 12 }} 47 | {{- end }}{{/* if $securityContextEnabled */}} 48 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 49 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 50 | {{- $tag := (default $imageDefaults.tag .tag) }} 51 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 52 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 53 | {{- end }} 54 | ports: 55 | - name: grpc 56 | containerPort: {{ .Values.cloudOne.malwareScanning.scanner.port }} 57 | protocol: TCP 58 | livenessProbe: 59 | {{- toYaml .Values.cloudOne.malwareScanning.scanner.livenessProbe | nindent 12 }} 60 | readinessProbe: 61 | {{- toYaml .Values.cloudOne.malwareScanning.scanner.readinessProbe | nindent 12 }} 62 | resources: 63 | {{ toYaml (default .Values.resources.defaults .Values.resources.malwareScanner) | indent 12 }} 64 | volumeMounts: 65 | {{- include "proxy.selfSignedCertificates.volumeMounts" . | nindent 12 }} 66 | env: 67 | - name: HTTPS_PROXY 68 | valueFrom: 69 | secretKeyRef: 70 | name: {{ template "container.security.name" . }}-outbound-proxy-credentials 71 | key: allProxy 72 | - name: TM_AM_LOG_LEVEL 73 | value: "{{ include "logLevel" (list .Values.cloudOne.malwareScanning.scanner.logLevel .) }}" 74 | - name: TM_AM_SCAN_LOG 75 | value: "{{ .Values.cloudOne.malwareScanning.scanner.scanLog }}" 76 | - name: TM_AM_SCAN_CACHE 77 | value: "{{ .Values.cloudOne.malwareScanning.scanner.enableScanCache }}" 78 | - name: TM_AM_FLUENTBIT_CONF 79 | value: fluent-bit.conf 80 | - name: TM_AM_SCAN_CACHE_REDIS_HOST 81 | value: "localhost:6379" 82 | - name: TM_AM_V1_ENDPOINT 83 | value: "{{ printf "%s%s" .Values.cloudOne.endpoint "/api/authorizer/callerIdentity" }}" 84 | volumes: 85 | {{- include "proxy.selfSignedCertificates.volumes" . | nindent 8 }} 86 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.malwareScanner }} 87 | nodeSelector: 88 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.malwareScanner) | indent 8 }} 89 | {{- end }} 90 | {{- if or .Values.tolerations.defaults .Values.tolerations.malwareScanner }} 91 | tolerations: 92 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.malwareScanner) | indent 8 }} 93 | {{- end }} 94 | {{- if or .Values.affinity.defaults .Values.affinity.malwareScanner }} 95 | affinity: 96 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.malwareScanner) | indent 8 }} 97 | {{- end }} 98 | 99 | --- 100 | {{- if .Values.serviceAccount.create -}} 101 | apiVersion: v1 102 | kind: ServiceAccount 103 | metadata: 104 | name: {{ include "malwareScanner.serviceAccountName" . }} 105 | namespace: {{ .Release.Namespace }} 106 | labels: 107 | {{- include "malwareScanner.labels" . | nindent 4 }} 108 | {{- with .Values.serviceAccount.malwareScanner.annotations }} 109 | annotations: 110 | {{- toYaml . | nindent 4 }} 111 | {{- end }} 112 | automountServiceAccountToken: true 113 | {{- end }} 114 | 115 | --- 116 | apiVersion: v1 117 | kind: Service 118 | metadata: 119 | name: {{ include "malwareScanner.svc" . }} 120 | labels: 121 | {{- include "malwareScanner.labels" . | nindent 4 }} 122 | spec: 123 | ports: 124 | - port: {{ .Values.cloudOne.malwareScanning.scanner.port }} 125 | targetPort: grpc 126 | protocol: TCP 127 | selector: 128 | {{- include "malwareScanner.selectorLabels" . | nindent 4 }} 129 | 130 | --- 131 | {{- if .Values.cloudOne.malwareScanning.scanner.autoscaling.enabled }} 132 | apiVersion: autoscaling/v2 133 | kind: HorizontalPodAutoscaler 134 | metadata: 135 | name: {{ include "malwareScanner.fullname" . }} 136 | labels: 137 | {{- include "malwareScanner.labels" . | nindent 4 }} 138 | spec: 139 | scaleTargetRef: 140 | apiVersion: apps/v1 141 | kind: Deployment 142 | name: trendmicro-malware-scanner 143 | minReplicas: {{ .Values.cloudOne.malwareScanning.scanner.autoscaling.minReplicas }} 144 | maxReplicas: {{ .Values.cloudOne.malwareScanning.scanner.autoscaling.maxReplicas }} 145 | metrics: 146 | {{- if .Values.cloudOne.malwareScanning.scanner.autoscaling.targetCPUUtilization }} 147 | - type: Resource 148 | resource: 149 | name: cpu 150 | target: 151 | type: Utilization 152 | averageUtilization: {{ .Values.cloudOne.malwareScanning.scanner.autoscaling.targetCPUUtilization }} 153 | {{- end }} 154 | {{- if .Values.cloudOne.malwareScanning.scanner.autoscaling.targetMemoryUtilization }} 155 | - type: Resource 156 | resource: 157 | name: memory 158 | target: 159 | type: Utilization 160 | averageUtilization: {{ .Values.cloudOne.malwareScanning.scanner.autoscaling.targetMemoryUtilization }} 161 | {{- end }} 162 | {{- end }} 163 | 164 | --- 165 | {{- $networkpolicyEnabled := and (hasKey .Values.networkPolicy "malwareScanner") (hasKey .Values.networkPolicy.malwareScanner "enabled") | ternary .Values.networkPolicy.malwareScanner.enabled .Values.networkPolicy.enabled }} 166 | {{ if $networkpolicyEnabled }} 167 | 168 | apiVersion: networking.k8s.io/v1 169 | kind: NetworkPolicy 170 | metadata: 171 | name: malware-scanner-networkpolicy 172 | namespace: {{ .Release.Namespace }} 173 | labels: 174 | {{- include "malwareScanner.labels" . | nindent 4 }} 175 | spec: 176 | podSelector: 177 | matchLabels: 178 | {{- include "malwareScanner.selectorLabels" . | nindent 6 }} 179 | policyTypes: 180 | - Ingress 181 | ingress: 182 | - from: 183 | - podSelector: {} 184 | ports: 185 | - protocol: TCP 186 | port: {{ .Values.cloudOne.malwareScanning.scanner.port }} 187 | {{- end }} 188 | 189 | {{- end }} 190 | -------------------------------------------------------------------------------- /templates/mutatingwebhook.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.fargateInjector.enabled) }} 2 | {{- $cn := printf "%s.%s.svc" "trendmicro-fargate-injector" .Release.Namespace }} 3 | {{- $ca := genCA (printf "%s-ca" "trendmicro-fargate-injector") (default 3650 (int .Values.cloudOne.fargateInjector.certificate.lifetime)) -}} 4 | {{- $cert := genSignedCert (default $cn .Values.cloudOne.fargateInjector.certificate.commonName) (default nil .Values.cloudOne.fargateInjector.certificate.ipAlternativeNames) (default (list $cn) .Values.cloudOne.fargateInjector.certificate.dnsAlternativeNames) (default 3650 (int .Values.cloudOne.fargateInjector.certificate.lifetime)) $ca -}} 5 | 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: {{ template "fargateInjector.fullname" . }}-tls-certificate 10 | namespace: {{ .Release.Namespace }} 11 | labels: 12 | {{- include "fargateInjector.labels" . | nindent 4 }} 13 | type: Opaque 14 | data: 15 | key.pem: {{ $cert.Key | b64enc | quote }} 16 | cert.pem: {{ $cert.Cert | b64enc | quote }} 17 | 18 | --- 19 | apiVersion: admissionregistration.k8s.io/v1 20 | kind: MutatingWebhookConfiguration 21 | metadata: 22 | name: {{ include "fargateInjector.fullname" . }} 23 | namespace: {{ .Release.Namespace }} 24 | labels: 25 | {{- include "fargateInjector.labels" . | nindent 4 }} 26 | webhooks: 27 | - name: {{ default $cn .Values.cloudOne.fargateInjector.certificate.commonName }} 28 | rules: 29 | - apiGroups: 30 | - '*' 31 | apiVersions: 32 | - '*' 33 | operations: ["CREATE", "CONNECT"] 34 | resources: 35 | - "pods" 36 | - "pods/exec" 37 | - "pods/attach" 38 | - "replicasets" 39 | - "replicationcontrollers" 40 | - "deployments" 41 | - "statefulsets" 42 | - "daemonsets" 43 | - "jobs" 44 | - "cronjobs" 45 | scope: "*" 46 | failurePolicy: {{ required "A valid failure policy is required!" .Values.cloudOne.fargateInjector.failurePolicy }} 47 | clientConfig: 48 | service: 49 | name: trendmicro-fargate-injector 50 | namespace: {{ .Release.Namespace }} 51 | path: "/" 52 | caBundle: {{ $ca.Cert | b64enc | quote }} 53 | admissionReviewVersions: ["v1", "v1beta1"] 54 | sideEffects: None 55 | timeoutSeconds: {{ default 30 .Values.cloudOne.fargateInjector.webhookTimeoutSeconds }} 56 | {{- end }} 57 | -------------------------------------------------------------------------------- /templates/outbound-proxy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ template "container.security.name" . }}-outbound-proxy 5 | labels: 6 | {{- include "container.security.labels" . | nindent 4 }} 7 | data: 8 | httpProxy: {{ quote (default "" .Values.proxy.httpProxy) }} 9 | httpsProxy: {{ quote (default "" .Values.proxy.httpsProxy) }} 10 | noProxy: {{ quote (printf ".cluster.local,%s" .Values.proxy.noProxy) }} 11 | 12 | --- 13 | {{ if not (and .Values.useExistingSecrets (eq true .Values.useExistingSecrets.outboundProxy)) }} 14 | apiVersion: v1 15 | kind: Secret 16 | metadata: 17 | name: {{ template "container.security.name" . }}-outbound-proxy-credentials 18 | labels: 19 | {{- include "container.security.labels" . | nindent 4 }} 20 | type: Opaque 21 | data: 22 | username: {{ default "" .Values.proxy.username | toString | b64enc | quote }} 23 | password: {{ default "" .Values.proxy.password | toString | b64enc | quote }} 24 | {{if .Values.proxy.username}} 25 | {{if .Values.proxy.httpsProxy | hasPrefix "socks5://"}} 26 | allProxy: {{printf "socks5://%s:%s@%s" (.Values.proxy.username | urlquery) .Values.proxy.password (.Values.proxy.httpsProxy | trimPrefix "socks5://") | b64enc | quote}} 27 | {{else if .Values.proxy.httpsProxy | hasPrefix "http://"}} 28 | allProxy: {{printf "http://%s:%s@%s" .Values.proxy.username .Values.proxy.password (.Values.proxy.httpsProxy | trimPrefix "http://") | b64enc | quote}} 29 | {{else}} 30 | allProxy: {{printf "http://%s:%s@%s" .Values.proxy.username .Values.proxy.password .Values.proxy.httpsProxy | b64enc | quote}} 31 | {{ end }} 32 | {{else}} 33 | allProxy: {{ default "" .Values.proxy.httpsProxy | toString | b64enc | quote }} 34 | {{ end }} 35 | {{ end }} 36 | -------------------------------------------------------------------------------- /templates/oversight-controller-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq true .Values.cloudOne.oversight.enabled }} 2 | {{- if .Values.rbac.create }} 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: Role 5 | metadata: 6 | name: oversight-leader-election-role 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | {{- include "oversight.labels" . | nindent 4 }} 10 | rules: 11 | - apiGroups: 12 | - "" 13 | resources: 14 | - configmaps 15 | verbs: 16 | - get 17 | - list 18 | - watch 19 | - create 20 | - update 21 | - patch 22 | - delete 23 | - apiGroups: 24 | - coordination.k8s.io 25 | resources: 26 | - leases 27 | verbs: 28 | - get 29 | - list 30 | - watch 31 | - create 32 | - update 33 | - patch 34 | - delete 35 | - apiGroups: 36 | - "" 37 | resources: 38 | - events 39 | verbs: 40 | - create 41 | - patch 42 | --- 43 | apiVersion: rbac.authorization.k8s.io/v1 44 | kind: ClusterRole 45 | metadata: 46 | creationTimestamp: null 47 | name: oversight-manager-role 48 | labels: 49 | {{- include "oversight.labels" . | nindent 4 }} 50 | rules: 51 | - apiGroups: 52 | - coordination.k8s.io 53 | - "" 54 | resources: 55 | - leases 56 | - nodes 57 | verbs: 58 | - get 59 | - list 60 | - watch 61 | - apiGroups: 62 | - "" 63 | resources: 64 | - pods 65 | verbs: 66 | - delete 67 | - get 68 | - list 69 | - patch 70 | - update 71 | - watch 72 | - apiGroups: 73 | - "" 74 | resources: 75 | - pods/status 76 | verbs: 77 | - get 78 | - patch 79 | - update 80 | - apiGroups: 81 | - cloudone.trendmicro.com 82 | resources: 83 | - oversights 84 | verbs: 85 | - create 86 | - delete 87 | - get 88 | - list 89 | - patch 90 | - update 91 | - watch 92 | - apiGroups: 93 | - cloudone.trendmicro.com 94 | resources: 95 | - oversights/status 96 | verbs: 97 | - get 98 | - patch 99 | - update 100 | {{- if eq true .Values.cloudOne.oversight.enableNetworkPolicyCreation }} 101 | - apiGroups: 102 | - networking.k8s.io 103 | resources: 104 | - networkpolicies 105 | verbs: 106 | - create 107 | - get 108 | - list 109 | - patch 110 | - update 111 | - watch 112 | - apiGroups: 113 | - networking.k8s.io 114 | resources: 115 | - networkpolicies/status 116 | verbs: 117 | - get 118 | - patch 119 | - update 120 | - apiGroups: 121 | - batch 122 | resources: 123 | - jobs 124 | verbs: 125 | - get 126 | - list 127 | - watch 128 | - create 129 | {{- end }} 130 | 131 | --- 132 | apiVersion: rbac.authorization.k8s.io/v1 133 | kind: ClusterRole 134 | metadata: 135 | name: oversight-proxy-role 136 | labels: 137 | {{- include "oversight.labels" . | nindent 4 }} 138 | rules: 139 | - apiGroups: 140 | - authentication.k8s.io 141 | resources: 142 | - tokenreviews 143 | verbs: 144 | - create 145 | - apiGroups: 146 | - authorization.k8s.io 147 | resources: 148 | - subjectaccessreviews 149 | verbs: 150 | - create 151 | 152 | --- 153 | apiVersion: rbac.authorization.k8s.io/v1 154 | kind: RoleBinding 155 | metadata: 156 | name: oversight-leader-election-rolebinding 157 | namespace: {{ .Release.Namespace }} 158 | labels: 159 | {{- include "oversight.labels" . | nindent 4 }} 160 | roleRef: 161 | apiGroup: rbac.authorization.k8s.io 162 | kind: Role 163 | name: oversight-leader-election-role 164 | subjects: 165 | - kind: ServiceAccount 166 | name: {{ include "oversight.serviceAccountName" . }} 167 | namespace: {{ .Release.Namespace }} 168 | 169 | --- 170 | apiVersion: rbac.authorization.k8s.io/v1 171 | kind: ClusterRoleBinding 172 | metadata: 173 | name: oversight-manager-rolebinding 174 | labels: 175 | {{- include "oversight.labels" . | nindent 4 }} 176 | roleRef: 177 | apiGroup: rbac.authorization.k8s.io 178 | kind: ClusterRole 179 | name: oversight-manager-role 180 | subjects: 181 | - kind: ServiceAccount 182 | name: {{ include "oversight.serviceAccountName" . }} 183 | namespace: {{ .Release.Namespace }} 184 | 185 | --- 186 | apiVersion: rbac.authorization.k8s.io/v1 187 | kind: ClusterRoleBinding 188 | metadata: 189 | name: oversight-proxy-rolebinding 190 | labels: 191 | {{- include "oversight.labels" . | nindent 4 }} 192 | roleRef: 193 | apiGroup: rbac.authorization.k8s.io 194 | kind: ClusterRole 195 | name: oversight-proxy-role 196 | subjects: 197 | - kind: ServiceAccount 198 | name: {{ include "oversight.serviceAccountName" . }} 199 | namespace: {{ .Release.Namespace }} 200 | {{- end }} 201 | {{- end }} 202 | -------------------------------------------------------------------------------- /templates/oversight-controller-scc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 2 | apiVersion: security.openshift.io/v1 3 | kind: SecurityContextConstraints 4 | metadata: 5 | annotations: 6 | kubernetes.io/description: | 7 | This SCC provides the privilege requirement to run the Oversight-Controller in Openshift. 8 | name: {{ template "container.security.name" . }}-oversight 9 | namespace: {{ .Release.Namespace }} 10 | labels: 11 | {{- include "container.security.labels" . | nindent 4 }} 12 | {{- $securityContextConstraints := .Values.serviceAccount.oversight.securityContextConstraints }} 13 | {{ toYaml $securityContextConstraints }} 14 | volumes: 15 | - configMap 16 | - downwardAPI 17 | - emptyDir 18 | - secret 19 | users: 20 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "oversight.serviceAccountName" . }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /templates/oversight.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq true .Values.cloudOne.oversight.enabled }} 2 | apiVersion: cloudone.trendmicro.com/v1 3 | kind: Oversight 4 | metadata: 5 | name: {{ template "oversight.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "oversight.labels" . | nindent 4 }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /templates/policy-operator-cluster-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: policy-operator-cluster-role 6 | labels: 7 | {{- include "policyOperator.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: 10 | - visionone.trendmicro.com 11 | resources: 12 | - clusterpolicies 13 | - runtimerulesets 14 | - clusters 15 | verbs: 16 | - get 17 | - list 18 | - watch 19 | - update 20 | - patch 21 | - apiGroups: 22 | - visionone.trendmicro.com 23 | resources: 24 | - clusterpolicies/status 25 | - runtimerulesets/status 26 | - clusters/status 27 | verbs: 28 | - get 29 | - update 30 | - apiGroups: 31 | - coordination.k8s.io 32 | resources: 33 | - leases 34 | verbs: 35 | - get 36 | - list 37 | - watch 38 | - create 39 | - update 40 | - patch 41 | - delete 42 | - apiGroups: 43 | - "" 44 | resources: 45 | - events 46 | verbs: 47 | - create 48 | - patch 49 | --- 50 | apiVersion: rbac.authorization.k8s.io/v1 51 | kind: ClusterRoleBinding 52 | metadata: 53 | name: policy-operator-cluster-role-rolebinding 54 | labels: 55 | {{- include "policyOperator.labels" . | nindent 4 }} 56 | roleRef: 57 | apiGroup: rbac.authorization.k8s.io 58 | kind: ClusterRole 59 | name: policy-operator-cluster-role 60 | subjects: 61 | - kind: ServiceAccount 62 | name: {{ include "policyOperator.serviceAccountName" . }} 63 | namespace: {{ .Release.Namespace }} 64 | -------------------------------------------------------------------------------- /templates/policy-operator-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.policyOperator.enabled) (.Values.cloudOne.clusterRegistrationKey) (.Values.visionOneFeatureGate) (eq (include "container.security.isVisionOneEndpoint" .) "true") }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: policy-operator-role 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "policyOperator.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - secrets 14 | verbs: 15 | - create 16 | - get 17 | - list 18 | - watch 19 | - update 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - configmaps 24 | verbs: 25 | - get 26 | - list 27 | - watch 28 | - update 29 | --- 30 | apiVersion: rbac.authorization.k8s.io/v1 31 | kind: RoleBinding 32 | metadata: 33 | name: policy-operator-role-rolebinding 34 | namespace: {{ .Release.Namespace }} 35 | labels: 36 | {{- include "policyOperator.labels" . | nindent 4 }} 37 | roleRef: 38 | apiGroup: rbac.authorization.k8s.io 39 | kind: Role 40 | name: policy-operator-role 41 | subjects: 42 | - kind: ServiceAccount 43 | name: {{ include "policyOperator.serviceAccountName" . }} 44 | namespace: {{ .Release.Namespace }} 45 | {{- end }} -------------------------------------------------------------------------------- /templates/policy-operator.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.policyOperator.enabled) (.Values.cloudOne.clusterRegistrationKey) (.Values.visionOneFeatureGate) (eq (include "container.security.isVisionOneEndpoint" .) "true") }} 2 | {{- include "validateClusterInput" . -}} 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: trendmicro-policy-operator 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | {{- include "policyOperator.labels" . | nindent 4 }} 10 | spec: 11 | replicas: 1 12 | selector: 13 | matchLabels: 14 | {{- include "policyOperator.selectorLabels" . | nindent 6 }} 15 | template: 16 | metadata: 17 | annotations: 18 | checksum/auth: {{ include "container.security.auth.secret" . | sha256sum }} 19 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.policyOperator) }} 20 | {{- toYaml . | nindent 8 }} 21 | {{- end }} 22 | labels: 23 | {{- include "policyOperator.labels" . | nindent 8 }} 24 | spec: 25 | serviceAccountName: {{ include "policyOperator.serviceAccountName" . }} 26 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 27 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.policyOperator }} 28 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 29 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container.policyOperator }} 30 | {{- if $securityContextEnabled }} 31 | securityContext: 32 | {{ toYaml $podSecurityContext | indent 8 }} 33 | {{- end }} 34 | {{- $imageDefaults := .Values.images.defaults }} 35 | {{- with .Values.images.policyOperator }} 36 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 37 | {{- if not (eq "" $secret) }} 38 | imagePullSecrets: 39 | - name: {{ $secret | quote }} 40 | {{- end }} 41 | containers: 42 | - name: trendmicro-policy-operator 43 | {{- if $securityContextEnabled }} 44 | securityContext: 45 | {{ toYaml $containerSecurityContext | indent 12 }} 46 | {{- end }} 47 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 48 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 49 | {{- $tag := (default $imageDefaults.tag .tag) }} 50 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 51 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 52 | {{- end }} 53 | args: 54 | - --zap-devel={{ default "false" .Values.logConfig.devel }} 55 | - --zap-log-level={{ include "logLevel" (list .Values.cloudOne.policyOperator.logLevel .) }} 56 | - --zap-encoder={{ default "json" .Values.logConfig.encoder }} 57 | - --zap-stacktrace-level={{ default "error" .Values.logConfig.stacktraceLevel }} 58 | - --zap-time-encoding={{ default "rfc3339" .Values.logConfig.timeEncoding }} 59 | - --cloud-one-endpoint={{ include "container.security.endpoint" . }} 60 | - --exclude-kubernetes-service-host-from-proxy={{ default "false" .Values.proxy.excludeKubernetesServiceHost }} 61 | - --reconciliation-period={{ .Values.cloudOne.policyOperator.reconciliationPeriod }} 62 | - --cluster-policy-name={{ .Values.cloudOne.policyOperator.clusterPolicyName }} 63 | - --cluster-name={{ .Values.cloudOne.clusterName }} 64 | - --cluster-name-prefix={{ .Values.cloudOne.clusterNamePrefix }} 65 | - --cluster-policy-id={{ .Values.cloudOne.policyId }} 66 | - --cluster-group-id={{ .Values.cloudOne.groupId }} 67 | - --namespace={{ .Release.Namespace }} 68 | - --auth-name={{ template "container.security.fullname" . }}-auth 69 | - --auto-register={{ default "false" .Values.cloudOne.clusterRegistrationKey }} 70 | - --enable-token-rotation={{ include "container.security.isVisionOneEndpoint" . }} 71 | {{- if .Values.visionOneFeatureGate }} 72 | - --spc-mode={{ default "false" .Values.spc.enabled }} 73 | - --policy-sync-interval={{ include "policyOperator.policy.sync.interval" . }} 74 | - --policy-config-name={{ template "container.security.name" . }}-policy-config 75 | - --runtime-rulesets-config-name={{ template "container.security.name" . }}-runtime-rulesets-config 76 | - --runtime-rules-config-name={{ template "container.security.name" . }}-runtime-rules-config 77 | - --runtime-policy-config-name={{ template "container.security.name" . }}-runtime-policy-config 78 | - --vision-one-feature-gate=true 79 | {{- end }} 80 | command: 81 | - /app/policy-operator 82 | env: 83 | - name: POD_NAME 84 | valueFrom: 85 | fieldRef: 86 | fieldPath: metadata.name 87 | - name: POD_NAMESPACE 88 | valueFrom: 89 | fieldRef: 90 | fieldPath: metadata.namespace 91 | {{- include "container.security.proxy.env" . | nindent 8 }} 92 | volumeMounts: 93 | - mountPath: /var/policy-operator 94 | name: workdir 95 | - mountPath: /secrets 96 | name: api-key 97 | {{- if .Values.cloudOne.clusterRegistrationKey }} 98 | - mountPath: /reg-secrets 99 | name: registration-key 100 | {{- end }} 101 | {{- include "proxy.selfSignedCertificates.volumeMounts" . | nindent 8 }} 102 | volumes: 103 | - name: workdir 104 | emptyDir: 105 | sizeLimit: 50Mi 106 | - name: api-key 107 | secret: 108 | secretName: {{ template "container.security.fullname" . }}-auth 109 | {{- if .Values.cloudOne.clusterRegistrationKey }} 110 | optional: true 111 | - name: registration-key 112 | secret: 113 | secretName: {{ template "container.security.fullname" . }}-registration-key 114 | {{- end }} 115 | {{- include "proxy.selfSignedCertificates.volumes" . | nindent 8 }} 116 | terminationGracePeriodSeconds: 10 117 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.policyOperator }} 118 | nodeSelector: 119 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.policyOperator) | indent 8 }} 120 | {{- end }} 121 | {{- if or .Values.tolerations.defaults .Values.tolerations.policyOperator }} 122 | tolerations: 123 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.policyOperator) | indent 8 }} 124 | {{- end }} 125 | {{- if or .Values.affinity.defaults .Values.affinity.policyOperator }} 126 | affinity: 127 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.policyOperator) | indent 8 }} 128 | {{- end }} 129 | {{- $classname := (default (default "" .Values.priorityClassName.default ) .Values.priorityClassName.policyOperator) }} 130 | {{- if not (eq "" $classname) }} 131 | priorityClassName: "{{ $classname }}" 132 | {{- end }} 133 | restartPolicy: Always 134 | {{ if .Values.serviceAccount.create }} 135 | --- 136 | apiVersion: v1 137 | kind: ServiceAccount 138 | metadata: 139 | name: {{ include "policyOperator.serviceAccountName" . }} 140 | labels: 141 | {{- include "policyOperator.labels" . | nindent 4 }} 142 | {{- with .Values.serviceAccount.policyOperator.annotations }} 143 | annotations: 144 | {{- toYaml . | nindent 4 }} 145 | {{- end }} 146 | {{- end }} 147 | {{- end }} 148 | --- 149 | apiVersion: v1 150 | kind: ConfigMap 151 | metadata: 152 | name: {{ template "container.security.name" . }}-policy-config 153 | namespace: {{ .Release.Namespace }} 154 | labels: 155 | {{- include "container.security.labels" . | nindent 4 }} 156 | data: 157 | cluster.policy: "{}" 158 | --- 159 | apiVersion: v1 160 | kind: ConfigMap 161 | metadata: 162 | name: {{ template "container.security.name" . }}-runtime-rulesets-config 163 | namespace: {{ .Release.Namespace }} 164 | labels: 165 | {{- include "container.security.labels" . | nindent 4 }} 166 | data: 167 | runtime.rulesets: "{}" 168 | --- 169 | apiVersion: v1 170 | kind: ConfigMap 171 | metadata: 172 | name: {{ template "container.security.name" . }}-runtime-rules-config 173 | namespace: {{ .Release.Namespace }} 174 | labels: 175 | {{- include "container.security.labels" . | nindent 4 }} 176 | data: 177 | runtime.rules: "" 178 | --- 179 | apiVersion: v1 180 | kind: ConfigMap 181 | metadata: 182 | name: {{ template "container.security.name" . }}-runtime-policy-config 183 | namespace: {{ .Release.Namespace }} 184 | labels: 185 | {{- include "container.security.labels" . | nindent 4 }} 186 | data: 187 | runtime.policy: "{}" 188 | -------------------------------------------------------------------------------- /templates/scan-job-scc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 2 | apiVersion: security.openshift.io/v1 3 | kind: SecurityContextConstraints 4 | metadata: 5 | annotations: 6 | kubernetes.io/description: | 7 | This SCC provides least-privilege requirement to run the scan job in Openshift. 8 | name: {{ template "container.security.name" . }}-scanner 9 | namespace: {{ .Release.Namespace }} 10 | labels: 11 | {{- include "container.security.labels" . | nindent 4 }} 12 | allowHostDirVolumePlugin: true 13 | allowHostIPC: false 14 | allowHostNetwork: false 15 | allowHostPID: false 16 | allowHostPorts: false 17 | allowPrivilegeEscalation: {{ .Values.scanner.imageAnnotations.enabled }} 18 | allowPrivilegedContainer: {{ .Values.scanner.imageAnnotations.enabled }} 19 | allowedCapabilities: 20 | {{- toYaml .Values.securityContext.scanner.target.capabilities.add | nindent 2}} 21 | allowedUnsafeSysctls: [] 22 | defaultAddCapabilities: [] 23 | fsGroup: 24 | type: MustRunAs 25 | groups: [] 26 | priority: 0 27 | readOnlyRootFilesystem: true 28 | requiredDropCapabilities: [] 29 | runAsUser: 30 | type: RunAsAny 31 | seLinuxContext: 32 | type: MustRunAs 33 | supplementalGroups: 34 | type: RunAsAny 35 | users: [] 36 | volumes: 37 | - hostPath 38 | - configMap 39 | - downwardAPI 40 | - emptyDir 41 | - secret 42 | {{- end }} 43 | -------------------------------------------------------------------------------- /templates/scan-manager-config.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.vulnerabilityScanning.enabled) (eq true .Values.cloudOne.malwareScanning.enabled) (eq true .Values.cloudOne.secretScanning.enabled) }} 2 | --- 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: {{ template "container.security.name" . }}-scan-manager-config 7 | labels: 8 | {{- include "scanManager.labels" . | nindent 4 }} 9 | data: 10 | inheritNodeSelector: {{ .Values.nodeSelector.inheritNodeSelectorScanner | quote }} 11 | inheritTolerations: {{ .Values.tolerations.inheritTolerationsScanner | quote }} 12 | filterInheritNodeSelector: | 13 | {{- if .Values.nodeSelector.filterNodeSelectorScanner }} 14 | {{- toYaml .Values.nodeSelector.filterNodeSelectorScanner | nindent 6 }} 15 | {{- end }} 16 | filterInheritTolerations: | 17 | {{- if .Values.tolerations.filterTolerationsScanner }} 18 | {{- toYaml .Values.tolerations.filterTolerationsScanner | nindent 6 }} 19 | {{- end }} 20 | scan-job-template.yaml: | 21 | apiVersion: batch/v1 22 | kind: Job 23 | metadata: 24 | labels: 25 | {{- include "scanner.labels" . | nindent 8 }} 26 | sidecar.istio.io/inject: "false" 27 | annotations: 28 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.scanner) }} 29 | {{- toYaml . | nindent 8 }} 30 | {{- end }} 31 | argocd.argoproj.io/sync-options: Prune=false 32 | argocd.argoproj.io/compare-options: IgnoreExtraneous 33 | spec: 34 | backoffLimit: 2 35 | activeDeadlineSeconds: {{ .Values.cloudOne.scanManager.activeDeadlineSeconds }} 36 | ttlSecondsAfterFinished: 60 37 | template: 38 | metadata: 39 | labels: 40 | {{- include "scanner.labels" . | nindent 12 }} 41 | ignoreRuntimeScan: true 42 | sidecar.istio.io/inject: "false" 43 | annotations: 44 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.scanner) }} 45 | {{- toYaml . | nindent 12 }} 46 | {{- end }} 47 | argocd.argoproj.io/sync-options: Prune=false 48 | argocd.argoproj.io/compare-options: IgnoreExtraneous 49 | spec: 50 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 51 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.scanner }} 52 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 53 | {{- $initSecurityContext := default .Values.securityContext.default.container $securityContext.init }} 54 | {{- $targetSecurityContext := default .Values.securityContext.default.container $securityContext.target }} 55 | {{- if $securityContextEnabled }} 56 | securityContext: 57 | {{ toYaml $podSecurityContext | indent 12 }} 58 | {{- end }} 59 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 60 | serviceAccountName: {{ include "scanJob.serviceAccountName" . }} 61 | {{- end }} 62 | restartPolicy: Never 63 | volumes: 64 | - name: utility-volume 65 | emptyDir: {} 66 | - name: tmp-volume 67 | emptyDir: {} 68 | {{- if and .Values.cloudOne.vulnerabilityScanning.enabled .Values.scanner.imageAnnotations.enabled }} 69 | {{- include "containerRuntime.sock.volumes" ( list $ .Values.scanner.imageAnnotations ) | trim | nindent 10 }} 70 | {{- end }} 71 | initContainers: 72 | - name: vulnerability-scanner-init 73 | image: IMAGE 74 | imagePullPolicy: Always 75 | volumeMounts: 76 | - mountPath: /utility 77 | name: utility-volume 78 | args: 79 | - init 80 | {{- if $securityContextEnabled }} 81 | securityContext: 82 | {{ toYaml $initSecurityContext | indent 14 }} 83 | {{- end }} 84 | resources: 85 | {{ toYaml (default .Values.resources.defaults .Values.resources.scanner) | indent 14 }} 86 | containers: 87 | - name: target 88 | image: IMAGE 89 | imagePullPolicy: Always 90 | args: 91 | {{- if and .Values.cloudOne.vulnerabilityScanning.enabled .Values.scanner.imageAnnotations.enabled }} 92 | {{- include "containerRuntime.sock.args" ( list "cri-path" "/host" .Values.scanner.imageAnnotations ) | trim | nindent 14 }} 93 | {{- end }} 94 | env: 95 | {{- if .Values.cloudOne.malwareScanning.enabled }} 96 | - name: TM_AM_SCAN_TIMEOUT_SECS 97 | value: {{ .Values.cloudOne.malwareScanning.scanTimeoutSeconds }} 98 | {{- end }} 99 | {{- if .Values.cloudOne.secretScanning.enabled }} 100 | - name: TMAS_SCAN_TIMEOUT_SECS 101 | value: {{ .Values.cloudOne.secretScanning.scanTimeoutSeconds }} 102 | {{- end }} 103 | volumeMounts: 104 | - mountPath: /utility 105 | name: utility-volume 106 | readOnly: true 107 | - mountPath: /tmp 108 | name: tmp-volume 109 | {{- if and .Values.cloudOne.vulnerabilityScanning.enabled .Values.scanner.imageAnnotations.enabled }} 110 | {{- include "containerRuntime.sock.volumeMounts" ( list "/host" .Values.scanner.imageAnnotations ) | trim | nindent 14 }} 111 | {{- end }} 112 | {{- if $securityContextEnabled }} 113 | securityContext: 114 | {{ toYaml $targetSecurityContext | indent 14 }} 115 | {{- end }} 116 | resources: 117 | {{ toYaml (default .Values.resources.defaults .Values.resources.scanner) | indent 14 }} 118 | {{- end }} 119 | -------------------------------------------------------------------------------- /templates/scan-manager-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.vulnerabilityScanning.enabled) (eq true .Values.cloudOne.malwareScanning.enabled) (eq true .Values.cloudOne.secretScanning.enabled) }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: scan-manager-role 7 | labels: 8 | {{- include "scanManager.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - cloudone.trendmicro.com 12 | resources: 13 | - workloadimages 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - update 19 | - apiGroups: 20 | - "" 21 | - batch 22 | - apps 23 | resources: 24 | - pods 25 | - deployments 26 | - replicasets 27 | - daemonsets 28 | - statefulsets 29 | - jobs 30 | - cronjobs 31 | - namespaces 32 | verbs: 33 | - get 34 | - list 35 | - watch 36 | - apiGroups: 37 | - "" 38 | resources: 39 | - secrets 40 | verbs: 41 | - get 42 | - create 43 | - update 44 | - delete 45 | - list 46 | - watch 47 | - apiGroups: 48 | - batch 49 | resources: 50 | - jobs 51 | verbs: 52 | - get 53 | - list 54 | - watch 55 | - create 56 | - apiGroups: 57 | - "" 58 | resources: 59 | - services 60 | - endpoints 61 | verbs: 62 | - get 63 | - list 64 | - apiGroups: 65 | - security.openshift.io 66 | resources: 67 | - securitycontextconstraints 68 | verbs: 69 | - use 70 | - apiGroups: 71 | - "" 72 | resources: 73 | - serviceaccounts 74 | verbs: 75 | - get 76 | - list 77 | - create 78 | - update 79 | - apiGroups: 80 | - rbac.authorization.k8s.io 81 | resources: 82 | - clusterroles 83 | - clusterrolebindings 84 | verbs: 85 | - get 86 | - list 87 | - create 88 | - update 89 | --- 90 | apiVersion: rbac.authorization.k8s.io/v1 91 | kind: ClusterRoleBinding 92 | metadata: 93 | name: scan-manager-rolebinding 94 | labels: 95 | {{- include "scanManager.labels" . | nindent 4 }} 96 | roleRef: 97 | apiGroup: rbac.authorization.k8s.io 98 | kind: ClusterRole 99 | name: scan-manager-role 100 | subjects: 101 | - kind: ServiceAccount 102 | name: {{ include "scanManager.serviceAccountName" . }} 103 | namespace: {{ .Release.Namespace }} 104 | --- 105 | apiVersion: rbac.authorization.k8s.io/v1 106 | kind: ClusterRole 107 | metadata: 108 | name: scan-manager-cleanup-resources-role 109 | labels: 110 | {{- include "scanManager.labels" . | nindent 4 }} 111 | annotations: 112 | helm.sh/hook: post-delete 113 | helm.sh/hook-delete-policy: hook-succeeded,hook-failed,before-hook-creation 114 | helm.sh/hook-weight: "-9" 115 | rules: 116 | - apiGroups: [""] 117 | resources: ["secrets", "serviceaccounts"] 118 | verbs: ["get", "list", "delete"] 119 | - apiGroups: [""] 120 | resources: ["namespaces"] 121 | verbs: ["get", "list"] 122 | - apiGroups: ["rbac.authorization.k8s.io"] 123 | resources: ["clusterroles", "clusterrolebindings"] 124 | verbs: ["get", "list", "delete"] 125 | --- 126 | apiVersion: rbac.authorization.k8s.io/v1 127 | kind: ClusterRoleBinding 128 | metadata: 129 | name: scan-manager-cleanup-resources-rolebinding 130 | labels: 131 | {{- include "scanManager.labels" . | nindent 4 }} 132 | annotations: 133 | helm.sh/hook: post-delete 134 | helm.sh/hook-delete-policy: hook-succeeded,hook-failed,before-hook-creation 135 | helm.sh/hook-weight: "-8" 136 | roleRef: 137 | apiGroup: rbac.authorization.k8s.io 138 | kind: ClusterRole 139 | name: scan-manager-cleanup-resources-role 140 | subjects: 141 | - kind: ServiceAccount 142 | name: scan-manager-cleanup-resources-service-account 143 | namespace: {{ .Release.Namespace }} 144 | {{- end }} 145 | -------------------------------------------------------------------------------- /templates/scout/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq (include "scout.shouldDeploy" .) "true" }} 2 | {{- if .Values.rbac.create }} 3 | kind: ClusterRole 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | metadata: 6 | name: scout-role 7 | labels: 8 | {{- include "scout.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - extensions 12 | - "" 13 | resources: 14 | - nodes 15 | - namespaces 16 | - pods 17 | - replicationcontrollers 18 | - replicasets 19 | - services 20 | - daemonsets 21 | - deployments 22 | - events 23 | - configmaps 24 | verbs: 25 | - get 26 | - list 27 | - watch 28 | - apiGroups: 29 | - apps 30 | resources: 31 | - daemonsets 32 | - deployments 33 | - replicasets 34 | - statefulsets 35 | verbs: 36 | - get 37 | - list 38 | - watch 39 | - nonResourceURLs: 40 | - /healthz 41 | - /healthz/* 42 | verbs: 43 | - get 44 | {{- end }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /templates/scout/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq (include "scout.shouldDeploy" .) "true" }} 2 | {{- if .Values.rbac.create }} 3 | kind: ClusterRoleBinding 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | metadata: 6 | name: scout-rolebinding 7 | labels: 8 | {{- include "scout.labels" . | nindent 4 }} 9 | subjects: 10 | - kind: ServiceAccount 11 | name: {{ include "scout.serviceAccountName" . }} 12 | namespace: {{ .Release.Namespace }} 13 | roleRef: 14 | kind: ClusterRole 15 | name: scout-role 16 | apiGroup: rbac.authorization.k8s.io 17 | {{- end }} 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /templates/scout/configmap-falco-customrules-config.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.cloudOne.runtimeSecurity.enabled .Values.cloudOne.runtimeSecurity.customRules.enabled }} 2 | {{ $events_pipe := (printf "%v/falco-customrules-events" .Values.scout.falco.falcoctl.pipes_dir ) }} 3 | --- 4 | apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: {{ template "container.security.name" . }}-customrules-falco-config 8 | labels: 9 | {{- include "scout.labels" . | nindent 4 }} 10 | data: 11 | {{- if .Values.cloudOne.runtimeSecurity.customRules.ociRepository.enabled }} 12 | falcoctl.yaml: | 13 | artifact: 14 | follow: 15 | every: 6h0m0s 16 | refs: 17 | {{- range .Values.cloudOne.runtimeSecurity.customRules.ociRepository.artifactUrls }} 18 | - {{ . }} 19 | {{- end }} 20 | {{- end }} 21 | falco-customrules-wrapper.sh: | 22 | #!/usr/bin/env bash 23 | #set -x 24 | {{- if .Values.cloudOne.runtimeSecurity.customRules.ociRepository.enabled }} 25 | # create empty oci-artifact files to allow falco watch them; 26 | # falco skips non-existed files 27 | {{- range .Values.cloudOne.runtimeSecurity.customRules.ociRepository.ruleFiles }} 28 | > {{ $.Values.scout.falco.ociRepository.artifacts_dir }}/{{- . -}} 29 | {{- end }} 30 | # configure OCI artifact with falcoctl 31 | set -o pipefail 32 | # this pipe aggregates falco and falcoctl events 33 | mkfifo {{ $events_pipe }} 34 | {{- if .Values.cloudOne.runtimeSecurity.customRules.params.clusterName }} 35 | SIEM_CLUSTER_NAME={{- .Values.cloudOne.runtimeSecurity.customRules.params.clusterName | quote -}} 36 | {{- else if .Values.clusterName }} 37 | SIEM_CLUSTER_NAME={{- .Values.clusterName | quote -}} 38 | {{- else }} 39 | SIEM_CLUSTER_NAME="" 40 | {{- end }} 41 | export SIEM_CLUSTER_NAME 42 | # map events generated by falco and falcoctl into artifact related events and send them using HEC_CLIENT 43 | tail -f {{ $events_pipe }} | /usr/scripts/falco-customrules-events-sender.sh & 44 | # run falcoctl as subprocess, redirect its output to falcoctl-artifact-installed-processor.sh; 45 | # certain falcoctl parameters are hardcoded and not exposes through helm chart. 46 | # Instead they are injected as arguments; 47 | {{- if .Values.cloudOne.runtimeSecurity.customRules.ociRepository.basicAuthTokenSecretName }} 48 | FALCOCTL_REGISTRY_AUTH_BASIC=${FALCOCTL_REGISTRY_AUTH_BASIC} \ 49 | {{- end }} 50 | /usr/bin/falcoctl --config /etc/falcoctl-config-volume/falcoctl.yaml \ 51 | artifact \ 52 | follow \ 53 | --falco-versions "http://127.0.0.1:{{- .Values.scout.falco.falcoctl.web_server_port -}}/versions" \ 54 | --rulesfiles-dir {{ $.Values.scout.falco.ociRepository.artifacts_dir | quote }} \ 55 | --log-format json \ 56 | --log-level trace \ 57 | 2>&1 | tee >(/usr/scripts/falcoctl-artifact-installed-processor.sh {{ $events_pipe }}) & 58 | {{- end }} 59 | /usr/bin/falco \ 60 | -c /etc/falco/falco-customrules.yaml \ 61 | {{- range regexSplit "\n" (include "containerRuntime.sock.falco.args" .Values.scout.falco ) -1 }} 62 | {{- $v := (. | nospace | trimPrefix "-") -}} 63 | {{- if $v }} 64 | {{ $v }} \ 65 | {{- end }} 66 | {{- end }} 67 | -v \ 68 | -p \ 69 | container.id=%container.id \ 70 | container.image.digest=%container.image.digest \ 71 | container.image.repository=%container.image.repository \ 72 | container.image.tag=%container.image.tag \ 73 | container.name=%container.name \ 74 | evt.arg.filename=%evt.arg.filename \ 75 | evt.arg.mode=%evt.arg.mode \ 76 | evt.arg.name=%evt.arg.name \ 77 | evt.category=%evt.category \ 78 | evt.num=%evt.num \ 79 | evt.rawtime=%evt.rawtime \ 80 | evt.type=%evt.type \ 81 | k8s.ns.name=%k8s.ns.name \ 82 | k8s.pod.id=%k8s.pod.id \ 83 | k8s.pod.labels=%k8s.pod.labels \ 84 | k8s.pod.name=%k8s.pod.name \ 85 | proc.args=%proc.args \ 86 | proc.cmdline=%proc.cmdline \ 87 | proc.exe=%proc.exe \ 88 | proc.exeline=%proc.exeline \ 89 | proc.name=%proc.name \ 90 | proc.pcmdline=%proc.pcmdline \ 91 | proc.pid=%proc.pid \ 92 | proc.pname=%proc.pname \ 93 | proc.ppid=%proc.ppid \ 94 | user.loginuid=%user.loginuid \ 95 | user.name=%user.name \ 96 | -o \ 97 | stdout_output.enabled={{ default "false" .Values.scout.falco.stdout_enabled }} \ 98 | -o \ 99 | syslog_output.enabled={{ default "false" .Values.scout.falco.syslog_enabled }} \ 100 | {{- if .Values.scout.falco.extraArgs }}{{ join " \\" .Values.scout.falco.extraArgs }}{{- end }}{{/* if */}} 101 | {{- if .Values.cloudOne.runtimeSecurity.customRules.ociRepository.enabled }} 102 | 2>&1 \ 103 | | tee >(/usr/scripts/falco-customrules-falcoctl-rules-applied-processor.sh {{ $events_pipe }}) 104 | {{- end }} 105 | #kill $sender_pid 106 | {{- end }} 107 | -------------------------------------------------------------------------------- /templates/scout/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq (include "scout.shouldDeploy" .) "true" }} 2 | --- 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: {{ template "container.security.name" . }}-scout-config 7 | labels: {{- include "scout.labels" . | nindent 4 }} 8 | data: 9 | default_rules.yaml: | 10 | - rule: Dummy rule 11 | desc: A dummy rule 12 | condition: evt.type = setuid and (evt.num=0) 13 | output: none 14 | priority: NOTICE 15 | {{ (.Files.Glob "config/falco.yaml").AsConfig | indent 2 }} 16 | {{- if .Values.scout.falco.config }} 17 | {{ toYaml .Values.scout.falco.config | indent 4 }} 18 | {{- end }} 19 | {{- include "falco.sanitier.ouput" . | indent 4 }} 20 | {{- if .Values.cloudOne.runtimeSecurity.customRules.enabled }} 21 | {{ (.Files.Glob "config/falco-customrules.yaml").AsConfig | indent 2 }} 22 | rules_files: 23 | - /etc/falco/default_rules.yaml 24 | - /etc/falco/rules.d 25 | {{- if .Values.cloudOne.runtimeSecurity.customRules.ociRepository.enabled }} 26 | {{- range .Values.cloudOne.runtimeSecurity.customRules.ociRepository.ruleFiles }} 27 | - {{ $.Values.scout.falco.ociRepository.artifacts_dir }}/{{- . -}} 28 | {{- end }} 29 | {{- end }} 30 | json_output: {{.Values.cloudOne.runtimeSecurity.customRules.output.json}} 31 | {{ if .Values.cloudOne.runtimeSecurity.customRules.output.splunk.url }} 32 | http_output: 33 | enabled: true 34 | url: {{ .Values.cloudOne.runtimeSecurity.customRules.output.splunk.url }} 35 | {{ if .Values.cloudOne.runtimeSecurity.customRules.output.splunk.headers }} 36 | custom_headers: 37 | {{- range .Values.cloudOne.runtimeSecurity.customRules.output.splunk.headers}} 38 | {{- if contains "Authorization:" . }} 39 | {{- if $.Values.cloudOne.runtimeSecurity.customRules.output.splunk.hecTokenSecretName -}} 40 | {{- fail "customRules.output.splunk.hecTokenSecretName automatically adds Splunk HEC auth header, no other Authorization headers allowed" -}} 41 | {{- end}}{{- end}} 42 | - "{{ . }}" 43 | {{- end }} 44 | {{- if $.Values.cloudOne.runtimeSecurity.customRules.output.splunk.hecTokenSecretName }} 45 | - "Authorization: Splunk ${SPLUNK_HEC_TOKEN}" 46 | {{- end }} 47 | {{- end }} 48 | ca_path: "/etc/ssl/certs" 49 | ca_cert: "/etc/ssl/certs/ca-certificates.crt" 50 | {{- end }} 51 | {{- if .Values.cloudOne.runtimeSecurity.customRules.ociRepository.enabled }} 52 | # falcoctl queries version via http 53 | webserver: 54 | enabled: true 55 | # When the `threadiness` value is set to 0, Falco will automatically determine 56 | # the appropriate number of threads based on the number of online cores in the system. 57 | threadiness: 0 58 | listen_port: {{ .Values.scout.falco.falcoctl.web_server_port }} 59 | # faloctl runs in the same container, localhost is fine 60 | # connections from other hosts are not accepted 61 | listen_address: 127.0.0.1 62 | k8s_healthz_endpoint: /healthz 63 | # [Incubating] `prometheus_metrics_enabled` 64 | # 65 | # Enable the metrics endpoint providing Prometheus values 66 | # It will only have an effect if metrics.enabled is set to true as well. 67 | prometheus_metrics_enabled: false 68 | ssl_enabled: false 69 | ssl_certificate: /etc/falco/falco.pem 70 | # rulesfiles may be updated by falcoctl 71 | watch_config_files: true 72 | # logs are monitored, need debug level to determine falco state properly 73 | log_level: {{ .Values.scout.falco.ociRepository.logLevel | quote }} 74 | {{ else }} 75 | # no changes to rulesfiles are expected 76 | watch_config_files: false 77 | # logs just informational 78 | log_level: {{ .Values.scout.falco.logLevel | quote }} 79 | {{ end }} 80 | {{- include "falco.sanitier.ouput" . | indent 4 }} 81 | {{- end }} 82 | --- 83 | {{- if .Values.cloudOne.runtimeSecurity.customRules.enabled }} 84 | apiVersion: v1 85 | kind: ConfigMap 86 | metadata: 87 | name: {{ template "container.security.name" . }}-customrules 88 | labels: 89 | {{- include "scout.labels" . | nindent 4 }} 90 | data: 91 | {{ (tpl (.Files.Glob "config/customrules/*.{yaml,yml}").AsConfig .) | indent 2 }} 92 | {{- end }} 93 | {{- end }} 94 | -------------------------------------------------------------------------------- /templates/scout/securitycontextconstraints.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq (include "scout.shouldDeploy" .) "true" }} 2 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 3 | apiVersion: security.openshift.io/v1 4 | kind: SecurityContextConstraints 5 | metadata: 6 | annotations: 7 | kubernetes.io/description: | 8 | This provides the minimum requirements in Openshift. 9 | name: {{ template "container.security.name" . }}-scout 10 | namespace: {{ .Release.Namespace }} 11 | labels: 12 | {{- include "container.security.labels" . | nindent 4 }} 13 | allowHostDirVolumePlugin: true 14 | allowHostIPC: false 15 | allowHostNetwork: true 16 | allowHostPID: true 17 | allowHostPorts: false 18 | allowPrivilegeEscalation: true 19 | allowPrivilegedContainer: true 20 | allowedCapabilities: [SYS_PTRACE, SYS_ADMIN, SYS_RESOURCE, DAC_READ_SEARCH] 21 | allowedUnsafeSysctls: [] 22 | defaultAddCapabilities: [] 23 | fsGroup: 24 | type: RunAsAny 25 | groups: [] 26 | priority: 0 27 | readOnlyRootFilesystem: false 28 | requiredDropCapabilities: [] 29 | runAsUser: 30 | type: RunAsAny 31 | seLinuxContext: 32 | type: RunAsAny 33 | seccompProfiles: 34 | - '*' 35 | supplementalGroups: 36 | type: RunAsAny 37 | users: 38 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "scout.serviceAccountName" . }} 39 | volumes: 40 | - hostPath 41 | - emptyDir 42 | - secret 43 | - configMap 44 | {{- end }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /templates/scout/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq (include "scout.shouldDeploy" .) "true" }} 2 | {{- if .Values.serviceAccount.create }} 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: {{ include "scout.serviceAccountName" . }} 7 | labels: 8 | {{- include "scout.labels" . | nindent 4 }} 9 | {{- with .Values.serviceAccount.scout.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end }} 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /templates/securitycontextconstraints.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.securityContextConstraints.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 2 | apiVersion: security.openshift.io/v1 3 | kind: SecurityContextConstraints 4 | metadata: 5 | annotations: 6 | kubernetes.io/description: | 7 | This SCC provides least-privilege requirement to run Trend Micro Cloud One Container Security in Openshift. 8 | name: {{ template "container.security.name" . }}-default 9 | namespace: {{ .Release.Namespace }} 10 | labels: 11 | {{- include "container.security.labels" . | nindent 4 }} 12 | allowHostDirVolumePlugin: false 13 | allowHostIPC: false 14 | allowHostNetwork: false 15 | allowHostPID: false 16 | allowHostPorts: false 17 | allowPrivilegeEscalation: false 18 | allowPrivilegedContainer: false 19 | allowedCapabilities: [] 20 | allowedUnsafeSysctls: [] 21 | defaultAddCapabilities: [] 22 | fsGroup: 23 | type: MustRunAs 24 | groups: [] 25 | priority: 0 26 | readOnlyRootFilesystem: true 27 | requiredDropCapabilities: [] 28 | runAsUser: 29 | type: MustRunAsNonRoot 30 | seLinuxContext: 31 | type: MustRunAs 32 | supplementalGroups: 33 | type: RunAsAny 34 | seccompProfiles: 35 | - '*' 36 | users: 37 | - system:serviceaccount:{{ .Release.Namespace }}:default 38 | {{ if .Values.serviceAccount.create }} 39 | {{- if eq true .Values.cloudOne.admissionController.enabled }} 40 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "admissionController.serviceAccountName" . }} 41 | {{- end }} 42 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "usage.serviceAccountName" . }} 43 | {{- if or (or (eq true .Values.cloudOne.vulnerabilityScanning.enabled) (eq true .Values.cloudOne.malwareScanning.enabled)) (eq true .Values.cloudOne.inventoryCollection.enabled) }} 44 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "workloadOperator.serviceAccountName" . }} 45 | {{- end }} 46 | {{- if (or (eq true .Values.cloudOne.vulnerabilityScanning.enabled) (eq true .Values.cloudOne.malwareScanning.enabled)) }} 47 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "scanManager.serviceAccountName" . }} 48 | {{- end }} 49 | {{- if or (eq true .Values.cloudOne.runtimeSecurity.enabled) (eq true .Values.cloudOne.malwareScanning.enabled) }} 50 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "k8sMetaCollector.serviceAccountName" . }} 51 | {{- end }} 52 | - system:serviceaccount:{{ .Release.Namespace }}:{{ include "policyOperator.serviceAccountName" . }} 53 | {{- end }} 54 | volumes: 55 | - configMap 56 | - downwardAPI 57 | - emptyDir 58 | - secret 59 | - projected 60 | {{- end }} 61 | -------------------------------------------------------------------------------- /templates/telemetry.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ template "container.security.fullname" . }}-telemetry 5 | labels: 6 | {{- include "container.security.labels" . | nindent 4 }} 7 | type: Opaque 8 | data: 9 | apiKey: {{ default "" .Values.telemetry.apiKey | b64enc | quote }} 10 | publicKey: {{ default "" .Values.telemetry.publicKey | b64enc | quote }} 11 | -------------------------------------------------------------------------------- /templates/usage-controller-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | name: usage-leader-election-role 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "usage.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: 10 | - "" 11 | resources: 12 | - configmaps 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - coordination.k8s.io 23 | resources: 24 | - leases 25 | verbs: 26 | - get 27 | - list 28 | - watch 29 | - create 30 | - update 31 | - patch 32 | - delete 33 | - apiGroups: 34 | - "" 35 | resources: 36 | - events 37 | verbs: 38 | - create 39 | - patch 40 | --- 41 | apiVersion: rbac.authorization.k8s.io/v1 42 | kind: ClusterRole 43 | metadata: 44 | creationTimestamp: null 45 | name: usage-manager-role 46 | labels: 47 | {{- include "usage.labels" . | nindent 4 }} 48 | rules: 49 | - apiGroups: 50 | - cloudone.trendmicro.com 51 | resources: 52 | - usages 53 | verbs: 54 | - create 55 | - delete 56 | - get 57 | - list 58 | - patch 59 | - update 60 | - watch 61 | - apiGroups: 62 | - cloudone.trendmicro.com 63 | resources: 64 | - usages/finalizers 65 | verbs: 66 | - update 67 | - apiGroups: 68 | - cloudone.trendmicro.com 69 | resources: 70 | - usages/status 71 | verbs: 72 | - get 73 | - patch 74 | - update 75 | - apiGroups: 76 | - "" 77 | resources: 78 | - nodes 79 | verbs: 80 | - get 81 | - list 82 | - watch 83 | - apiGroups: 84 | - "" 85 | resources: 86 | - nodes/status 87 | verbs: 88 | - get 89 | - apiGroups: 90 | - "" 91 | resources: 92 | - pods 93 | verbs: 94 | - get 95 | - list 96 | - watch 97 | - apiGroups: 98 | - "" 99 | resources: 100 | - pods/status 101 | verbs: 102 | - get 103 | 104 | --- 105 | apiVersion: rbac.authorization.k8s.io/v1 106 | kind: ClusterRole 107 | metadata: 108 | name: usage-proxy-role 109 | labels: 110 | {{- include "usage.labels" . | nindent 4 }} 111 | rules: 112 | - apiGroups: 113 | - authentication.k8s.io 114 | resources: 115 | - tokenreviews 116 | verbs: 117 | - create 118 | - apiGroups: 119 | - authorization.k8s.io 120 | resources: 121 | - subjectaccessreviews 122 | verbs: 123 | - create 124 | 125 | --- 126 | apiVersion: rbac.authorization.k8s.io/v1 127 | kind: RoleBinding 128 | metadata: 129 | name: usage-leader-election-rolebinding 130 | namespace: {{ .Release.Namespace }} 131 | labels: 132 | {{- include "usage.labels" . | nindent 4 }} 133 | roleRef: 134 | apiGroup: rbac.authorization.k8s.io 135 | kind: Role 136 | name: usage-leader-election-role 137 | subjects: 138 | - kind: ServiceAccount 139 | name: {{ include "usage.serviceAccountName" . }} 140 | namespace: {{ .Release.Namespace }} 141 | 142 | --- 143 | apiVersion: rbac.authorization.k8s.io/v1 144 | kind: ClusterRoleBinding 145 | metadata: 146 | name: usage-manager-rolebinding 147 | labels: 148 | {{- include "usage.labels" . | nindent 4 }} 149 | roleRef: 150 | apiGroup: rbac.authorization.k8s.io 151 | kind: ClusterRole 152 | name: usage-manager-role 153 | subjects: 154 | - kind: ServiceAccount 155 | name: {{ include "usage.serviceAccountName" . }} 156 | namespace: {{ .Release.Namespace }} 157 | 158 | --- 159 | apiVersion: rbac.authorization.k8s.io/v1 160 | kind: ClusterRoleBinding 161 | metadata: 162 | name: usage-proxy-rolebinding 163 | labels: 164 | {{- include "usage.labels" . | nindent 4 }} 165 | roleRef: 166 | apiGroup: rbac.authorization.k8s.io 167 | kind: ClusterRole 168 | name: usage-proxy-role 169 | subjects: 170 | - kind: ServiceAccount 171 | name: {{ include "usage.serviceAccountName" . }} 172 | namespace: {{ .Release.Namespace }} 173 | -------------------------------------------------------------------------------- /templates/usage-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | {{- include "usage.labels" . | nindent 4 }} 6 | name: trendmicro-usage-controller 7 | namespace: {{ .Release.Namespace }} 8 | spec: 9 | replicas: {{ default 1 .Values.replicas.usage }} 10 | selector: 11 | matchLabels: 12 | {{- include "usage.selectorLabels" . | nindent 6 }} 13 | template: 14 | metadata: 15 | annotations: 16 | checksum/auth: {{ include "container.security.auth.secret" . | sha256sum }} 17 | checksum/cert: {{ include (print $.Template.BasePath "/kube-rbac-proxy-cert.yaml") . | sha256sum }} 18 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.usage) }} 19 | {{- toYaml . | nindent 8 }} 20 | {{- end }} 21 | labels: 22 | {{- include "usage.labels" . | nindent 8 }} 23 | spec: 24 | serviceAccountName: {{ include "usage.serviceAccountName" . }} 25 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 26 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.usage }} 27 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 28 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container.usage }} 29 | {{- if $securityContextEnabled }} 30 | securityContext: 31 | {{ toYaml $podSecurityContext | indent 8 }} 32 | {{- end }} 33 | {{- $imageDefaults := .Values.images.defaults }} 34 | {{- with .Values.images.usage }} 35 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 36 | {{- if not (eq "" $secret) }} 37 | imagePullSecrets: 38 | - name: {{ $secret | quote }} 39 | {{- end }} 40 | containers: 41 | - name: controller-manager 42 | {{- if $securityContextEnabled }} 43 | securityContext: 44 | {{ toYaml $containerSecurityContext | indent 12 }} 45 | {{- end }} 46 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 47 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 48 | {{- $tag := (default $imageDefaults.tag .tag) }} 49 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 50 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 51 | {{- end }} 52 | args: 53 | - --health-probe-bind-address=:8081 54 | - --metrics-bind-address=127.0.0.1:8080 55 | - --exclude-kubernetes-service-host-from-proxy={{ default "false" .Values.proxy.excludeKubernetesServiceHost }} 56 | {{- if gt (int .Values.replicas.usage) 1 }} 57 | - --leader-elect 58 | {{- end }} 59 | - --cloud-one-endpoint={{ include "container.security.endpoint" . }} 60 | - --application-version={{ .Chart.AppVersion }} 61 | command: 62 | - /manager 63 | env: 64 | {{- include "container.security.proxy.env" . | nindent 8 }} 65 | - name: NAMESPACE 66 | valueFrom: 67 | fieldRef: 68 | fieldPath: metadata.namespace 69 | livenessProbe: 70 | httpGet: 71 | path: /healthz 72 | port: 8081 73 | initialDelaySeconds: 15 74 | periodSeconds: 20 75 | readinessProbe: 76 | httpGet: 77 | path: /readyz 78 | port: 8081 79 | initialDelaySeconds: 5 80 | periodSeconds: 10 81 | volumeMounts: 82 | - mountPath: /secrets 83 | name: api-key 84 | {{- include "proxy.selfSignedCertificates.volumeMounts" . | nindent 10 }} 85 | resources: 86 | {{ toYaml (default .Values.resources.defaults .Values.resources.usage) | indent 12 }} 87 | - {{ include "rbacProxy" (dict "securityContext" .Values.securityContext "images" .Values.images "resources" .Values.resources "customSecurityContext" .Values.securityContext.usage "tlsConfig" .Values.tlsConfig ) | nindent 8 | trim }} 88 | volumes: 89 | - name: api-key 90 | secret: 91 | secretName: {{ template "container.security.fullname" . }}-auth 92 | - name: rbac-proxy-certs 93 | secret: 94 | secretName: {{ template "kubeRbacProxy.fullname" . }}-tls-certificate 95 | {{- include "proxy.selfSignedCertificates.volumes" . | nindent 8 }} 96 | terminationGracePeriodSeconds: 10 97 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.usage }} 98 | nodeSelector: 99 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.usage) | indent 8 }} 100 | {{- end }} 101 | {{- if or .Values.tolerations.defaults .Values.tolerations.usage }} 102 | tolerations: 103 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.usage) | indent 8 }} 104 | {{- end }} 105 | {{- if or .Values.affinity.defaults .Values.affinity.usage }} 106 | affinity: 107 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.usage) | indent 8 }} 108 | {{- end }} 109 | {{- $classname := (default (default "" .Values.priorityClassName.default ) .Values.priorityClassName.usage) }} 110 | {{- if not (eq "" $classname) }} 111 | priorityClassName: "{{ $classname }}" 112 | {{- end }} 113 | restartPolicy: Always 114 | 115 | --- 116 | apiVersion: v1 117 | kind: Service 118 | metadata: 119 | labels: 120 | {{- include "usage.labels" . | nindent 4 }} 121 | name: trendmicro-usage-controller-metrics-service 122 | namespace: {{ .Release.Namespace }} 123 | spec: 124 | ports: 125 | - name: https 126 | port: 8443 127 | targetPort: https 128 | selector: 129 | {{- include "usage.selectorLabels" . | nindent 4 }} 130 | 131 | {{ if .Values.networkPolicy.enabled }} 132 | --- 133 | apiVersion: networking.k8s.io/v1 134 | kind: NetworkPolicy 135 | metadata: 136 | name: usage-controller-networkpolicy 137 | namespace: {{ .Release.Namespace }} 138 | labels: 139 | {{- include "usage.labels" . | nindent 4 }} 140 | spec: 141 | podSelector: 142 | matchLabels: 143 | {{- include "usage.selectorLabels" . | nindent 6 }} 144 | policyTypes: 145 | - Ingress 146 | ingress: 147 | - from: # any -- this is for metrics 148 | ports: 149 | - protocol: TCP 150 | port: 8443 151 | - from: # any -- this should just be kubelet for health probes 152 | ports: 153 | - protocol: TCP 154 | port: 8081 155 | {{- end }} 156 | 157 | {{ if .Values.serviceAccount.create }} 158 | --- 159 | apiVersion: v1 160 | kind: ServiceAccount 161 | metadata: 162 | name: {{ include "usage.serviceAccountName" . }} 163 | labels: 164 | {{- include "usage.labels" . | nindent 4 }} 165 | {{- with .Values.serviceAccount.usage.annotations }} 166 | annotations: 167 | {{- toYaml . | nindent 4 }} 168 | {{- end }} 169 | {{- end }} 170 | -------------------------------------------------------------------------------- /templates/usage.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cloudone.trendmicro.com/v1 2 | kind: Usage 3 | metadata: 4 | name: {{ template "usage.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "usage.labels" . | nindent 4 }} 8 | -------------------------------------------------------------------------------- /templates/validatingwebhook.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq true .Values.cloudOne.admissionController.enabled }} 2 | {{- $cn := printf "%s.%s.svc" "trendmicro-admission-controller" .Release.Namespace }} 3 | {{- $ca := genCA (printf "%s-ca" "trendmicro-admission-controller") (default 3650 (int .Values.cloudOne.admissionController.certificate.lifetime)) -}} 4 | {{- $cert := genSignedCert (default $cn .Values.cloudOne.admissionController.certificate.commonName) (default nil .Values.cloudOne.admissionController.certificate.ipAlternativeNames) (default (list $cn) .Values.cloudOne.admissionController.certificate.dnsAlternativeNames) (default 3650 (int .Values.cloudOne.admissionController.certificate.lifetime)) $ca -}} 5 | 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: {{ template "admissionController.fullname" . }}-tls-certificate 10 | namespace: {{ .Release.Namespace }} 11 | labels: 12 | {{- include "admissionController.labels" . | nindent 4 }} 13 | type: Opaque 14 | data: 15 | key.pem: {{ $cert.Key | b64enc | quote }} 16 | cert.pem: {{ $cert.Cert | b64enc | quote }} 17 | 18 | --- 19 | apiVersion: admissionregistration.k8s.io/v1 20 | kind: ValidatingWebhookConfiguration 21 | metadata: 22 | name: {{ include "admissionController.fullname" . }} 23 | namespace: {{ .Release.Namespace }} 24 | labels: 25 | {{- include "admissionController.labels" . | nindent 4 }} 26 | webhooks: 27 | - name: {{ default $cn .Values.cloudOne.admissionController.certificate.commonName }} 28 | namespaceSelector: 29 | matchExpressions: 30 | {{- $excludedNamespaces := (include "namespaceExclusions" .) | splitList "," }} 31 | {{- if $excludedNamespaces }} 32 | - key: kubernetes.io/metadata.name 33 | operator: NotIn 34 | values: 35 | {{- range $excludedNamespace := $excludedNamespaces }} 36 | - {{ quote $excludedNamespace }} 37 | {{- end }} 38 | {{- end }} 39 | {{- range $k, $v := (required "A validationNamespaceSelector is required" .Values.cloudOne.admissionController.validationNamespaceSelector) }} 40 | {{- range $match := $v }} 41 | - 42 | {{- range $key, $val := $match }} 43 | {{- if eq $key "values" }} 44 | values: 45 | {{- range $val }} 46 | - {{ quote . }} 47 | {{- end }} 48 | {{- else }} 49 | {{ $key }}: {{ quote $val }} 50 | {{- end }} 51 | {{- end }} 52 | {{- end }} 53 | {{- end }} 54 | rules: 55 | - apiGroups: 56 | - '*' 57 | apiVersions: 58 | - '*' 59 | operations: 60 | - '*' 61 | resources: 62 | - "pods" 63 | - "pods/exec" 64 | - "pods/portforward" 65 | - "pods/attach" 66 | - "pods/ephemeralcontainers" 67 | - "replicasets" 68 | - "replicationcontrollers" 69 | - "deployments" 70 | - "statefulsets" 71 | - "daemonsets" 72 | - "jobs" 73 | - "cronjobs" 74 | scope: "Namespaced" 75 | failurePolicy: {{ required "A valid failure policy is required!" .Values.cloudOne.admissionController.failurePolicy }} 76 | clientConfig: 77 | service: 78 | name: trendmicro-admission-controller 79 | namespace: {{ .Release.Namespace }} 80 | path: "/api/validate" 81 | caBundle: {{ $ca.Cert | b64enc | quote }} 82 | admissionReviewVersions: ["v1", "v1beta1"] 83 | sideEffects: None 84 | timeoutSeconds: {{ default 30 .Values.cloudOne.admissionController.webhookTimeoutSeconds }} 85 | {{- end }} 86 | -------------------------------------------------------------------------------- /templates/workload-operator-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.vulnerabilityScanning.enabled) (eq true .Values.cloudOne.inventoryCollection.enabled) }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: workload-operator-role 7 | labels: 8 | {{- include "workloadOperator.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - batch 12 | - "" 13 | - apps 14 | - networking.k8s.io 15 | resources: 16 | - cronjobs 17 | - jobs 18 | - pods 19 | - replicationcontrollers 20 | - replicasets 21 | - daemonsets 22 | - statefulsets 23 | - deployments 24 | - nodes 25 | - services 26 | - ingresses 27 | verbs: 28 | - get 29 | - list 30 | - watch 31 | - apiGroups: 32 | - cloudone.trendmicro.com 33 | resources: 34 | - workloadimages 35 | verbs: 36 | - get 37 | - list 38 | - watch 39 | - create 40 | - update 41 | - patch 42 | - delete 43 | - apiGroups: 44 | - coordination.k8s.io 45 | resources: 46 | - leases 47 | verbs: 48 | - get 49 | - list 50 | - watch 51 | - create 52 | - update 53 | - patch 54 | - delete 55 | - apiGroups: 56 | - "" 57 | resources: 58 | - events 59 | verbs: 60 | - create 61 | - patch 62 | --- 63 | apiVersion: rbac.authorization.k8s.io/v1 64 | kind: ClusterRoleBinding 65 | metadata: 66 | name: workload-operator-rolebinding 67 | labels: 68 | {{- include "workloadOperator.labels" . | nindent 4 }} 69 | roleRef: 70 | apiGroup: rbac.authorization.k8s.io 71 | kind: ClusterRole 72 | name: workload-operator-role 73 | subjects: 74 | - kind: ServiceAccount 75 | name: {{ include "workloadOperator.serviceAccountName" . }} 76 | namespace: {{ .Release.Namespace }} 77 | --- 78 | apiVersion: rbac.authorization.k8s.io/v1 79 | kind: ClusterRole 80 | metadata: 81 | creationTimestamp: null 82 | name: workload-images-remover-role 83 | labels: 84 | {{- include "workloadOperator.labels" . | nindent 4 }} 85 | annotations: 86 | helm.sh/hook: post-delete 87 | helm.sh/hook-delete-policy: hook-succeeded,hook-failed,before-hook-creation 88 | helm.sh/hook-weight: "-9" 89 | rules: 90 | - apiGroups: 91 | - apiextensions.k8s.io 92 | resources: 93 | - customresourcedefinitions 94 | resourceNames: 95 | - workloadimages.cloudone.trendmicro.com 96 | verbs: 97 | - delete 98 | --- 99 | apiVersion: rbac.authorization.k8s.io/v1 100 | kind: ClusterRoleBinding 101 | metadata: 102 | name: workload-images-remover-rolebinding 103 | labels: 104 | {{- include "workloadOperator.labels" . | nindent 4 }} 105 | annotations: 106 | helm.sh/hook: post-delete 107 | helm.sh/hook-delete-policy: hook-succeeded,hook-failed,before-hook-creation 108 | helm.sh/hook-weight: "-8" 109 | roleRef: 110 | apiGroup: rbac.authorization.k8s.io 111 | kind: ClusterRole 112 | name: workload-images-remover-role 113 | subjects: 114 | - kind: ServiceAccount 115 | name: workload-images-remover-service-account 116 | namespace: {{ .Release.Namespace }} 117 | {{- end }} 118 | -------------------------------------------------------------------------------- /templates/workload-operator.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (eq true .Values.cloudOne.vulnerabilityScanning.enabled) (eq true .Values.cloudOne.inventoryCollection.enabled) }} 2 | {{ if .Values.serviceAccount.create }} 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: {{ include "workloadOperator.serviceAccountName" . }} 7 | labels: 8 | {{- include "workloadOperator.labels" . | nindent 4 }} 9 | {{- with .Values.serviceAccount.workloadOperator.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end }} 14 | 15 | --- 16 | apiVersion: apps/v1 17 | kind: Deployment 18 | metadata: 19 | name: trendmicro-workload-operator 20 | namespace: {{ .Release.Namespace }} 21 | labels: 22 | {{- include "workloadOperator.labels" . | nindent 4 }} 23 | spec: 24 | replicas: {{ default 1 .Values.replicas.workloadOperator }} 25 | selector: 26 | matchLabels: 27 | {{- include "workloadOperator.selectorLabels" . | nindent 6 }} 28 | template: 29 | metadata: 30 | annotations: 31 | checksum/auth: {{ include "container.security.auth.secret" . | sha256sum }} 32 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.workloadOperator) }} 33 | {{- toYaml . | nindent 8 }} 34 | {{- end }} 35 | labels: 36 | {{- include "workloadOperator.labels" . | nindent 8 }} 37 | spec: 38 | serviceAccountName: {{ include "workloadOperator.serviceAccountName" . }} 39 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 40 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.workloadOperator }} 41 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 42 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container.workloadOperator }} 43 | {{- if $securityContextEnabled }} 44 | securityContext: 45 | {{ toYaml $podSecurityContext | indent 8 }} 46 | {{- end }} 47 | {{- $imageDefaults := .Values.images.defaults }} 48 | {{- with .Values.images.workloadOperator }} 49 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 50 | {{- if not (eq "" $secret) }} 51 | imagePullSecrets: 52 | - name: {{ $secret | quote }} 53 | {{- end }} 54 | containers: 55 | - name: trendmicro-workload-operator 56 | {{- if $securityContextEnabled }} 57 | securityContext: 58 | {{ toYaml $containerSecurityContext | indent 12 }} 59 | {{- end }} 60 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 61 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 62 | {{- $tag := (default $imageDefaults.tag .tag) }} 63 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 64 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 65 | {{- end }} 66 | args: 67 | - --zap-devel={{ default "false" .Values.logConfig.devel }} 68 | - --zap-log-level={{ include "logLevel" (list .Values.cloudOne.workloadOperator.logLevel .) }} 69 | - --zap-encoder={{ default "json" .Values.logConfig.encoder }} 70 | - --zap-stacktrace-level={{ default "error" .Values.logConfig.stacktraceLevel }} 71 | - --zap-time-encoding={{ default "rfc3339" .Values.logConfig.timeEncoding }} 72 | - --cloud-one-endpoint={{ include "container.security.endpoint" . }} 73 | - --excluded-namespaces 74 | {{- $excludeNS := (include "namespaceExclusions" .) }} 75 | - {{ $excludeNS | quote }} 76 | - --workload-controller-instance-name={{ .Release.Name }} 77 | - --rescan-interval 78 | - 30m 79 | - --exclude-kubernetes-service-host-from-proxy={{ default "false" .Values.proxy.excludeKubernetesServiceHost }} 80 | - --vulnerability-scanning={{ default "false" .Values.cloudOne.vulnerabilityScanning.enabled }} 81 | - --inventory-collection={{ default "false" .Values.cloudOne.inventoryCollection.enabled }} 82 | - --inventory-collection-period={{ default "5m" .Values.cloudOne.inventoryCollection.period }} 83 | - --chart-version={{ default "unknown" .Chart.AppVersion }} 84 | - --runtime-security={{ default "false" .Values.cloudOne.runtimeSecurity.enabled }} 85 | - --malware-scanning={{ default "false" .Values.cloudOne.malwareScanning.enabled }} 86 | - --secret-scanning={{ default "false" .Values.cloudOne.secretScanning.enabled }} 87 | - --trusted-images={{ include "digest" . }} 88 | {{- if gt (int .Values.replicas.workloadOperator) 1 }} 89 | - --leader-elect 90 | {{- end }} 91 | command: 92 | - /app/workload-operator 93 | env: 94 | - name: NAMESPACE 95 | valueFrom: 96 | fieldRef: 97 | fieldPath: metadata.namespace 98 | - name: CREATION_TIMESTAMP 99 | value: "{{ now.Unix }}" 100 | {{- include "container.security.proxy.env" . | nindent 8 }} 101 | volumeMounts: 102 | - mountPath: /secrets 103 | name: api-key 104 | {{- include "proxy.selfSignedCertificates.volumeMounts" . | nindent 10 }} 105 | resources: 106 | {{ toYaml (default .Values.resources.defaults .Values.resources.workloadOperator) | indent 12 }} 107 | volumes: 108 | - name: api-key 109 | secret: 110 | secretName: {{ template "container.security.fullname" . }}-auth 111 | {{- include "proxy.selfSignedCertificates.volumes" . | nindent 8 }} 112 | terminationGracePeriodSeconds: 10 113 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.workloadOperator }} 114 | nodeSelector: 115 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.workloadOperator) | indent 8 }} 116 | {{- end }} 117 | {{- if or .Values.tolerations.defaults .Values.tolerations.workloadOperator }} 118 | tolerations: 119 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.workloadOperator) | indent 8 }} 120 | {{- end }} 121 | {{- if or .Values.affinity.defaults .Values.affinity.workloadOperator }} 122 | affinity: 123 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.workloadOperator) | indent 8 }} 124 | {{- end }} 125 | {{- $classname := (default (default "" .Values.priorityClassName.default ) .Values.priorityClassName.workloadOperator) }} 126 | {{- if not (eq "" $classname) }} 127 | priorityClassName: "{{ $classname }}" 128 | {{- end }} 129 | restartPolicy: Always 130 | --- 131 | apiVersion: v1 132 | kind: ServiceAccount 133 | metadata: 134 | name: workload-images-remover-service-account 135 | labels: 136 | {{- include "workloadOperator.labels" . | nindent 4 }} 137 | annotations: 138 | helm.sh/hook: post-delete 139 | helm.sh/hook-delete-policy: hook-succeeded,hook-failed,before-hook-creation 140 | helm.sh/hook-weight: "-10" 141 | --- 142 | apiVersion: batch/v1 143 | kind: Job 144 | metadata: 145 | name: trendmicro-workload-images-remover 146 | namespace: {{ .Release.Namespace }} 147 | labels: 148 | {{- include "workloadOperator.labels" . | nindent 4 }} 149 | annotations: 150 | helm.sh/hook: post-delete 151 | helm.sh/hook-delete-policy: hook-succeeded,hook-failed 152 | spec: 153 | backoffLimit: 2 154 | activeDeadlineSeconds: 90 155 | ttlSecondsAfterFinished: 60 156 | template: 157 | metadata: 158 | annotations: 159 | {{- with (default .Values.podAnnotations.defaults .Values.podAnnotations.workloadOperator) }} 160 | {{- toYaml . | nindent 8 }} 161 | {{- end }} 162 | labels: 163 | {{- include "workloadOperator.labels" . | nindent 8 }} 164 | spec: 165 | serviceAccountName: workload-images-remover-service-account 166 | {{- $securityContextEnabled := .Values.securityContext.enabled }} 167 | {{- $securityContext := default .Values.securityContext.default .Values.securityContext.workloadOperator }} 168 | {{- $podSecurityContext := default .Values.securityContext.default.pod $securityContext.pod }} 169 | {{- $containerSecurityContext := default .Values.securityContext.default.container $securityContext.container.workloadOperator }} 170 | {{- if $securityContextEnabled }} 171 | securityContext: 172 | runAsNonRoot: true 173 | seccompProfile: 174 | type: RuntimeDefault 175 | {{- end }} 176 | {{- $imageDefaults := .Values.images.defaults }} 177 | {{- with .Values.images.workloadOperator }} 178 | {{- $secret := (default (default "" $imageDefaults.imagePullSecret) .imagePullSecret) }} 179 | {{- if not (eq "" $secret) }} 180 | imagePullSecrets: 181 | - name: {{ $secret | quote }} 182 | {{- end }} 183 | restartPolicy: Never 184 | containers: 185 | - name: trendmicro-workload-images-remover 186 | {{- if $securityContextEnabled }} 187 | securityContext: 188 | allowPrivilegeEscalation: false 189 | capabilities: 190 | drop: 191 | - ALL 192 | privileged: false 193 | readOnlyRootFilesystem: true 194 | runAsNonRoot: true 195 | {{- end }} 196 | {{- $project := (default (default "trendmicrocloudone" $imageDefaults.project) .project) }} 197 | {{- $repository := printf "%s/%s" $project (required ".repository is required!" .repository) }} 198 | {{- $tag := (default $imageDefaults.tag .tag) }} 199 | image: {{ include "image.source" (dict "repository" $repository "registry" .registry "tag" $tag "imageDefaults" $imageDefaults "digest" .digest) }} 200 | imagePullPolicy: {{ default (default "Always" $imageDefaults.pullPolicy) .pullPolicy }} 201 | {{- end }} 202 | command: 203 | - /app/workload-operator 204 | args: 205 | - --cleanup-mode 206 | {{- if or .Values.nodeSelector.defaults .Values.nodeSelector.workloadOperator }} 207 | nodeSelector: 208 | {{ toYaml (default .Values.nodeSelector.defaults .Values.nodeSelector.workloadOperator) | indent 8 }} 209 | {{- end }} 210 | {{- if or .Values.tolerations.defaults .Values.tolerations.workloadOperator }} 211 | tolerations: 212 | {{ toYaml (default .Values.tolerations.defaults .Values.tolerations.workloadOperator) | indent 8 }} 213 | {{- end }} 214 | {{- if or .Values.affinity.defaults .Values.affinity.workloadOperator }} 215 | affinity: 216 | {{ toYaml (default .Values.affinity.defaults .Values.affinity.workloadOperator) | indent 8 }} 217 | {{- end }} 218 | {{- $classname := (default (default "" .Values.priorityClassName.default ) .Values.priorityClassName.workloadOperator) }} 219 | {{- if not (eq "" $classname) }} 220 | priorityClassName: "{{ $classname }}" 221 | {{- end }} 222 | {{- end }} 223 | --------------------------------------------------------------------------------