Skip to content

Instantly share code, notes, and snippets.

@howardjohn
Last active January 12, 2023 15:52
Show Gist options
  • Save howardjohn/ae20c608bebfb79e701009ee8f83b57b to your computer and use it in GitHub Desktop.
Save howardjohn/ae20c608bebfb79e701009ee8f83b57b to your computer and use it in GitHub Desktop.
Policies with multiple service accounts

This script analyzes AuthorizationPolicies in a cluster and checks whether there are Selector based policies that span multiple service accounts. This info may help guide future API decisions.

Example output:

$ curl -sL https://gist.githubusercontent.com/howardjohn/ae20c608bebfb79e701009ee8f83b57b/raw/8af7a83dff4ed000b18858cc96527b6c1f688ed8/find-cross-service-account-policies | sh
Policy echo/echo/ns1 has selects service accounts 'alpha,beta,', but doesn't fully select 'alpha,'
Policy echo/echo/ns1 has 2 Service accounts: 'alpha beta,
Policy echo/echo/policy has selects service accounts 'waypoint,', but doesn't fully select 'waypoint,'
Root Policy istio-system/ns1 has 2 Service accounts: alpha beta
Results: 6 Policies, 3 with Selector, 2 not fully covering an account, 1 with Multiple accounts, 1 with multiple accounts (root namespace)

(curl | sh usage is optional, of course).

The script does kubectl get requests only and does not mutate cluster state.

#!/bin/bash
policies=0
uncovered=0
global_policies=0
selector_policies=0
multiple=0
root_multiple=0
while read -r line;
do
((policies++))
if [[ "$line" == "" ]]; then
continue
fi
((selector_policies++))
name="$(<<< "$line" cut -d$'\t' -f1)"
ns="$(<<< "$name" cut -d/ -f1)"
labels="$(<<< "$line" cut -d$'\t' -f2)"
lbl="$(kubectl get pods -n $ns -l "$labels" -o go-template='{{range .items}}{{.metadata.name}}{{"\t"}}{{.spec.serviceAccountName}}{{"\n"}}{{end}}' | sort)"
all="$(kubectl get pods -n $ns -o go-template='{{range .items}}{{.metadata.name}}{{"\t"}}{{.spec.serviceAccountName}}{{"\n"}}{{end}}' | sort)"
notSelected="$(comm -13 <(echo "$lbl") <(echo "$all"))"
lbl_sa="$(<<<"$lbl" cut -d$'\t' -f2 | sort | uniq)"
notSelected_sa="$(<<<"$notSelected" cut -d$'\t' -f2 | sort | uniq)"
uncovered_sa="$(comm -12 <(echo "$lbl_sa") <(echo "$notSelected_sa"))"
if [[ ! -z "${uncovered_sa}" ]]; then
((uncovered++))
echo "Policy $ns/$name has selects service accounts '$(echo "$lbl_sa" | tr '\n' ',')', but doesn't fully select '$(echo "$uncovered_sa" | tr '\n' ',')'"
fi
sas="$(<<< "${lbl}" cut -d$'\t' -f2)"
sa_count="$(<<< "${sas}" sort | uniq | wc -l)"
if [[ "$sa_count" != "1" ]]; then
echo "Policy $ns/$name has $sa_count Service accounts: '$(echo $sas | tr '\n' ',')"
((multiple++))
fi
if [[ "$ns" == "istio-system" ]]; then
sas="$(kubectl get pods -A -l "$labels" -ojsonpath='{.items[*].spec.serviceAccountName}')"
sa_count="$(<<< "${sas}" tr ' ' '\n' | sort | uniq | wc -l)"
if [[ "$sa_count" != "1" ]]; then
echo "Root Policy $name has $sa_count Service accounts: $sas"
((root_multiple++))
fi
fi
done < <(kubectl get -A authorizationpolicies.security.istio.io -o go-template='{{range .items}}{{ if .spec.selector.matchLabels}}{{.metadata.namespace}}/{{.metadata.name}}{{end}}{{"\t"}}{{range $k, $v := .spec.selector.matchLabels }}{{$k}}={{$v}},{{end}}{{"\n"}}{{end}}' | rev | cut -c 2- | rev)
echo "Results: $policies Policies, $selector_policies with Selector, $uncovered not fully covering an account, $multiple with Multiple accounts, $root_multiple with multiple accounts (root namespace)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment