sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL-privilegier och säkerhet - Låsa det offentliga schemat

Introduktion

I en tidigare artikel introducerade vi grunderna för att förstå PostgreSQL-scheman, mekaniken för att skapa och radera, och granskat flera användningsfall. Den här artikeln kommer att utvidga dessa grunder och utforska hanteringsprivilegier relaterade till scheman.

Mer terminologiöverbelastning

Men det finns en preliminär fråga som behöver klargöras. Kom ihåg att vi i den föregående artikeln uppehöll oss vid en möjlig förvirringspunkt relaterad till överbelastning av termen "schema". Den specialiserade innebörden av den termen i samband med PostgreSQL-databaser är skild från hur den vanligtvis används i relationsdatabashanteringssystem. Vi har en annan liknande möjlig terminologistråk för det aktuella ämnet relaterat till ordet "offentlig".

När den första databasen skapades innehåller den nyskapade Postgresql-databasen ett fördefinierat schema med namnet "public". Det är ett schema som alla andra, men samma ord används också som ett nyckelord som betecknar "alla användare" i sammanhang där annars ett faktiskt rollnamn kan användas, som ... vänta på det ... schemaprivilegiehantering . Betydelsen och två distinkta användningsområden kommer att förtydligas i exemplen nedan.

Fråga schemaprivilegier

Innan vi gör detta konkret med exempelkod för att bevilja och återkalla schemaprivilegier, måste vi se över hur man undersöker schemaprivilegier. Med hjälp av kommandoradsgränssnittet psql listar vi scheman och tillhörande privilegier med kommandot \dn+. För en nyskapad sampledb-databas ser vi denna post för det offentliga schemat:

sampledb=# \dn+ 
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description      
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres+| standard public schema
        |          | =UC/postgres         |
(1 row)

De två första och fjärde kolumnerna är ganska enkla:som tidigare nämnts visar det standardskapade schemat med namnet "public", beskrivs som "standard offentligt schema" och ägs av rollen "postgres". (Schemaägandet, om inte annat anges, är inställt på rollen som skapar schemat.) Den tredje kolumnen som listar åtkomstbehörigheterna är av intresse här. Formatet för privilegieinformationen tillhandahåller tre poster:privilegiemottagaren, privilegierna och privilegiebeviljaren i formatet "grantee=privileges/grantor", det vill säga till vänster om likhetstecknet är rollen som tar emot privilegiet(erna), omedelbart till höger om likhetstecknet finns en grupp bokstäver som specificerar de särskilda privilegierna, och slutligen efter snedstrecket vilken roll som gav privilegier. Det kan finnas flera sådana privilegieinformationsspecifikationer, listade separerade med ett plustecken eftersom privilegier är additiv.

För scheman finns det två möjliga privilegier som kan beviljas separat:U för "USAGE" och C för "CREATE". Den förra krävs för att en roll ska ha möjlighet att slå upp databasobjekt såsom tabeller och vyer i schemat; det senare privilegiet tillåter en roll för att skapa databasobjekt i schemat. Det finns andra bokstäver för andra privilegier relaterade till olika typer av databasobjekt, men för scheman gäller endast U och C.

För att tolka privilegielistan ovan säger den första specifikationen oss att postgres-användaren beviljades uppdateringen och skapa privilegier själv på det offentliga schemat.

Observera att för den andra specifikationen ovan visas en tom sträng till vänster om likhetstecknet. Så här betecknas privilegier som beviljats ​​alla användare med hjälp av det PUBLIC-nyckelord som nämnts tidigare.

Denna senare specifikation att bevilja användning och skapa privilegier på det offentliga schemat till alla användare anses av vissa som möjligen strida mot allmänna säkerhetsprincipers bästa praxis, där man kanske föredrar att börja med åtkomstbegränsad som standard, vilket kräver att databasadministratören uttryckligen ger lämpliga och minimalt nödvändiga åtkomstbehörigheter. Dessa liberala privilegier på det offentliga schemat är avsiktligt konfigurerade i systemet som en bekvämlighet och för äldre kompatibilitet.

Observera också att förutom de tillåtande behörighetsinställningarna, är det enda speciella med det offentliga schemat att det också finns med i sökvägen, som vi diskuterade i föregående artikel. Detta är på samma sätt för bekvämlighets skull:sökvägskonfigurationen och liberala privilegier resulterar tillsammans i att en ny databas kan användas som om det inte fanns något sådant koncept som scheman.

Historisk bakgrund om det offentliga schemat

Detta kompatibilitetsproblem kommer från ungefär femton år sedan (före PostgreSQLversion 7.3, jfr version 7.3 release notes) när schemafunktionen inte var en del av PostgreSQL. Konfiguration av det offentliga schemat med liberala privilegier och närvaron av sökväg när scheman introducerades i version 7.3 möjliggjorde kompatibilitet för äldre applikationer, som inte är schemamedvetna, att fungera oförändrat med den uppgraderade databasfunktionen.

Annars finns det inget särskilt speciellt med det offentliga schemat:vissa DBA:s tar bort det om deras användningsfall inte ställer krav på det; andra låser den genom att återkalla standardbehörigheterna.

Visa mig koden – återkalla privilegier

Låt oss göra lite kod för att illustrera och utöka det vi har diskuterat hittills.

Schemaprivilegier hanteras med kommandona GRANT och REVOKE för att lägga till respektive ta tillbaka behörigheter. Vi ska prova några specifika exempel för att låsa det offentliga schemat, men den allmänna syntaxen är:

REVOKE [ GRANT OPTION FOR ]
    { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
    ON SCHEMA schema_name [, ...]
    FROM { [ GROUP ] role_name | PUBLIC } [, ...]
    [ CASCADE | RESTRICT ]

Så, som ett första exempel på låsning, låt oss ta bort skapa-privilegiet från det offentliga schemat. Observera att i dessa exempel hänvisar det gemena ordet "public" till schemat och kan ersättas av vilket annat giltigt schemanamn som helst som kan finnas i databasen. Versalerna "PUBLIC" är det speciella nyckelordet som innebär "alla användare" och kan istället ersättas med ett specifikt rollnamn eller kommaseparerad lista med rollnamn för mer finkornig åtkomstkontroll.

sampledb=# REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE
sampledb=# \dn+
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description       
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres+| standard public schema
        |          | =U/postgres          | 
(1 row)

Den enda skillnaden i denna lista över schemaprivilegier från den första är frånvaron av "C" i den andra behörighetsspecifikationen, vilket verifierar att vårt kommando var effektivt:andra användare än postgres-användaren får inte längre skapa tabeller, vyer eller andra objekt i det offentliga schemat.

Observera att kommandot ovan som återkallar skapa privilegier från det offentliga schemat är den rekommenderade begränsningen för en nyligen publicerad sårbarhet, CVE-2018-1058, som uppstår från standardbehörighetsinställningen på det offentliga schemat.

En ytterligare nivå av låsning kan innebära att man nekar uppslagsåtkomst till schemat helt genom att ta bort användningsprivilegiet:

sampledb=# REVOKE USAGE ON SCHEMA public FROM PUBLIC;
REVOKE
sampledb=# \dn+
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description       
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres | standard public schema
(1 row)

Eftersom alla tillgängliga schemaprivilegier för användare som inte är ägare har återkallats, försvinner hela den andra behörighetsspecifikationen i listan ovan.

Det vi gjorde med två separata kommandon kunde ha gjorts kortfattat med ett enda kommando som specificerade alla privilegier som:

sampledb=# REVOKE ALL PRIVILEGES ON SCHEMA public FROM PUBLIC;
REVOKE

Dessutom är det också möjligt att återkalla privilegier från schemaägaren:

sampledb=# REVOKE ALL PRIVILEGES ON SCHEMA public FROM postgres;
REVOKE
sampledb=# \dn+
                        List of schemas
  Name  |  Owner   | Access privileges |      Description       
--------+----------+-------------------+------------------------
 public | postgres |                   | standard public schema
(1 row)

men det åstadkommer egentligen inget praktiskt, eftersom schemaägaren behåller fulla privilegier till ägda scheman oavsett explicit tilldelning helt enkelt på grund av ägande.

Den liberala privilegietilldelningen för det offentliga schemat är en speciell artefakt som är associerad med initial databasskapande. Senare skapade scheman i en befintlig databas överensstämmer med bästa praxis att starta utan tilldelade privilegier. Om du till exempel undersöker schemabehörigheter efter att ha skapat ett nytt schema med namnet "privat" visar det att det nya schemat inte har några privilegier:

sampledb=# create schema private;
CREATE SCHEMA
sampledb=# \dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres |                      | 
 public  | postgres |                      | standard public schema
(2 rows)
Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda Whitepaper

Visa mig koden – bevilja privilegier

Den allmänna formen för kommandot för att lägga till privilegier är:

GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
    ON SCHEMA schema_name [, ...]
    TO role_specification [, ...] [ WITH GRANT OPTION ]
where role_specification can be:
  [ GROUP ] role_name
  | PUBLIC
  | CURRENT_USER
  | SESSION_USER

Med det här kommandot kan vi till exempel tillåta alla roller att söka upp databasobjekt i det privata schemat genom att lägga till användningsprivilegiet med

sampledb=# GRANT USAGE ON SCHEMA private TO PUBLIC;
GRANT
sampledb=# \dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres | postgres=UC/postgres+| 
         |          | =U/postgres          | 
 public  | postgres |                      | standard public schema
(2 rows)

Notera hur UC-behörigheterna visas för postgres-ägaren som den första specifikationen, nu när vi har tilldelat andra privilegier än standardbehörigheter till schemat. Den andra specifikationen, =U/postgres, motsvarar GRANT-kommandot som vi just anropade som användarens postgres som ger användarbehörighet till alla användare (där, kom ihåg, den tomma strängen till vänster om likhetstecknet antyder "alla användare").

En specifik roll, till exempel kallad "user1", kan beviljas både skapande och användningsrättigheter till det privata schemat med:

sampledb=# GRANT ALL PRIVILEGES ON SCHEMA private TO user1;
GRANT
sampledb=# \dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres | postgres=UC/postgres+| 
         |          | =U/postgres         +| 
         |          | user1=UC/postgres    | 
 public  | postgres |                      | standard public schema
(2 rows)

Vi har ännu inte nämnt "WITH GRANT OPTION"-klausulen i det allmänna kommandoformuläret. Precis som det låter tillåter den här klausulen en beviljad roll att själv ge den angivna behörigheten till andra användare, och den betecknas i behörighetslistan med asterisker som läggs till den specifika behörigheten:

sampledb=# GRANT ALL PRIVILEGES ON SCHEMA private TO user1 WITH GRANT OPTION;
GRANT
sampledb=# \dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres | postgres=UC/postgres+| 
         |          | =U/postgres         +| 
         |          | user1=U*C*/postgres  | 
 public  | postgres |                      | standard public schema
(2 rows)

Slutsats

Detta avslutar dagens ämne. Som en sista anmärkning, kom dock ihåg att vi bara har diskuterat schemaåtkomstprivilegier. Medan USAGE-behörigheten tillåter uppslagning av databasobjekt i ett schema, för att faktiskt komma åt objekten för specifika operationer, såsom läsning, skrivning, exekvering, etc., måste rollen också ha lämpliga privilegier för dessa operationer på dessa specifika databasobjekt.


  1. Hitta det maximala antalet år i följd för varje ID i en tabell (Oracle SQL)

  2. Varför raderna returnerar genom förklara är inte lika med count()?

  3. Hur man beräknar månatliga aktiva användare (MAU) i MySQL

  4. SQL Välja från två tabeller med inre koppling och limit