-
-
Save rosskevin/00f05766829a9b45888c508949399f0a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }, | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
}) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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