Skip to content

Instantly share code, notes, and snippets.

@itmayziii
Last active September 4, 2021 20:38
Show Gist options
  • Save itmayziii/25743011b013c9df7fca89a7aa987177 to your computer and use it in GitHub Desktop.
Save itmayziii/25743011b013c9df7fca89a7aa987177 to your computer and use it in GitHub Desktop.
Terraform IAM Bindings GCP Service Agents
{
"type": "module",
"private": true,
"author": "Tommy May III <[email protected]>",
"license": "MIT",
"dependencies": {
"node-fetch": "~3.0.0",
"node-html-parser": "~4.1.4"
}
}
import nodeHTMLParser from 'node-html-parser'
import fetch from 'node-fetch'
const { parse } = nodeHTMLParser
const baseGCPURL = 'https://cloud.google.com'
const args = process.argv.slice(2)
const projectId = args[0]
if (!projectId) {
throw new Error('Project ID should be supplied to this script, "node service-agents.js \'${google_project.project.number}\'"')
}
fetch(`${baseGCPURL}/iam/docs/service-agents`)
.then(response => {
if (!response.ok) {
throw new Error(`Unexpected response ${response.statusText}, ${response.status}.`)
}
return response.text()
})
.then(responseHTML => {
const html = parse(responseHTML)
const serviceAgentsTable = html.querySelector('#service-agents')
if (!serviceAgentsTable) {
throw new Error('Unable to find service agents table.')
}
const serviceAgentsTableBody = serviceAgentsTable.querySelector('.list')
if (!serviceAgentsTableBody) {
throw new Error('Unable to find service agents table body.')
}
serviceAgentsTableBody.removeWhitespace()
// Most service agents need to be prefixed with `service-` but certain ones do not, hence this exception list.
const exceptionRoles = ['roles/cloudbuild.builds.builder']
serviceAgentsTableBody.childNodes.map(tableRow => {
const { name, domain, link, role } = extractDataFromRow(tableRow)
if (!name || !domain || !link || !role) return
const member = exceptionRoles.includes(role)
? `serviceAccount:${projectId}@${domain}`
: `serviceAccount:service-${projectId}@${domain}`
console.log(`
binding {
/*
${name}
${link}
*/
role = "${role}"
members = ["${member}"]
}
`.trim())
})
})
.catch(console.error)
function extractDataFromRow (row) {
const name = row.childNodes[0].text.trim()
const domain = row.childNodes[1].text.trim()
if (row.childNodes[2].text.trim().toLowerCase() === 'none') {
return { name, domain, link: null, role: null }
}
const anchor = row.childNodes[2].querySelector('a')
if (!anchor) {
throw new Error(`Unable to find documentation link for ${name}`)
}
const link = anchor.getAttribute('href').trim()
if (!link) {
throw new Error(`Empty documentation link for ${name}`)
}
const code = row.childNodes[2].querySelector('code')
if (!code) {
throw new Error(`Unable to find documentation link for ${name}`)
}
const role = code.text.trim()
if (!role) {
throw new Error(`Empty role for ${name}`)
}
return { name, domain, link: `${baseGCPURL}${link}`, role }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment