diff options
author | Robert Haas | 2011-07-20 17:18:24 +0000 |
---|---|---|
committer | Robert Haas | 2011-07-20 17:18:24 +0000 |
commit | 463f2625a5fb183b6a8925ccde98bb3889f921d9 (patch) | |
tree | f64c17891383a1867946c82215321b6aa42f1a42 /src/bin | |
parent | cacd42d62cb2ddf32135b151f627780a5509780f (diff) |
Support SECURITY LABEL on databases, tablespaces, and roles.
This requires a new shared catalog, pg_shseclabel.
Along the way, fix the security_label regression tests so that they
don't monkey with the labels of any pre-existing objects. This is
unlikely to matter in practice, since only the label for the "dummy"
provider was being manipulated. But this way still seems cleaner.
KaiGai Kohei, with fairly extensive hacking by me.
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/pg_dump/dumputils.c | 44 | ||||
-rw-r--r-- | src/bin/pg_dump/dumputils.h | 4 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 18 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dumpall.c | 56 |
4 files changed, 111 insertions, 11 deletions
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 6e5e625e6d0..acce7f82fa4 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -1166,3 +1166,47 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, return added_clause; #undef WHEREAND } + +/* + * buildShSecLabelQuery + * + * Build a query to retrieve security labels for a shared object. + */ +void +buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId, + PQExpBuffer sql) +{ + appendPQExpBuffer(sql, + "SELECT provider, label FROM pg_catalog.pg_shseclabel " + "WHERE classoid = '%s'::pg_catalog.regclass AND " + "objoid = %u", catalog_name, objectId); +} + +/* + * emitShSecLabels + * + * Format security label data retrieved by the query generated in + * buildShSecLabelQuery. + */ +void +emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, + const char *target, const char *objname) +{ + int i; + + for (i = 0; i < PQntuples(res); i++) + { + char *provider = PQgetvalue(res, i, 0); + char *label = PQgetvalue(res, i, 1); + + /* must use fmtId result before calling it again */ + appendPQExpBuffer(buffer, + "SECURITY LABEL FOR %s ON %s", + fmtId(provider), target); + appendPQExpBuffer(buffer, + " %s IS ", + fmtId(objname)); + appendStringLiteralConn(buffer, label, conn); + appendPQExpBuffer(buffer, ";\n"); + } +} diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index 44d90669b61..40bbc81ae8d 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -47,5 +47,9 @@ extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule); +extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name, + uint32 objectId, PQExpBuffer sql); +extern void emitShSecLabels(PGconn *conn, PGresult *res, + PQExpBuffer buffer, const char *target, const char *objname); #endif /* DUMPUTILS_H */ diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 9e69b0fc524..f2ee57cabd3 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2048,6 +2048,24 @@ dumpDatabase(Archive *AH) PQclear(res); + /* Dump shared security label. */ + if (!no_security_labels && g_fout->remoteVersion >= 90200) + { + PQExpBuffer seclabelQry = createPQExpBuffer(); + + buildShSecLabelQuery(g_conn, "pg_database", dbCatId.oid, seclabelQry); + res = PQexec(g_conn, seclabelQry->data); + check_sql_result(res, g_conn, seclabelQry->data, PGRES_TUPLES_OK); + resetPQExpBuffer(seclabelQry); + emitShSecLabels(g_conn, res, seclabelQry, "DATABASE", datname); + if (strlen(seclabelQry->data)) + ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL, + dba, false, "SECURITY LABEL", SECTION_NONE, + seclabelQry->data, "", NULL, + &dbDumpId, 1, NULL, NULL); + destroyPQExpBuffer(seclabelQry); + } + destroyPQExpBuffer(dbQry); destroyPQExpBuffer(delQry); destroyPQExpBuffer(creaQry); diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index b3ad2eac29b..b5f64e8d68e 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -52,6 +52,9 @@ static void dumpTimestamp(char *msg); static void doShellQuoting(PQExpBuffer buf, const char *str); static int runPgDump(const char *dbname); +static void buildShSecLabels(PGconn *conn, const char *catalog_name, + uint32 objectId, PQExpBuffer buffer, + const char *target, const char *objname); static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport, const char *pguser, enum trivalue prompt_password, bool fail_on_error); static PGresult *executeQuery(PGconn *conn, const char *query); @@ -718,15 +721,15 @@ dumpRoles(PGconn *conn) for (i = 0; i < PQntuples(res); i++) { const char *rolename; + Oid auth_oid; + auth_oid = atooid(PQgetvalue(res, i, i_oid)); rolename = PQgetvalue(res, i, i_rolname); resetPQExpBuffer(buf); if (binary_upgrade) { - Oid auth_oid = atooid(PQgetvalue(res, i, i_oid)); - appendPQExpBuffer(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n"); appendPQExpBuffer(buf, "SELECT binary_upgrade.set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n", @@ -796,6 +799,10 @@ dumpRoles(PGconn *conn) appendPQExpBuffer(buf, ";\n"); } + if (!no_security_labels && server_version >= 90200) + buildShSecLabels(conn, "pg_authid", auth_oid, + buf, "ROLE", rolename); + fprintf(OPF, "%s", buf->data); if (server_version >= 70300) @@ -981,7 +988,7 @@ dumpTablespaces(PGconn *conn) * pg_xxx) */ if (server_version >= 90000) - res = executeQuery(conn, "SELECT spcname, " + res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, " "array_to_string(spcoptions, ', ')," @@ -990,7 +997,7 @@ dumpTablespaces(PGconn *conn) "WHERE spcname !~ '^pg_' " "ORDER BY 1"); else if (server_version >= 80200) - res = executeQuery(conn, "SELECT spcname, " + res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, null, " "pg_catalog.shobj_description(oid, 'pg_tablespace') " @@ -998,7 +1005,7 @@ dumpTablespaces(PGconn *conn) "WHERE spcname !~ '^pg_' " "ORDER BY 1"); else - res = executeQuery(conn, "SELECT spcname, " + res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, " "null, null " @@ -1012,12 +1019,13 @@ dumpTablespaces(PGconn *conn) for (i = 0; i < PQntuples(res); i++) { PQExpBuffer buf = createPQExpBuffer(); - char *spcname = PQgetvalue(res, i, 0); - char *spcowner = PQgetvalue(res, i, 1); - char *spclocation = PQgetvalue(res, i, 2); - char *spcacl = PQgetvalue(res, i, 3); - char *spcoptions = PQgetvalue(res, i, 4); - char *spccomment = PQgetvalue(res, i, 5); + uint32 spcoid = atooid(PQgetvalue(res, i, 0)); + char *spcname = PQgetvalue(res, i, 1); + char *spcowner = PQgetvalue(res, i, 2); + char *spclocation = PQgetvalue(res, i, 3); + char *spcacl = PQgetvalue(res, i, 4); + char *spcoptions = PQgetvalue(res, i, 5); + char *spccomment = PQgetvalue(res, i, 6); char *fspcname; /* needed for buildACLCommands() */ @@ -1051,6 +1059,10 @@ dumpTablespaces(PGconn *conn) appendPQExpBuffer(buf, ";\n"); } + if (!no_security_labels && server_version >= 90200) + buildShSecLabels(conn, "pg_tablespace", spcoid, + buf, "TABLESPACE", fspcname); + fprintf(OPF, "%s", buf->data); free(fspcname); @@ -1615,6 +1627,28 @@ runPgDump(const char *dbname) return ret; } +/* + * buildShSecLabels + * + * Build SECURITY LABEL command(s) for an shared object + * + * The caller has to provide object type and identifier to select security + * labels from pg_seclabels system view. + */ +static void +buildShSecLabels(PGconn *conn, const char *catalog_name, uint32 objectId, + PQExpBuffer buffer, const char *target, const char *objname) +{ + PQExpBuffer sql = createPQExpBuffer(); + PGresult *res; + + buildShSecLabelQuery(conn, catalog_name, objectId, sql); + res = executeQuery(conn, sql->data); + emitShSecLabels(conn, res, buffer, target, objname); + + PQclear(res); + destroyPQExpBuffer(sql); +} /* * Make a database connection with the given parameters. An |