CREATE SERVER fuseki FOREIGN DATA WRAPPER rdf_fdw OPTIONS ( endpoint 'http://fuseki:3030/dt/sparql', update_url 'http://fuseki:3030/dt/update', http_proxy 'http://172.19.42.101:3128', connect_timeout '1'); CREATE FOREIGN TABLE ft ( subject rdfnode OPTIONS (variable '?s'), predicate rdfnode OPTIONS (variable '?p'), object rdfnode OPTIONS (variable '?o') ) SERVER fuseki OPTIONS ( log_sparql 'true', sparql 'SELECT * WHERE {?s ?p ?o}', sparql_update_pattern '?s ?p ?o .' ); CREATE USER MAPPING FOR postgres SERVER fuseki OPTIONS ( user 'admin', password 'secret', proxy_user 'proxyuser', proxy_password 'proxypass'); /* Correct proxy settings */ INSERT INTO ft (subject, predicate, object) VALUES ('', '', '"Westfälische Wilhelms-Universität Münster"@de'); INFO: SPARQL query sent to 'fuseki': INSERT DATA { "Westfälische Wilhelms-Universität Münster"@de }; SELECT * FROM ft; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 1 record. subject | predicate | object -------------------------------+------------------------------------+------------------------------------------------ | | "Westfälische Wilhelms-Universität Münster"@de (1 row) SELECT * FROM sparql.describe('fuseki', 'DESCRIBE '); subject | predicate | object -------------------------------+------------------------------------+------------------------------------------------ | | "Westfälische Wilhelms-Universität Münster"@de (1 row) CALL rdf_fdw_clone_table( create_table => true, foreign_table => 'public.ft', target_table => 'public.t1' ); INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} ORDER BY ASC(?s) OFFSET 0 LIMIT 100 INFO: SPARQL returned 1 record. INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} ORDER BY ASC(?s) OFFSET 100 LIMIT 100 INFO: SPARQL returned 0 records. SELECT * FROM public.t1; subject | predicate | object -------------------------------+------------------------------------+------------------------------------------------ | | "Westfälische Wilhelms-Universität Münster"@de (1 row) UPDATE ft SET object = '"University of Münster"@en' WHERE subject = ''; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o ## rdf_fdw pushdown conditions ## FILTER(?s = ) } INFO: SPARQL returned 1 record. INFO: SPARQL query sent to 'fuseki': DELETE DATA { "Westfälische Wilhelms-Universität Münster"@de }; INSERT DATA { "University of Münster"@en }; SELECT * FROM ft; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 1 record. subject | predicate | object -------------------------------+------------------------------------+---------------------------- | | "University of Münster"@en (1 row) DELETE FROM ft; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 1 record. INFO: SPARQL query sent to 'fuseki': DELETE DATA { "University of Münster"@en }; SELECT * FROM ft; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 0 records. subject | predicate | object ---------+-----------+-------- (0 rows) /* * A cached plan uses the user mapping current at execution, not the one * of the role that planned it. */ \set VERBOSITY terse CREATE ROLE proxy_role; GRANT USAGE ON FOREIGN SERVER fuseki TO proxy_role; GRANT SELECT ON ft TO proxy_role; CREATE USER MAPPING FOR proxy_role SERVER fuseki OPTIONS (proxy_user 'proxyuser', proxy_password 'wrongpass'); PREPARE ft_count AS SELECT count(*) FROM ft; EXECUTE ft_count; INFO: SPARQL query sent to 'fuseki': SELECT * {?s ?p ?o} INFO: SPARQL returned 0 records. count ------- 0 (1 row) SET ROLE proxy_role; EXECUTE ft_count; -- must fail: proxy_role's mapping INFO: SPARQL query sent to 'fuseki': SELECT * {?s ?p ?o} ERROR: proxy authentication required on server "fuseki" (HTTP 407) RESET ROLE; ALTER USER MAPPING FOR postgres SERVER fuseki OPTIONS (SET proxy_password 'wrongpass'); EXECUTE ft_count; -- must fail: altered mapping INFO: SPARQL query sent to 'fuseki': SELECT * {?s ?p ?o} ERROR: proxy authentication required on server "fuseki" (HTTP 407) ALTER USER MAPPING FOR postgres SERVER fuseki OPTIONS (SET proxy_password 'proxypass'); EXECUTE ft_count; INFO: SPARQL query sent to 'fuseki': SELECT * {?s ?p ?o} INFO: SPARQL returned 0 records. count ------- 0 (1 row) DEALLOCATE ft_count; /* * A foreign table queried through a view uses the user mapping of the * view owner, as the permissions are checked as that role. */ CREATE VIEW ft_view AS SELECT * FROM ft; GRANT SELECT, INSERT, UPDATE, DELETE ON ft_view TO proxy_role; SET ROLE proxy_role; INSERT INTO ft_view (subject, predicate, object) VALUES ('', '', '"Universität Münster"@de'); INFO: SPARQL query sent to 'fuseki': INSERT DATA { "Universität Münster"@de }; SELECT * FROM ft_view; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 1 record. subject | predicate | object -------------------------------+------------------------------------+-------------------------- | | "Universität Münster"@de (1 row) UPDATE ft_view SET object = '"University of Münster"@en' WHERE subject = ''; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o ## rdf_fdw pushdown conditions ## FILTER(?s = ) } INFO: SPARQL returned 1 record. INFO: SPARQL query sent to 'fuseki': DELETE DATA { "Universität Münster"@de }; INSERT DATA { "University of Münster"@en }; SELECT * FROM ft_view; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 1 record. subject | predicate | object -------------------------------+------------------------------------+---------------------------- | | "University of Münster"@en (1 row) DELETE FROM ft_view; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 1 record. INFO: SPARQL query sent to 'fuseki': DELETE DATA { "University of Münster"@en }; SELECT * FROM ft_view; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} INFO: SPARQL returned 0 records. subject | predicate | object ---------+-----------+-------- (0 rows) SELECT * FROM ft; -- must fail: proxy_role's mapping INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} ERROR: proxy authentication required on server "fuseki" (HTTP 407) RESET ROLE; DROP VIEW ft_view; DROP USER MAPPING FOR proxy_role SERVER fuseki; REVOKE ALL ON ft FROM proxy_role; REVOKE ALL ON FOREIGN SERVER fuseki FROM proxy_role; DROP ROLE proxy_role; \set VERBOSITY default /* Wrong user - must fail */ ALTER USER MAPPING FOR postgres SERVER fuseki OPTIONS (SET proxy_user 'wronguser'); SELECT * FROM ft; INFO: SPARQL query sent to 'fuseki': SELECT ?s ?p ?o {?s ?p ?o} ERROR: proxy authentication required on server "fuseki" (HTTP 407) DETAIL: ERROR: Cache Access Denied