I'm trying to connect from a nodejs/typescript codebase running in GAE to a GCP managed Postgres db via secret manager.
I'm getting:
Error: 7 PERMISSION_DENIED: Permission denied on resource project DATABASE_USER.
when I run it in GAE.
First, make sure you've granted Secrets Access to the GAE service account in IAM.
Then use the following code example to get your ENV vars from secret manager.
import * as path from 'path';
import {SecretManagerServiceClient} from '@google-cloud/secret-manager';
import deasync from 'deasync';
require('dotenv').config();
const SnakeNamingStrategy =
require('typeorm-naming-strategies').SnakeNamingStrategy;
const googleProjectId = process.env.GOOGLE_CLOUD_PROJECT;
const isInGAE = googleProjectId !== undefined;
const isLocalUsingCloudProxy = process.env.USE_CLOUD_SQL_AUTH_PROXY !== undefined;
const getSecretSync = deasync((name: string, cb:any) => {
const c = new SecretManagerServiceClient();
c.accessSecretVersion({name: c.secretVersionPath(googleProjectId, name, "latest")}).then(([secret]) => {
cb(null, secret.payload.data.toString());
}).catch((err) => {
cb(err);
});
});
let config = {
type: 'postgres',
host: process.env.DATABASE_HOST || 'localhost',
port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
username: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
synchronize: false,
logging: false,
subscribers: [path.join(__dirname, '..', 'subscribers', '*.{ts,js}')],
entities: [path.join(__dirname, '..', 'models', '*.{ts,js}')],
migrations: [path.join(__dirname, '..', 'migrations', '*.{ts,js}')],
cli: {
entitiesDir: [path.join(__dirname, '..', 'models', '*.{ts,js}')],
migrationsDir: [path.join(__dirname, '..', 'migrations', '*.{ts,js}')],
},
namingStrategy: new SnakeNamingStrategy(),
};
if (isInGAE || isLocalUsingCloudProxy) {
config.username = getSecretSync("DATABASE_USER");
config.password = getSecretSync("DATABASE_PASSWORD");
config.database = getSecretSync("DATABASE_NAME");
config.host = isInGAE ? "/cloudsql/" + getSecretSync("DATABASE_HOST") : 'localhost';
config.port = isInGAE ? parseInt(getSecretSync("DATABASE_PORT"), 10) : 5432;
console.log("dbuser", config.username);
}
It's important to note that the DATABASE_HOST should be in the form of the "Connection Name" on the SQL tab, like project-id:us-central1:db-name