Skip to content

Instantly share code, notes, and snippets.

@theMagicalKarp
Last active December 12, 2020 00:00
Show Gist options
  • Save theMagicalKarp/bb75c1edb038b9e33b145ac6622e167d to your computer and use it in GitHub Desktop.
Save theMagicalKarp/bb75c1edb038b9e33b145ac6622e167d to your computer and use it in GitHub Desktop.

What

This is a deno typscript script, which pulls all the pods in the cluster, and runs a given opa policiy on each pod.

Requirements

Usage

deno run --allow-run \
  https://gist.githubusercontent.com/theMagicalKarp/bb75c1edb038b9e33b145ac6622e167d/raw/48f7969b068cbcf21f12839392ddc765c71055a8/pod-opa.ts \
  policies.rego data.main.is_root_user
import { autoDetectClient } from "https://deno.land/x/kubernetes_client@v0.1.0/mod.ts";
import {
CoreV1Api,
PodFields,
} from "https://deno.land/x/kubernetes_apis@v0.1.0/builtin/core@v1/mod.ts";
import { pooledMap } from "https://deno.land/std@0.80.0/async/mod.ts";
if (Deno.args.length !== 2) {
console.log("Must only provide <rego file> and <query expression>!");
Deno.exit(1);
}
const kubernetes = await autoDetectClient();
const coreApi = new CoreV1Api(kubernetes).namespace("");
const encoder = new TextEncoder();
const decoder = new TextDecoder();
function hasViolation(output: any): boolean {
if (!output.result) {
return false;
}
for (const result of output.result) {
if (!result.expressions) {
continue;
}
for (const expression of result.expressions) {
if (expression?.value) {
return true;
}
}
}
return false;
}
type PodEvaluation = {
name: string;
namespace: string;
violation: boolean;
};
async function evaluatePod(pod: PodFields): Promise<PodEvaluation> {
const p = Deno.run({
cmd: [
"opa",
"eval",
"--data",
Deno.args[0],
"--stdin-input",
Deno.args[1],
],
stdin: "piped",
stdout: "piped",
});
await p.stdin.write(encoder.encode(JSON.stringify(pod)));
await p.stdin.close();
const output = JSON.parse(decoder.decode(await p.output()));
p.close();
return {
name: pod.metadata?.name || "undefined",
namespace: pod.metadata?.namespace || "undefined",
violation: hasViolation(output),
};
}
const podList = await coreApi.getPodList();
const podEvaluations = pooledMap(32, podList.items, evaluatePod);
for await (const podEvaluation of podEvaluations) {
if (podEvaluation.violation) {
console.log(
`${podEvaluation.namespace}/${podEvaluation.name} is in violation!`,
);
}
}
package main
is_root_user {
input.spec.securityContext.runAsUser == 0
}
is_root_user {
input.spec.containers[_].securityContext.runAsUser == 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment