opencode-skills-collection 3.0.31 → 3.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +5 -1
- package/bundled-skills/container-security-hardening/SKILL.md +988 -0
- package/bundled-skills/container-security-hardening/references/base-image-comparison.md +245 -0
- package/bundled-skills/container-security-hardening/references/kubernetes-pod-security.md +561 -0
- package/bundled-skills/container-security-hardening/references/seccomp-profile-template.json +337 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/github-actions-advanced/SKILL.md +1075 -0
- package/bundled-skills/longbridge/SKILL.md +91 -0
- package/bundled-skills/runaway-guard/SKILL.md +331 -0
- package/package.json +1 -1
- package/skills_index.json +131 -27
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
# Kubernetes Pod Security Reference
|
|
2
|
+
|
|
3
|
+
Full reference for hardening workloads in Kubernetes — NetworkPolicy, RBAC, Pod Security Admission, admission controllers (Kyverno/OPA), and service account hardening.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Pod Security Admission (PSA)](#pod-security-admission)
|
|
8
|
+
2. [NetworkPolicy — Zero-Trust Networking](#networkpolicy)
|
|
9
|
+
3. [RBAC — Least Privilege](#rbac)
|
|
10
|
+
4. [Admission Controllers (Kyverno / OPA Gatekeeper)](#admission-controllers)
|
|
11
|
+
5. [Service Account Hardening](#service-account-hardening)
|
|
12
|
+
6. [Runtime Security — Falco](#runtime-security--falco)
|
|
13
|
+
7. [Secrets Management in K8s](#secrets-management-in-k8s)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Pod Security Admission
|
|
18
|
+
|
|
19
|
+
Built-in K8s 1.25+ policy engine (replaces deprecated PodSecurityPolicy).
|
|
20
|
+
|
|
21
|
+
### Three Built-In Policy Levels
|
|
22
|
+
|
|
23
|
+
| Level | What It Blocks |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `privileged` | No restrictions (cluster default) |
|
|
26
|
+
| `baseline` | Blocks hostNetwork, hostPID, hostIPC, privileged containers, dangerous volume types, hostPath |
|
|
27
|
+
| `restricted` | Everything in baseline + requires non-root, read-only FS, drops capabilities, requires seccomp |
|
|
28
|
+
|
|
29
|
+
### Three Modes Per Level
|
|
30
|
+
|
|
31
|
+
| Mode | Behavior |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `enforce` | Reject pods that violate the policy |
|
|
34
|
+
| `audit` | Allow but log a violation in audit log |
|
|
35
|
+
| `warn` | Allow but return a warning to the user |
|
|
36
|
+
|
|
37
|
+
### Applying PSA Labels
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Audit before enforcing — find what would fail
|
|
41
|
+
kubectl label namespace production \
|
|
42
|
+
pod-security.kubernetes.io/audit=restricted \
|
|
43
|
+
pod-security.kubernetes.io/audit-version=latest
|
|
44
|
+
|
|
45
|
+
# Gradual rollout: warn in staging, enforce in production
|
|
46
|
+
kubectl label namespace staging \
|
|
47
|
+
pod-security.kubernetes.io/warn=restricted \
|
|
48
|
+
pod-security.kubernetes.io/warn-version=latest
|
|
49
|
+
|
|
50
|
+
kubectl label namespace production \
|
|
51
|
+
pod-security.kubernetes.io/enforce=restricted \
|
|
52
|
+
pod-security.kubernetes.io/enforce-version=latest
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Check What Would Fail Before Enforcing
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Dry-run check against a namespace
|
|
59
|
+
kubectl --dry-run=server apply -f manifests/ --namespace production
|
|
60
|
+
|
|
61
|
+
# Check a specific pod spec
|
|
62
|
+
kubectl run test-pod --image=nginx --dry-run=server -n production
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Minimum Pod Spec for `restricted` Level
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
spec:
|
|
69
|
+
securityContext:
|
|
70
|
+
runAsNonRoot: true
|
|
71
|
+
runAsUser: 10001
|
|
72
|
+
runAsGroup: 10001
|
|
73
|
+
fsGroup: 10001
|
|
74
|
+
seccompProfile:
|
|
75
|
+
type: RuntimeDefault # or Localhost with a custom profile
|
|
76
|
+
containers:
|
|
77
|
+
- name: app
|
|
78
|
+
securityContext:
|
|
79
|
+
allowPrivilegeEscalation: false
|
|
80
|
+
readOnlyRootFilesystem: true
|
|
81
|
+
capabilities:
|
|
82
|
+
drop: ["ALL"]
|
|
83
|
+
# Resource limits are required for restricted PSA
|
|
84
|
+
resources:
|
|
85
|
+
requests:
|
|
86
|
+
memory: "64Mi"
|
|
87
|
+
cpu: "50m"
|
|
88
|
+
limits:
|
|
89
|
+
memory: "256Mi"
|
|
90
|
+
cpu: "250m"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## NetworkPolicy — Zero-Trust Networking
|
|
96
|
+
|
|
97
|
+
By default all pods in a cluster can reach all other pods on any port. Lock down with NetworkPolicy.
|
|
98
|
+
|
|
99
|
+
> **Prerequisite:** Your CNI plugin must support NetworkPolicy (Calico, Cilium, Weave Net — but NOT Flannel by default).
|
|
100
|
+
|
|
101
|
+
### Step 1: Default Deny All
|
|
102
|
+
|
|
103
|
+
Apply a default-deny to every namespace that holds workloads:
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
apiVersion: networking.k8s.io/v1
|
|
107
|
+
kind: NetworkPolicy
|
|
108
|
+
metadata:
|
|
109
|
+
name: default-deny-all
|
|
110
|
+
namespace: production
|
|
111
|
+
spec:
|
|
112
|
+
podSelector: {} # Selects all pods in this namespace
|
|
113
|
+
policyTypes:
|
|
114
|
+
- Ingress
|
|
115
|
+
- Egress
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Step 2: Allow Only Required Traffic
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
# Allow ingress from nginx ingress controller, egress to postgres + DNS
|
|
122
|
+
apiVersion: networking.k8s.io/v1
|
|
123
|
+
kind: NetworkPolicy
|
|
124
|
+
metadata:
|
|
125
|
+
name: allow-myapp
|
|
126
|
+
namespace: production
|
|
127
|
+
spec:
|
|
128
|
+
podSelector:
|
|
129
|
+
matchLabels:
|
|
130
|
+
app: myapp
|
|
131
|
+
policyTypes:
|
|
132
|
+
- Ingress
|
|
133
|
+
- Egress
|
|
134
|
+
ingress:
|
|
135
|
+
- from:
|
|
136
|
+
- namespaceSelector:
|
|
137
|
+
matchLabels:
|
|
138
|
+
kubernetes.io/metadata.name: ingress-nginx
|
|
139
|
+
- podSelector:
|
|
140
|
+
matchLabels:
|
|
141
|
+
app.kubernetes.io/name: ingress-nginx
|
|
142
|
+
ports:
|
|
143
|
+
- protocol: TCP
|
|
144
|
+
port: 3000
|
|
145
|
+
egress:
|
|
146
|
+
- to:
|
|
147
|
+
- podSelector:
|
|
148
|
+
matchLabels:
|
|
149
|
+
app: postgres
|
|
150
|
+
namespaceSelector:
|
|
151
|
+
matchLabels:
|
|
152
|
+
kubernetes.io/metadata.name: production
|
|
153
|
+
ports:
|
|
154
|
+
- protocol: TCP
|
|
155
|
+
port: 5432
|
|
156
|
+
- to: {} # Allow DNS resolution (required for service discovery)
|
|
157
|
+
ports:
|
|
158
|
+
- protocol: UDP
|
|
159
|
+
port: 53
|
|
160
|
+
- protocol: TCP
|
|
161
|
+
port: 53
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Allow Access to External Services (e.g., cloud APIs)
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
egress:
|
|
168
|
+
- to:
|
|
169
|
+
- ipBlock:
|
|
170
|
+
cidr: 0.0.0.0/0 # All external IPs
|
|
171
|
+
except:
|
|
172
|
+
- 10.0.0.0/8 # But not internal cluster ranges
|
|
173
|
+
- 172.16.0.0/12
|
|
174
|
+
- 192.168.0.0/16
|
|
175
|
+
ports:
|
|
176
|
+
- protocol: TCP
|
|
177
|
+
port: 443 # HTTPS only
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Validate NetworkPolicy with Cilium or Calico CLI
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Cilium — test connectivity between pods
|
|
184
|
+
cilium connectivity test
|
|
185
|
+
|
|
186
|
+
# Calico — list effective policies
|
|
187
|
+
kubectl exec -it deploy/myapp -- calicoctl get networkpolicy -n production
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## RBAC — Least Privilege
|
|
193
|
+
|
|
194
|
+
### Principle: Scope Narrowly, Avoid Wildcards
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
# ❌ DANGEROUS — grants everything to everything
|
|
198
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
199
|
+
kind: ClusterRoleBinding
|
|
200
|
+
metadata:
|
|
201
|
+
name: full-admin
|
|
202
|
+
subjects:
|
|
203
|
+
- kind: ServiceAccount
|
|
204
|
+
name: myapp-sa
|
|
205
|
+
namespace: production
|
|
206
|
+
roleRef:
|
|
207
|
+
kind: ClusterRole
|
|
208
|
+
name: cluster-admin
|
|
209
|
+
apiGroup: rbac.authorization.k8s.io
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
# ✅ CORRECT — minimal namespace-scoped role with specific resource names
|
|
213
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
214
|
+
kind: Role
|
|
215
|
+
metadata:
|
|
216
|
+
name: myapp-role
|
|
217
|
+
namespace: production
|
|
218
|
+
rules:
|
|
219
|
+
- apiGroups: [""]
|
|
220
|
+
resources: ["configmaps"]
|
|
221
|
+
resourceNames: ["myapp-config"] # Lock to specific named resources
|
|
222
|
+
verbs: ["get", "list"] # Never ["*"]
|
|
223
|
+
- apiGroups: [""]
|
|
224
|
+
resources: ["secrets"]
|
|
225
|
+
resourceNames: ["myapp-db-creds"]
|
|
226
|
+
verbs: ["get"]
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
230
|
+
kind: RoleBinding
|
|
231
|
+
metadata:
|
|
232
|
+
name: myapp-rolebinding
|
|
233
|
+
namespace: production
|
|
234
|
+
subjects:
|
|
235
|
+
- kind: ServiceAccount
|
|
236
|
+
name: myapp-sa
|
|
237
|
+
namespace: production
|
|
238
|
+
roleRef:
|
|
239
|
+
kind: Role
|
|
240
|
+
name: myapp-role
|
|
241
|
+
apiGroup: rbac.authorization.k8s.io
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Audit RBAC
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# What can a service account do?
|
|
248
|
+
kubectl auth can-i --list \
|
|
249
|
+
--as=system:serviceaccount:production:myapp-sa \
|
|
250
|
+
-n production
|
|
251
|
+
|
|
252
|
+
# Find all cluster-admin bindings (security anti-pattern)
|
|
253
|
+
kubectl get clusterrolebindings -o json | \
|
|
254
|
+
jq '.items[] | select(.roleRef.name=="cluster-admin") | {name:.metadata.name, subjects:.subjects}'
|
|
255
|
+
|
|
256
|
+
# Find overly broad wildcard permissions
|
|
257
|
+
kubectl get roles,clusterroles -A -o json | \
|
|
258
|
+
jq '.items[] | select(.rules[]?.verbs[]? == "*") | .metadata.name'
|
|
259
|
+
|
|
260
|
+
# Use rbac-tool for a full audit
|
|
261
|
+
kubectl rbac-tool who-can get secrets -n production
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Admission Controllers
|
|
267
|
+
|
|
268
|
+
### Kyverno (Policy as Kubernetes Resources)
|
|
269
|
+
|
|
270
|
+
Kyverno validates, mutates, and generates resources — no Rego knowledge required.
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
# Install Kyverno
|
|
274
|
+
helm repo add kyverno https://kyverno.github.io/kyverno/
|
|
275
|
+
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Essential Policies:**
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
# 1. Require non-root containers
|
|
282
|
+
apiVersion: kyverno.io/v1
|
|
283
|
+
kind: ClusterPolicy
|
|
284
|
+
metadata:
|
|
285
|
+
name: require-non-root
|
|
286
|
+
spec:
|
|
287
|
+
validationFailureAction: Enforce
|
|
288
|
+
rules:
|
|
289
|
+
- name: check-run-as-non-root
|
|
290
|
+
match:
|
|
291
|
+
resources:
|
|
292
|
+
kinds: [Pod]
|
|
293
|
+
validate:
|
|
294
|
+
message: "runAsNonRoot: true is required"
|
|
295
|
+
pattern:
|
|
296
|
+
spec:
|
|
297
|
+
containers:
|
|
298
|
+
- securityContext:
|
|
299
|
+
runAsNonRoot: true
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
# 2. Require image digest pinning
|
|
303
|
+
apiVersion: kyverno.io/v1
|
|
304
|
+
kind: ClusterPolicy
|
|
305
|
+
metadata:
|
|
306
|
+
name: require-image-digest
|
|
307
|
+
spec:
|
|
308
|
+
validationFailureAction: Enforce
|
|
309
|
+
rules:
|
|
310
|
+
- name: check-digest
|
|
311
|
+
match:
|
|
312
|
+
resources:
|
|
313
|
+
kinds: [Pod]
|
|
314
|
+
validate:
|
|
315
|
+
message: "Images must use @sha256: digest, not floating tags"
|
|
316
|
+
pattern:
|
|
317
|
+
spec:
|
|
318
|
+
containers:
|
|
319
|
+
- image: "*@sha256:*"
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
# 3. Disallow privileged containers
|
|
323
|
+
apiVersion: kyverno.io/v1
|
|
324
|
+
kind: ClusterPolicy
|
|
325
|
+
metadata:
|
|
326
|
+
name: disallow-privileged
|
|
327
|
+
spec:
|
|
328
|
+
validationFailureAction: Enforce
|
|
329
|
+
rules:
|
|
330
|
+
- name: check-privileged
|
|
331
|
+
match:
|
|
332
|
+
resources:
|
|
333
|
+
kinds: [Pod]
|
|
334
|
+
validate:
|
|
335
|
+
message: "Privileged containers are not allowed"
|
|
336
|
+
pattern:
|
|
337
|
+
spec:
|
|
338
|
+
containers:
|
|
339
|
+
- =(securityContext):
|
|
340
|
+
=(privileged): "false"
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
# 4. Require resource limits (prevents resource starvation)
|
|
344
|
+
apiVersion: kyverno.io/v1
|
|
345
|
+
kind: ClusterPolicy
|
|
346
|
+
metadata:
|
|
347
|
+
name: require-resource-limits
|
|
348
|
+
spec:
|
|
349
|
+
validationFailureAction: Enforce
|
|
350
|
+
rules:
|
|
351
|
+
- name: check-limits
|
|
352
|
+
match:
|
|
353
|
+
resources:
|
|
354
|
+
kinds: [Pod]
|
|
355
|
+
validate:
|
|
356
|
+
message: "Resource limits (memory and cpu) must be set"
|
|
357
|
+
pattern:
|
|
358
|
+
spec:
|
|
359
|
+
containers:
|
|
360
|
+
- resources:
|
|
361
|
+
limits:
|
|
362
|
+
memory: "?*"
|
|
363
|
+
cpu: "?*"
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
# 5. Auto-mutate: add drop ALL capabilities if not set
|
|
367
|
+
apiVersion: kyverno.io/v1
|
|
368
|
+
kind: ClusterPolicy
|
|
369
|
+
metadata:
|
|
370
|
+
name: drop-all-capabilities
|
|
371
|
+
spec:
|
|
372
|
+
rules:
|
|
373
|
+
- name: add-drop-all
|
|
374
|
+
match:
|
|
375
|
+
resources:
|
|
376
|
+
kinds: [Pod]
|
|
377
|
+
mutate:
|
|
378
|
+
patchStrategicMerge:
|
|
379
|
+
spec:
|
|
380
|
+
containers:
|
|
381
|
+
- (name): "*"
|
|
382
|
+
securityContext:
|
|
383
|
+
capabilities:
|
|
384
|
+
drop: ["ALL"]
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### OPA Gatekeeper (Policy as Rego)
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
# Install Gatekeeper
|
|
391
|
+
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.17/deploy/gatekeeper.yaml
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
```yaml
|
|
395
|
+
# ConstraintTemplate — define the Rego policy
|
|
396
|
+
apiVersion: templates.gatekeeper.sh/v1
|
|
397
|
+
kind: ConstraintTemplate
|
|
398
|
+
metadata:
|
|
399
|
+
name: k8srequiredlabels
|
|
400
|
+
spec:
|
|
401
|
+
crd:
|
|
402
|
+
spec:
|
|
403
|
+
names:
|
|
404
|
+
kind: K8sRequiredLabels
|
|
405
|
+
validation:
|
|
406
|
+
openAPIV3Schema:
|
|
407
|
+
properties:
|
|
408
|
+
labels:
|
|
409
|
+
type: array
|
|
410
|
+
items:
|
|
411
|
+
type: string
|
|
412
|
+
targets:
|
|
413
|
+
- target: admission.k8s.gatekeeper.sh
|
|
414
|
+
rego: |
|
|
415
|
+
package k8srequiredlabels
|
|
416
|
+
violation[{"msg": msg}] {
|
|
417
|
+
provided := {label | input.review.object.metadata.labels[label]}
|
|
418
|
+
required := {label | label := input.parameters.labels[_]}
|
|
419
|
+
missing := required - provided
|
|
420
|
+
count(missing) > 0
|
|
421
|
+
msg := sprintf("Missing required labels: %v", [missing])
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
# Constraint — apply the policy
|
|
426
|
+
apiVersion: constraints.gatekeeper.sh/v1beta1
|
|
427
|
+
kind: K8sRequiredLabels
|
|
428
|
+
metadata:
|
|
429
|
+
name: require-app-label
|
|
430
|
+
spec:
|
|
431
|
+
enforcementAction: deny
|
|
432
|
+
match:
|
|
433
|
+
kinds:
|
|
434
|
+
- apiGroups: ["apps"]
|
|
435
|
+
kinds: ["Deployment"]
|
|
436
|
+
parameters:
|
|
437
|
+
labels: ["app", "version", "owner"]
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Service Account Hardening
|
|
443
|
+
|
|
444
|
+
```yaml
|
|
445
|
+
# Dedicated service account per workload (never use 'default')
|
|
446
|
+
apiVersion: v1
|
|
447
|
+
kind: ServiceAccount
|
|
448
|
+
metadata:
|
|
449
|
+
name: myapp-sa
|
|
450
|
+
namespace: production
|
|
451
|
+
annotations:
|
|
452
|
+
# EKS — IAM Roles for Service Accounts (IRSA)
|
|
453
|
+
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/myapp-role
|
|
454
|
+
# GKE — Workload Identity
|
|
455
|
+
iam.gke.io/gcp-service-account: myapp@my-project.iam.gserviceaccount.com
|
|
456
|
+
automountServiceAccountToken: false # Disable unless app calls K8s API
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
# In the pod spec — also disable token mounting
|
|
460
|
+
spec:
|
|
461
|
+
serviceAccountName: myapp-sa
|
|
462
|
+
automountServiceAccountToken: false
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Why use Workload Identity instead of K8s Secrets for cloud credentials?**
|
|
466
|
+
- Credentials are short-lived (1h) and auto-rotated
|
|
467
|
+
- No secret to leak, rotate, or store
|
|
468
|
+
- Audit trail tied to workload identity, not a shared key
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Runtime Security — Falco
|
|
473
|
+
|
|
474
|
+
Falco detects anomalous runtime behaviour (unexpected syscalls, network connections, file reads).
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
# Install via Helm
|
|
478
|
+
helm repo add falcosecurity https://falcosecurity.github.io/charts
|
|
479
|
+
helm install falco falcosecurity/falco \
|
|
480
|
+
--namespace falco --create-namespace \
|
|
481
|
+
--set falco.grpc.enabled=true \
|
|
482
|
+
--set falco.grpcOutput.enabled=true
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
**Example rules:**
|
|
486
|
+
|
|
487
|
+
```yaml
|
|
488
|
+
# Alert on shell spawned inside a container
|
|
489
|
+
- rule: Terminal shell in container
|
|
490
|
+
desc: A shell was spawned in a container with an attached terminal
|
|
491
|
+
condition: >
|
|
492
|
+
spawned_process and container
|
|
493
|
+
and shell_procs and proc.tty != 0
|
|
494
|
+
and container_entrypoint
|
|
495
|
+
output: >
|
|
496
|
+
Shell spawned in a container (user=%user.name container=%container.name
|
|
497
|
+
shell=%proc.name parent=%proc.pname)
|
|
498
|
+
priority: WARNING
|
|
499
|
+
|
|
500
|
+
# Alert on sensitive file read
|
|
501
|
+
- rule: Read sensitive file untrusted
|
|
502
|
+
desc: An attempt to read a sensitive file by a non-trusted program
|
|
503
|
+
condition: >
|
|
504
|
+
open_read and sensitive_files
|
|
505
|
+
and not proc.name in (trusted_programs)
|
|
506
|
+
output: >
|
|
507
|
+
Sensitive file opened for reading (file=%fd.name user=%user.name
|
|
508
|
+
container=%container.name)
|
|
509
|
+
priority: WARNING
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## Secrets Management in K8s
|
|
515
|
+
|
|
516
|
+
**Kubernetes Secrets are base64-encoded, not encrypted by default.** Use one of these:
|
|
517
|
+
|
|
518
|
+
| Solution | Mechanism | Best For |
|
|
519
|
+
|---|---|---|
|
|
520
|
+
| **External Secrets Operator** | Sync from AWS Secrets Manager / GCP Secret Manager / Vault | Production — secrets never live in etcd |
|
|
521
|
+
| **Sealed Secrets (Bitnami)** | Asymmetric encryption of secrets in Git | GitOps workflows |
|
|
522
|
+
| **HashiCorp Vault** | Dynamic secrets, PKI, lease management | Complex multi-cloud setups |
|
|
523
|
+
| **SOPS + Age/GPG** | Encrypted secret files in Git | Small teams, simple workflows |
|
|
524
|
+
|
|
525
|
+
```yaml
|
|
526
|
+
# External Secrets Operator — sync from AWS Secrets Manager
|
|
527
|
+
apiVersion: external-secrets.io/v1beta1
|
|
528
|
+
kind: ExternalSecret
|
|
529
|
+
metadata:
|
|
530
|
+
name: myapp-db-creds
|
|
531
|
+
namespace: production
|
|
532
|
+
spec:
|
|
533
|
+
refreshInterval: 1h
|
|
534
|
+
secretStoreRef:
|
|
535
|
+
name: aws-secrets-manager
|
|
536
|
+
kind: ClusterSecretStore
|
|
537
|
+
target:
|
|
538
|
+
name: myapp-db-creds
|
|
539
|
+
creationPolicy: Owner
|
|
540
|
+
data:
|
|
541
|
+
- secretKey: DB_PASSWORD
|
|
542
|
+
remoteRef:
|
|
543
|
+
key: production/myapp/db
|
|
544
|
+
property: password
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
# Enable etcd encryption at rest (K8s)
|
|
549
|
+
# In kube-apiserver: --encryption-provider-config=encryption-config.yaml
|
|
550
|
+
# encryption-config.yaml:
|
|
551
|
+
apiVersion: apiserver.config.k8s.io/v1
|
|
552
|
+
kind: EncryptionConfiguration
|
|
553
|
+
resources:
|
|
554
|
+
- resources: [secrets]
|
|
555
|
+
providers:
|
|
556
|
+
- aescbc:
|
|
557
|
+
keys:
|
|
558
|
+
- name: key1
|
|
559
|
+
secret: <base64-encoded-32-byte-key>
|
|
560
|
+
- identity: {}
|
|
561
|
+
```
|