GOOD SHELL MAS BOY
Server: Apache/2.4.52 (Ubuntu)
System: Linux vmi1836763.contaboserver.net 5.15.0-130-generic #140-Ubuntu SMP Wed Dec 18 17:59:53 UTC 2024 x86_64
User: www-data (33)
PHP: 8.4.10
Disabled: NONE
Upload Files
File: //usr/local/lib/node_modules/firebase-tools/lib/gcp/cloudsql/permissions.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupSQLPermissions = exports.iamUserIsCSQLAdmin = exports.checkSQLRoleIsGranted = exports.fdcSqlRoleMap = exports.firebasewriter = exports.firebasereader = exports.firebaseowner = void 0;
const projectUtils_1 = require("../../projectUtils");
const connect_1 = require("./connect");
const iam_1 = require("../iam");
const logger_1 = require("../../logger");
const lodash_1 = require("lodash");
const error_1 = require("../../error");
function firebaseowner(databaseId) {
    return `firebaseowner_${databaseId}_public`;
}
exports.firebaseowner = firebaseowner;
function firebasereader(databaseId) {
    return `firebasereader_${databaseId}_public`;
}
exports.firebasereader = firebasereader;
function firebasewriter(databaseId) {
    return `firebasewriter_${databaseId}_public`;
}
exports.firebasewriter = firebasewriter;
exports.fdcSqlRoleMap = {
    owner: firebaseowner,
    writer: firebasewriter,
    reader: firebasereader,
};
async function checkSQLRoleIsGranted(options, instanceId, databaseId, grantedRole, granteeRole) {
    const checkCmd = `
    DO $$
    DECLARE
        role_count INTEGER;
    BEGIN
        -- Count the number of rows matching the criteria
        SELECT COUNT(*)
        INTO role_count
        FROM
          pg_auth_members m
        JOIN
          pg_roles grantee ON grantee.oid = m.member
        JOIN
          pg_roles granted ON granted.oid = m.roleid
        JOIN
          pg_roles grantor ON grantor.oid = m.grantor
        WHERE
          granted.rolname = '${grantedRole}'
          AND grantee.rolname = '${granteeRole}';

        -- If no rows were found, raise an exception
        IF role_count = 0 THEN
            RAISE EXCEPTION 'Role "%", is not granted to role "%".', '${grantedRole}', '${granteeRole}';
        END IF;
    END $$;
`;
    try {
        await (0, connect_1.executeSqlCmdsAsIamUser)(options, instanceId, databaseId, [checkCmd], true);
        return true;
    }
    catch (e) {
        if (e instanceof error_1.FirebaseError && e.message.includes("not granted to role")) {
            return false;
        }
        logger_1.logger.error(`Role Check Failed: ${e}`);
        throw e;
    }
}
exports.checkSQLRoleIsGranted = checkSQLRoleIsGranted;
async function iamUserIsCSQLAdmin(options) {
    const projectId = (0, projectUtils_1.needProjectId)(options);
    const requiredPermissions = [
        "cloudsql.instances.connect",
        "cloudsql.instances.get",
        "cloudsql.users.create",
        "cloudsql.users.update",
    ];
    try {
        const iamResult = await (0, iam_1.testIamPermissions)(projectId, requiredPermissions);
        return iamResult.passed;
    }
    catch (err) {
        logger_1.logger.debug(`[iam] error while checking permissions, command may fail: ${err}`);
        return false;
    }
}
exports.iamUserIsCSQLAdmin = iamUserIsCSQLAdmin;
function ownerRolePermissions(databaseId, superuser, schema) {
    const firebaseOwnerRole = firebaseowner(databaseId);
    return [
        `do
      $$
      begin
        if not exists (select FROM pg_catalog.pg_roles
          WHERE  rolname = '${firebaseOwnerRole}') then
          CREATE ROLE "${firebaseOwnerRole}" WITH ADMIN "${superuser}";
        end if;
      end
      $$
    ;`,
        `GRANT "${firebaseOwnerRole}" TO "cloudsqlsuperuser"`,
        `ALTER SCHEMA "${schema}" OWNER TO "${firebaseOwnerRole}"`,
        `GRANT USAGE ON SCHEMA "${schema}" TO "${firebaseOwnerRole}"`,
        `GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA "${schema}" TO "${firebaseOwnerRole}"`,
        `GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA "${schema}" TO "${firebaseOwnerRole}"`,
    ];
}
function writerRolePermissions(databaseId, superuser, schema) {
    const firebaseWriterRole = firebasewriter(databaseId);
    return [
        `do
      $$
      begin
        if not exists (select FROM pg_catalog.pg_roles
          WHERE  rolname = '${firebaseWriterRole}') then
          CREATE ROLE "${firebaseWriterRole}" WITH ADMIN "${superuser}";
        end if;
      end
      $$
    ;`,
        `GRANT "${firebaseWriterRole}" TO "cloudsqlsuperuser"`,
        `GRANT USAGE ON SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
        `GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON ALL TABLES IN SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
        `GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
        `GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
        `SET ROLE = '${firebaseowner(databaseId)}';`,
        `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO "${firebaseWriterRole}";`,
        `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT USAGE ON SEQUENCES TO "${firebaseWriterRole}";`,
        `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT EXECUTE ON FUNCTIONS TO "${firebaseWriterRole}"`,
        `SET ROLE = cloudsqlsuperuser`,
    ];
}
function readerRolePermissions(databaseId, superuser, schema) {
    const firebaseReaderRole = firebasereader(databaseId);
    return [
        `do
      $$
      begin
        if not exists (select FROM pg_catalog.pg_roles
          WHERE  rolname = '${firebaseReaderRole}') then
          CREATE ROLE "${firebaseReaderRole}" WITH ADMIN "${superuser}";
        end if;
      end
      $$
    ;`,
        `GRANT "${firebaseReaderRole}" TO "cloudsqlsuperuser"`,
        `GRANT USAGE ON SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
        `GRANT SELECT ON ALL TABLES IN SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
        `GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
        `GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
        `SET ROLE = '${firebaseowner(databaseId)}';`,
        `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT SELECT ON TABLES TO "${firebaseReaderRole}";`,
        `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT SELECT, USAGE ON SEQUENCES TO "${firebaseReaderRole}";`,
        `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT EXECUTE ON FUNCTIONS TO "${firebaseReaderRole}"`,
        `SET ROLE = cloudsqlsuperuser`,
    ];
}
async function setupSQLPermissions(instanceId, databaseId, options, silent = false) {
    const superuser = "firebasesuperuser";
    const revokes = [];
    if (await checkSQLRoleIsGranted(options, instanceId, databaseId, "cloudsqlsuperuser", firebaseowner(databaseId))) {
        logger_1.logger.warn("Detected cloudsqlsuperuser was previously given to firebase owner, revoking to improve database security.");
        revokes.push(`REVOKE "cloudsqlsuperuser" FROM "${firebaseowner(databaseId)}"`);
    }
    const sqlRoleSetupCmds = (0, lodash_1.concat)(revokes, [`CREATE SCHEMA IF NOT EXISTS "public"`], ownerRolePermissions(databaseId, superuser, "public"), writerRolePermissions(databaseId, superuser, "public"), readerRolePermissions(databaseId, superuser, "public"));
    return (0, connect_1.executeSqlCmdsAsSuperUser)(options, instanceId, databaseId, sqlRoleSetupCmds, silent);
}
exports.setupSQLPermissions = setupSQLPermissions;