Skip to content

Instantly share code, notes, and snippets.

@rosskevin
Last active March 28, 2019 21:29
Show Gist options
  • Save rosskevin/00f05766829a9b45888c508949399f0a to your computer and use it in GitHub Desktop.
Save rosskevin/00f05766829a9b45888c508949399f0a to your computer and use it in GitHub Desktop.
import { project } from './gcp'
import { Identity } from '@alienfast/pulumi'
import { protect } from './protect'
export const api = new Identity(
'api',
{
project,
iamRoles: [
// access to buckets
'roles/storage.admin',
],
},
{ protect },
)
import { ComponentResource, ComponentResourceOptions, Output } from '@pulumi/pulumi'
import kebabCase from 'lodash/kebabCase'
import * as gcp from '@pulumi/gcp'
import { upperCaseFirstLetter } from '@alienfast/common'
import { getStack } from '@pulumi/pulumi/runtime'
import { Log } from '@alienfast/common-node'
import camelCase from 'lodash/camelCase'
const log = new Log('Identity', 'debug')
export interface IdentityArgs {
readonly iamRoles?: string[]
readonly project: string
}
/**
*
* @see https://cloud.google.com/iam/docs/understanding-roles
* @see https://cloud.google.com/kubernetes-engine/docs/how-to/iam
*/
export class Identity extends ComponentResource {
public account!: gcp.serviceAccount.Account
public key!: gcp.serviceAccount.Key
public secret!: Output<string>
constructor(nameArg: string, args: IdentityArgs, opts: ComponentResourceOptions) {
const name = `${nameArg}${upperCaseFirstLetter(getStack() || '')}`
super('af:pulumi:Identity', name, {}, opts)
const { iamRoles, project } = args
log.debug('creating service account:', name)
this.account = new gcp.serviceAccount.Account(
name,
{
project,
accountId: kebabCase(name),
},
{ parent: this },
)
if (iamRoles) {
for (let role of iamRoles) {
let bindingName = camelCase(role.replace('roles/', ''))
bindingName = `${name}${upperCaseFirstLetter(bindingName)}`
log.debug('creating role binding:', bindingName, '=>', role)
new gcp.projects.IAMBinding(
bindingName,
{
project,
role,
members: [this.account.email.apply(email => `serviceAccount:${email}`)],
},
{ parent: this, dependsOn: [this.account] },
)
}
}
this.key = new gcp.serviceAccount.Key(
`${name}Key`,
{ serviceAccountId: this.account.name },
{ parent: this },
)
/**
* Export client secret so that CI/CD systems can authenticate as this service account.
*
* The formats are slightly different from key, so decode the `privateKey` field and expose this json for use
* in secrets and consumption/propagation as the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.
*
* @see https://cloud.google.com/iam/docs/creating-managing-service-account-keys#iam-service-account-keys-create-rest
*/
this.secret = this.key.privateKey.apply(key =>
JSON.parse(Buffer.from(key, 'base64').toString('ascii')),
) as any
this.registerOutputs({
account: this.account,
key: this.key,
secret: this.secret,
})
}
}
{
"account": {
"accountId": "api-development",
"displayName": "",
"email": "api-development@acme.iam.gserviceaccount.com",
"id": "projects/acme/serviceAccounts/api-development@acme.iam.gserviceaccount.com",
"name": "projects/acme/serviceAccounts/api-development@acme.iam.gserviceaccount.com",
"project": "acme",
"uniqueId": "10604847519",
"urn": "urn:pulumi:development::acme-identity::af:pulumi:Identity$gcp:serviceAccount/account:Account::apiDevelopment"
},
"key": {
"id": "projects/acme/serviceAccounts/api-development@acme.iam.gserviceaccount.com/keys/892f109e8ccc2c9506cf9d2a22d12cc926d1abdd",
"keyAlgorithm": "KEY_ALG_RSA_2048",
"name": "projects/acme/serviceAccounts/api-development@acme.iam.gserviceaccount.com/keys/892f109e8ccc2c9506cf9d2a22d12cc926d1abdd",
"privateKey": "ewoiYWR2aXNvcmluNmNmOWQyYTIyZDEyY2M5MjZkMWFiZGQiLAogICJwcml2YXRlX2tleSI6ICItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRHF2djZzd3ozQ0ZRN3pcblNWY0FZWmJndXludHp4R1dlMXZrYUphSnpzMC8wT2xWVGh3WjVBYUlIcXUxbU42bW44ZVFNZUdENE5ZV2ZNa2NcbkxpWmg4R1FDeXpnOXZNV3daUUZ1cTFJS2U0bk52WWd6eUNnYzlicjdGR2JkWndHaG9Ta1RwdU5yNytIQ0VsTW1cblBZa1ViaVZGbURsSDRwZHZtUUVLaXBjVnBzTHNzdjNPeGZBM281bDRENWtKR1JBWnJHOHFGbWFyVndWWUdPUUxcbjJHTStCQWowbmNvVHJWQ3MyK3RQY3g3QkZyNWlEWWlsMDBIRm5NY0NhMkhSYThFcWJRWEhKOG1uallvM1J1U0FcbnpnQmpIYkhGYStqM09kQWlpRm5ybnc4ODV0ZGxraHRyUnZVNy9wNTNEUDczQWlLQTdYTFdrTlczTHlOeTFNWmZcblFDNWxBRXFoQWdNQkFBRUNnZ0VBRm1RTXFIZXdoYmxLdldXdzB1QmNHdmc3Ui92RThKSzRhWVZZMjVEeVZxeVRcbmZ3K2w0a25UM2lxM3cranVqdHZsZGdGdUFtMWhHbERCZ1lxODNrRm0xclhoMmRDdVZoU1NVZ2N0R29NZFdqYWlcbmZkYnhEWThhVEUzdVFGN05ndWhiZ2N4OHU0eE1YejJ1ZVBLc1p6cVkyMFlwYTR3SFdBMlM4Zm1WYnVzaXcxOGlcbkRTMUZmeURHejVpRmR0SGdlOWFyNnhkNmh2Z3RSUWJyQjZBb3hFdWJjT0JHcURvaUpPdTlzbGIvOVJycFptNWFcbkRIQmRBeCt3L1hyVGEvdWlXTktDM0xyNW9NOGdJZTRrRDk1d1RHajdWUCtaQ1JaWXA2LzB2MmZpS1l5Q2plQmdcbnJXN2hBS0JzcGFNN25rR1RIY2tnQWJZbDlqUGtPRVNqYjJ0VGxCVGZHUUtCZ1FENUVzd0p3a3JQUnZKZExKMzBcblgwNFJWNTRCUWZYVWF1MHI4am1OWEIvbFB0L05kL1UydDRjT2ZiVWs3VDBNQlAzZDVVazhCRVlvZGxURG9LZ3pcbmw5d3VMdjliVktXL0dGdzNkTHVWeDVZQUxYTm9DN0JlM1NFUUtrOVBFMTh0RG9ZbXozclRiNjVkdGhYcnpOcWZcbnJVWkpQUjJ0RUNmWUdHak4rZEMyMG5HU2lRS0JnUUR4UmpMVDJDdHhRTXBpVzYwUUxrZFhNVUVYQVQwdkdJQlBcblFTTVovUXhFdlNrNWwzdm9BNjRLMTNVSmpkNGhNQkhOYi9QK21XcWo5Mmc1cGoxRUhaTTNDT21NZ25qRjlBMi9cblFWeU1tQnY1S0w4S1lWWTdSTUVBcTZyMXAzenhHdzhiVFJ3VzdNbHJxaHBtd1NvVXQwc3J3WkVieWdpYzljdjFcbnhkenUvUzlSV1FLQmdFd3VXS1AvZmp3cHVnV1BtUHhlamhVMTFFa1VNS2w0enZQckVYbFFIUjFUL3NYc2s5N1pcbmdZQ0lLSGlUNjJFYXdiODEyeEYxU1RRbEJVWVVoSDNMUy9nQVBmQmtVcEhCVkt0TmsvWjY1a0ZGcFkvRVMzeW9cbmErMXkwM0VmUHJRY1JpSG13ZTJic2h4TmppVGlNbGcyZWxINlZISlRoNnhMd3ZxRkZ6Wmo1WUxwQW9HQkFJK0FcblJBelJ2b3plajBETzYvRDZ4WDJya3Q0ZTQ0Z1dWNEpMNkplMWRNMlJnR3A3bWJ1V0xMYlFEUkZBcXNRc2Rmb3RcblF2N0R1clNKR3hsbXNYdkk1MTFOVkxNNGlxS2FGRzhUYmZ0RklTWWhRUGJvaThRMmtXQlh1aGZmcFNVMkJkY2tcbkZyZmYzN0RFZkcxdktCc29KWEtCNzArSzYzS0hrdWE3NXpyUnBZb0pBb0dBSGdtWWRzclpvOTJHWHFiMU1Wb3lcblNOUHFMdEowVXRuTXZONHluY0tpT0xhSTc2MXVHT3VUK1pJTkVxVWRoQ3d4STAreXp3Y3dKSTl1UENFRVIyQ3NcbkhwaFVCNkl5YVRUYS9PUUJpcFJTSmpYRXZIN3hBa1dOZG9QS1JhK1hsblQzUFdRajJCWXpyM2NNK2tFR2ZXTzRcbkRUSURlTlFCa2dGK3dOTlJRK1dkV01FPVxuLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLVxuIiwKICAiY2xpZW50X2VtYWlsIjogImFwaS1kZXZlbG9wbWVudEBhZHZpc29yaW50YWtlLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwKICAiY2xpZW50X2lkIjogIjEwNjA1Mjc3Mjc4MTE4NDg0NzUxOSIsCiAgImF1dGhfdXJpIjogImh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi9hdXRoIiwKICAidG9rZW5fdXJpIjogImh0dHBzOi8vb2F1dGgyLmdvb2dsZWFwaXMuY29tL3Rva2VuIiwKICAiYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92MS9jZXJ0cyIsCiAgImNsaWVudF94NTA5X2NlcnRfdXJsIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3JvYm90L3YxL21ldGFkYXRhL3g1MDkvYXBpLWRldmVsb3BtZW50JTQwYWR2aXNvcmludGFrZS5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIKfQo=",
"privateKeyType": "TYPE_GOOGLE_CREDENTIALS_FILE",
"publicKey": "LS0tLS1CRUdJTikRySFFEV3JuaXd3RFFZSktvWklodmNOQVFFRkJRQXdJREVlTUJ3R0ExVUUKQXhNVk1UQTJNRFV5TnpjeU56Z3hNVGcwT0RRM05URTVNQjRYRFRFNU1ETXhPREU0TVRRek1Wb1hEVEk1TURNeApOVEU0TVRRek1Wb3dJREVlTUJ3R0ExVUVBeE1WTVRBMk1EVXlOemN5TnpneE1UZzBPRFEzTlRFNU1JSUJJakFOCkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTZyNytyTU05d2hVTzgwbFhBR0dXNExzcDdjOFIKbG50YjVHaVdpYzdOUDlEcFZVNGNHZVFHaUI2cnRaamVwcC9Ia0RIaGcrRFdGbnpKSEM0bVlmQmtBc3M0UGJ6RgpzR1VCYnF0U0NudUp6YjJJTThnb0hQVzYreFJtM1djQm9hRXBFNmJqYSsvaHdoSlRKajJKRkc0bFJaZzVSK0tYCmI1a0JDb3FYRmFiQzdMTDl6c1h3TjZPWmVBK1pDUmtRR2F4dktoWm1xMWNGV0Jqa0M5aGpQZ1FJOUozS0U2MVEKck52clQzTWV3UmErWWcySXBkTkJ4WnpIQW10aDBXdkJLbTBGeHlmSnA0MktOMGJrZ000QVl4Mnh4V3ZvOXpuUQpJb2haNjU4UFBPYlhaWkliYTBiMU8vNmVkd3orOXdJaWdPMXkxcERWdHk4amN0VEdYMEF1WlFCS29RSURBUUFCCm96Z3dOakFNQmdOVkhSTUJBZjhFQWpBQU1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBV0JnTlZIU1VCQWY4RUREQUsKQmdnckJnRUZCUWNEQWpBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQTBSbW1Ob1RGWG9vYVVIQ0JWclk4eGIyRgpqNnpkYWhFY2NoVU92dWplZDlaZjQ4TUFIdHhTUWNxTzlwMi9SZnF3TGFWOHQrYnBkaXZsZkcrcUJNUTYrM0FuCmd0V2loM0ZDNnNqbEczMEt1K1pTSHptdGFpVUNvMXMrUlQxWkVQdWVpWG4zQy9pVHc0YXNWaEpBbEZremFuSkQKMkU5RTU0M0Qvc3A1cHRtU2hQemZMZ3FUTFBvQ2ZHS0lLYXB1RVBLZlQ4bEsxemdNaElGTkFLUjFkcDNJeWFuNgo1N01HdzRuaFlVdGUxTXVkNEFCWHl0ZkM1a1dPc0kydFNGYkRLVWV5M1hUSHlxWEVEZFFiaUFpWUxvMzJFY29UCmVXUjJyVjRGVlcrc0ZOcFpZOUlvV3owR1Fuc0l4QzJXQ00wS2dpUU1nMGhseW5odnlaTzZXeUtnMVh6OG53PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
"publicKeyType": "TYPE_X509_PEM_FILE",
"serviceAccountId": "projects/acme/serviceAccounts/api-development@acme.iam.gserviceaccount.com",
"urn": "urn:pulumi:development::acme-identity::af:pulumi:Identity$gcp:serviceAccount/key:Key::apiDevelopmentKey",
"validAfter": "2019-03-18T18:14:31Z",
"validBefore": "2029-03-15T18:14:31Z"
},
"secret": {
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"client_email": "api-development@acme.iam.gserviceaccount.com",
"client_id": "1060527519",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/api-development%40acme.iam.gserviceaccount.com",
"private_key": "-----BEGIN PRIVATE KEY-----\guyntzxGWe1vkaJaJzs0/0OlVThwZ5AaINYWfMkc\nLiZh8GQCyzg9vMWwZQFuq1IKe4nNvYgzyCgc9br7FGbdZwGhoSkTpuNr7+HCElMm\nPYkUbiVFmDlH4pdvmQEKipcVpsLssv3OxfA3o5l4D5kJGRAZrG8qFmarVwVYGOQL\n2GM+BAj0ncoTrVCs2+tPcx7BFr5iDYil00HFnMcCa2HRa8EqbQXHJ8mnjYo3RuSA\nzgBjHbHFa+j3OdAiiFnrnw885tdlkhtrRvU7/p53DP73AiKA7XLWkNW3LyNy1MZf\nQC5lAEqhAgMBAAECggEAFmQMqHewhblKvWWw0uBcGvg7R/vE8JK4aYVY25DyVqyT\nfw+l4knT3iq3w+jujtvldgFuAm1hGlDBgYq83kFm1rXh2dCuVhSSUgctGoMdWjai\nfdbxDY8aTE3uQF7Nguhbgcx8u4xMXz2uePKsZzqY20Ypa4wHWA2S8fmVbusiw18i\nDS1FfyDGz5iFdtHge9ar6xd6hvgtRQbrB6AoxEubcOBGqDoiJOu9slb/9RrpZm5a\nDHBdAx+w/XrTa/uiWNKC3Lr5oM8gIe4kD95wTGj7VP+ZCRZYp6/0v2fiKYyCjeBg\nrW7hAKBspaM7nkGTHckgAbYl9jPkOESjb2tTlBTfGQKBgQD5EswJwkrPRvJdLJ30\nX04RV54BQfXUau0r8jmNXB/lPt/Nd/U2t4cOfbUk7T0MBP3d5Uk8BEYodlTDoKgz\nl9wuLv9bVKW/GFw3dLuVx5YALXNoC7Be3SEQKk9PE18tDoYmz3rTb65dthXrzNqf\nrUZJPR2tECfYGGjN+dC20nGSiQKBgQDxRjLT2CtxQMpiW60QLkdXMUEXAT0vGIBP\nQSMZ/QxEvSk5l3voA64K13UJjd4hMBHNb/P+mWqj92g5pj1EHZM3COmMgnjF9A2/\nQVyMmBv5KL8KYVY7RMEAq6r1p3zxGw8bTRwW7MlrqhpmwSoUt0srwZEbygic9cv1\nxdzu/S9RWQKBgEwuWKP/fjwpugWPmPxejhU11EkUMKl4zvPrEXlQHR1T/sXsk97Z\ngYCIKHiT62Eawb812xF1STQlBUYUhH3LS/gAPfBkUpHBVKtNk/Z65kFFpY/ES3yo\na+1y03EfPrQcRiHmwe2bshxNjiTiMlg2elH6VHJTh6xLwvqFFzZj5YLpAoGBAI+A\nRAzRvozej0DO6/D6xX2rkt4e44gWV4JL6Je1dM2RgGp7mbuWLLbQDRFAqsQsdfot\nQv7DurSJGxlmsXvI511NVLM4iqKaFG8TbftFISYhQPboi8Q2kWBXuhffpSU2Bdck\nFrff37DEfG1vKBsoJXKB70+K63KHkua75zrRpYoJAoGAHgmYdsrZo92GXqb1MVoy\nSNPqLtJ0UtnMvN4yncKiOLaI761uGOuT+ZINEqUdhCwxI0+yzwcwJI9uPCEER2Cs\nHphUB6IyaTTa/OQBipRSJjXEvH7xAkWNdoPKRa+XlnT3PWQj2BYzr3cM+kEGfWO4\nDTIDeNQBkgF+wNNRQ+WdWME=\n-----END PRIVATE KEY-----\n",
"private_key_id": "892f109e8ccc2c9506cf9d2a22d12cc926d1abdd",
"project_id": "acme",
"token_uri": "https://oauth2.googleapis.com/token",
"type": "service_account"
},
"urn": "urn:pulumi:development::acme-identity::af:pulumi:Identity::apiDevelopment"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment