diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2023-03-06 15:24:51 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2023-03-19 22:54:02 +0100 |
commit | 2e40af7c5fbfc2c057487d12d1b926b11185b6ea (patch) | |
tree | 226cffa3f2be22898de79500734936160c0857f6 /docs | |
parent | a9fb50417dd4cd5a8a00efdf5400cb63e8c07d8e (diff) | |
download | tracker-2e40af7c5fbfc2c057487d12d1b926b11185b6ea.tar.gz |
docs: Separate sandboxing documentation to its own doc
Explain this a bit better, add some diagrams, etc.
Diffstat (limited to 'docs')
7 files changed, 386 insertions, 25 deletions
diff --git a/docs/reference/libtracker-sparql/images/graph-example-diagram.dot b/docs/reference/libtracker-sparql/images/graph-example-diagram.dot new file mode 100644 index 000000000..56827d7f3 --- /dev/null +++ b/docs/reference/libtracker-sparql/images/graph-example-diagram.dot @@ -0,0 +1,28 @@ +digraph { + rankdir=LR; + fontname="sans-serif"; + compound=true; + node [shape="box", style="rounded", border=0, fontname="sans-serif"]; + + subgraph cluster_graph2 { + style="rounded"; + color="lightgrey"; + label = "example:B" + tooltip = "example:B" + fontsize=10; + item2[label="example:item2",tooltip="example:item2"]; + type2[label="rdfs:Resource",tooltip="rdfs:Resource"]; + item2 -> type2 [label="rdf:type",fontsize=10,fontname="sans-serif",tooltip="rdf:type",labeltooltip="rdf:type"]; + } + + subgraph cluster_graph1 { + style="rounded"; + color="lightgrey"; + label = "example:A" + tooltip = "example:A" + fontsize=10; + item1[label="example:item1",tooltip="example:item1"]; + type1[label="rdfs:Resource",tooltip="rdfs:Resource"]; + item1 -> type1 [label="rdf:type",fontsize=10,fontname="sans-serif",tooltip="rdf:type",labeltooltip="rdf:type"]; + } +} diff --git a/docs/reference/libtracker-sparql/images/graph-example-diagram.svg b/docs/reference/libtracker-sparql/images/graph-example-diagram.svg new file mode 100644 index 000000000..384bb9c57 --- /dev/null +++ b/docs/reference/libtracker-sparql/images/graph-example-diagram.svg @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 7.1.0 (0) + --> +<!-- Pages: 1 --> +<svg width="335pt" height="174pt" + viewBox="0.00 0.00 335.00 174.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 170)"> +<polygon fill="white" stroke="none" points="-4,4 -4,-170 331,-170 331,4 -4,4"/> +<g id="clust1" class="cluster"> +<title>cluster_graph2</title> +<g id="a_clust1"><a xlink:title="example:B"> +<path fill="none" stroke="lightgrey" d="M20,-8C20,-8 307,-8 307,-8 313,-8 319,-14 319,-20 319,-20 319,-67 319,-67 319,-73 313,-79 307,-79 307,-79 20,-79 20,-79 14,-79 8,-73 8,-67 8,-67 8,-20 8,-20 8,-14 14,-8 20,-8"/> +<text text-anchor="middle" x="163.5" y="-67" font-family="sans-serif" font-size="10.00">example:B</text> +</a> +</g> +</g> +<g id="clust2" class="cluster"> +<title>cluster_graph1</title> +<g id="a_clust2"><a xlink:title="example:A"> +<path fill="none" stroke="lightgrey" d="M20,-87C20,-87 307,-87 307,-87 313,-87 319,-93 319,-99 319,-99 319,-146 319,-146 319,-152 313,-158 307,-158 307,-158 20,-158 20,-158 14,-158 8,-152 8,-146 8,-146 8,-99 8,-99 8,-93 14,-87 20,-87"/> +<text text-anchor="middle" x="163.5" y="-146" font-family="sans-serif" font-size="10.00">example:A</text> +</a> +</g> +</g> +<!-- item2 --> +<g id="node1" class="node"> +<title>item2</title> +<g id="a_node1"><a xlink:title="example:item2"> +<path fill="none" stroke="black" d="M118,-52C118,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 118,-16 118,-16 124,-16 130,-22 130,-28 130,-28 130,-40 130,-40 130,-46 124,-52 118,-52"/> +<text text-anchor="middle" x="73" y="-30.3" font-family="sans-serif" font-size="14.00">example:item2</text> +</a> +</g> +</g> +<!-- type2 --> +<g id="node2" class="node"> +<title>type2</title> +<g id="a_node2"><a xlink:title="rdfs:Resource"> +<path fill="none" stroke="black" d="M299,-52C299,-52 216,-52 216,-52 210,-52 204,-46 204,-40 204,-40 204,-28 204,-28 204,-22 210,-16 216,-16 216,-16 299,-16 299,-16 305,-16 311,-22 311,-28 311,-28 311,-40 311,-40 311,-46 305,-52 299,-52"/> +<text text-anchor="middle" x="257.5" y="-30.3" font-family="sans-serif" font-size="14.00">rdfs:Resource</text> +</a> +</g> +</g> +<!-- item2->type2 --> +<g id="edge1" class="edge"> +<title>item2->type2</title> +<g id="a_edge1"><a xlink:title="rdf:type"> +<path fill="none" stroke="black" d="M130.25,-34C149.86,-34 172.02,-34 192.23,-34"/> +<polygon fill="black" stroke="black" points="192.04,-37.5 202.04,-34 192.04,-30.5 192.04,-37.5"/> +</a> +</g> +<g id="a_edge1-label"><a xlink:title="rdf:type"> +<text text-anchor="middle" x="167" y="-37" font-family="sans-serif" font-size="10.00">rdf:type</text> +</a> +</g> +</g> +<!-- item1 --> +<g id="node3" class="node"> +<title>item1</title> +<g id="a_node3"><a xlink:title="example:item1"> +<path fill="none" stroke="black" d="M118,-131C118,-131 28,-131 28,-131 22,-131 16,-125 16,-119 16,-119 16,-107 16,-107 16,-101 22,-95 28,-95 28,-95 118,-95 118,-95 124,-95 130,-101 130,-107 130,-107 130,-119 130,-119 130,-125 124,-131 118,-131"/> +<text text-anchor="middle" x="73" y="-109.3" font-family="sans-serif" font-size="14.00">example:item1</text> +</a> +</g> +</g> +<!-- type1 --> +<g id="node4" class="node"> +<title>type1</title> +<g id="a_node4"><a xlink:title="rdfs:Resource"> +<path fill="none" stroke="black" d="M299,-131C299,-131 216,-131 216,-131 210,-131 204,-125 204,-119 204,-119 204,-107 204,-107 204,-101 210,-95 216,-95 216,-95 299,-95 299,-95 305,-95 311,-101 311,-107 311,-107 311,-119 311,-119 311,-125 305,-131 299,-131"/> +<text text-anchor="middle" x="257.5" y="-109.3" font-family="sans-serif" font-size="14.00">rdfs:Resource</text> +</a> +</g> +</g> +<!-- item1->type1 --> +<g id="edge2" class="edge"> +<title>item1->type1</title> +<g id="a_edge2"><a xlink:title="rdf:type"> +<path fill="none" stroke="black" d="M130.25,-113C149.86,-113 172.02,-113 192.23,-113"/> +<polygon fill="black" stroke="black" points="192.04,-116.5 202.04,-113 192.04,-109.5 192.04,-116.5"/> +</a> +</g> +<g id="a_edge2-label"><a xlink:title="rdf:type"> +<text text-anchor="middle" x="167" y="-116" font-family="sans-serif" font-size="10.00">rdf:type</text> +</a> +</g> +</g> +</g> +</svg> diff --git a/docs/reference/libtracker-sparql/images/sandbox-diagram.dot b/docs/reference/libtracker-sparql/images/sandbox-diagram.dot new file mode 100644 index 000000000..d8b9c505b --- /dev/null +++ b/docs/reference/libtracker-sparql/images/sandbox-diagram.dot @@ -0,0 +1,45 @@ +graph { + rankdir=LR; + fontname="sans-serif"; + compound=true; + node [shape="box", style="rounded", border=0, fontname="sans-serif"]; + + subgraph cluster_session { + style="rounded"; + color="lightgrey"; + label = "User session" + tooltip = "User session" + fontsize=10; + + Portal; + node [shape="cylinder"];"Provider #1"; "Provider #2"; + + "Provider #1" -- Portal; + "Provider #2" -- Portal; + } + + subgraph cluster_client1 { + style="dashed"; + color="lightgrey"; + label = "Sandbox #1" + tooltip = "Sandbox #1" + fontsize=10; + "App A"; + node [shape="cylinder"]; "Provider #3"; + "App A" -- "Provider #3"; + } + + subgraph cluster_client2 { + style="dashed"; + color="lightgrey"; + label = "Sandbox #2" + tooltip = "Sandbox #2" + fontsize=10; + "App B"; + node [shape="cylinder";style="invis"]; "Provider #4"; + "App B" -- "Provider #4" [style="invis"]; + } + + Portal -- "App A" [lhead=cluster_client1]; + Portal -- "App B" [lhead=cluster_client2]; +} diff --git a/docs/reference/libtracker-sparql/images/sandbox-diagram.svg b/docs/reference/libtracker-sparql/images/sandbox-diagram.svg new file mode 100644 index 000000000..ac643ad10 --- /dev/null +++ b/docs/reference/libtracker-sparql/images/sandbox-diagram.svg @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 7.1.0 (0) + --> +<!-- Pages: 1 --> +<svg width="443pt" height="174pt" + viewBox="0.00 0.00 443.00 174.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 170)"> +<polygon fill="white" stroke="none" points="-4,4 -4,-170 439,-170 439,4 -4,4"/> +<g id="clust1" class="cluster"> +<title>cluster_session</title> +<g id="a_clust1"><a xlink:title="User session"> +<path fill="none" stroke="lightgrey" d="M20,-20C20,-20 196,-20 196,-20 202,-20 208,-26 208,-32 208,-32 208,-133 208,-133 208,-139 202,-145 196,-145 196,-145 20,-145 20,-145 14,-145 8,-139 8,-133 8,-133 8,-32 8,-32 8,-26 14,-20 20,-20"/> +<text text-anchor="middle" x="108" y="-133" font-family="sans-serif" font-size="10.00">User session</text> +</a> +</g> +</g> +<g id="clust2" class="cluster"> +<title>cluster_client1</title> +<g id="a_clust2"><a xlink:title="Sandbox #1"> +<polygon fill="none" stroke="lightgrey" stroke-dasharray="5,2" points="228,-87 228,-158 427,-158 427,-87 228,-87"/> +<text text-anchor="middle" x="327.5" y="-146" font-family="sans-serif" font-size="10.00">Sandbox #1</text> +</a> +</g> +</g> +<g id="clust3" class="cluster"> +<title>cluster_client2</title> +<g id="a_clust3"><a xlink:title="Sandbox #2"> +<polygon fill="none" stroke="lightgrey" stroke-dasharray="5,2" points="228,-8 228,-79 427,-79 427,-8 228,-8"/> +<text text-anchor="middle" x="327.5" y="-67" font-family="sans-serif" font-size="10.00">Sandbox #2</text> +</a> +</g> +</g> +<!-- Portal --> +<g id="node1" class="node"> +<title>Portal</title> +<path fill="none" stroke="black" d="M188,-91C188,-91 156,-91 156,-91 150,-91 144,-85 144,-79 144,-79 144,-67 144,-67 144,-61 150,-55 156,-55 156,-55 188,-55 188,-55 194,-55 200,-61 200,-67 200,-67 200,-79 200,-79 200,-85 194,-91 188,-91"/> +<text text-anchor="middle" x="172" y="-69.3" font-family="sans-serif" font-size="14.00">Portal</text> +</g> +<!-- App A --> +<g id="node4" class="node"> +<title>App A</title> +<path fill="none" stroke="black" d="M279,-131C279,-131 248,-131 248,-131 242,-131 236,-125 236,-119 236,-119 236,-107 236,-107 236,-101 242,-95 248,-95 248,-95 279,-95 279,-95 285,-95 291,-101 291,-107 291,-107 291,-119 291,-119 291,-125 285,-131 279,-131"/> +<text text-anchor="middle" x="263.5" y="-109.3" font-family="sans-serif" font-size="14.00">App A</text> +</g> +<!-- Portal--App A --> +<g id="edge5" class="edge"> +<title>Portal--App A</title> +<path fill="none" stroke="black" d="M200.34,-85.22C209.06,-89.12 218.84,-93.49 228,-97.58"/> +</g> +<!-- App B --> +<g id="node6" class="node"> +<title>App B</title> +<path fill="none" stroke="black" d="M279,-52C279,-52 248,-52 248,-52 242,-52 236,-46 236,-40 236,-40 236,-28 236,-28 236,-22 242,-16 248,-16 248,-16 279,-16 279,-16 285,-16 291,-22 291,-28 291,-28 291,-40 291,-40 291,-46 285,-52 279,-52"/> +<text text-anchor="middle" x="263.5" y="-30.3" font-family="sans-serif" font-size="14.00">App B</text> +</g> +<!-- Portal--App B --> +<g id="edge6" class="edge"> +<title>Portal--App B</title> +<path fill="none" stroke="black" d="M200.34,-61.09C209.06,-57.28 218.84,-53.03 228,-49.03"/> +</g> +<!-- Provider #1 --> +<g id="node2" class="node"> +<title>Provider #1</title> +<path fill="none" stroke="black" d="M108,-114.73C108,-116.53 87.38,-118 62,-118 36.62,-118 16,-116.53 16,-114.73 16,-114.73 16,-85.27 16,-85.27 16,-83.47 36.62,-82 62,-82 87.38,-82 108,-83.47 108,-85.27 108,-85.27 108,-114.73 108,-114.73"/> +<path fill="none" stroke="black" d="M108,-114.73C108,-112.92 87.38,-111.45 62,-111.45 36.62,-111.45 16,-112.92 16,-114.73"/> +<text text-anchor="middle" x="62" y="-96.3" font-family="sans-serif" font-size="14.00">Provider #1</text> +</g> +<!-- Provider #1--Portal --> +<g id="edge1" class="edge"> +<title>Provider #1--Portal</title> +<path fill="none" stroke="black" d="M108.49,-88.63C120.48,-85.63 133.04,-82.49 143.74,-79.82"/> +</g> +<!-- Provider #2 --> +<g id="node3" class="node"> +<title>Provider #2</title> +<path fill="none" stroke="black" d="M108,-60.73C108,-62.53 87.38,-64 62,-64 36.62,-64 16,-62.53 16,-60.73 16,-60.73 16,-31.27 16,-31.27 16,-29.47 36.62,-28 62,-28 87.38,-28 108,-29.47 108,-31.27 108,-31.27 108,-60.73 108,-60.73"/> +<path fill="none" stroke="black" d="M108,-60.73C108,-58.92 87.38,-57.45 62,-57.45 36.62,-57.45 16,-58.92 16,-60.73"/> +<text text-anchor="middle" x="62" y="-42.3" font-family="sans-serif" font-size="14.00">Provider #2</text> +</g> +<!-- Provider #2--Portal --> +<g id="edge2" class="edge"> +<title>Provider #2--Portal</title> +<path fill="none" stroke="black" d="M108.49,-57.37C120.48,-60.37 133.04,-63.51 143.74,-66.18"/> +</g> +<!-- Provider #3 --> +<g id="node5" class="node"> +<title>Provider #3</title> +<path fill="none" stroke="black" d="M419,-127.73C419,-129.53 398.38,-131 373,-131 347.62,-131 327,-129.53 327,-127.73 327,-127.73 327,-98.27 327,-98.27 327,-96.47 347.62,-95 373,-95 398.38,-95 419,-96.47 419,-98.27 419,-98.27 419,-127.73 419,-127.73"/> +<path fill="none" stroke="black" d="M419,-127.73C419,-125.92 398.38,-124.45 373,-124.45 347.62,-124.45 327,-125.92 327,-127.73"/> +<text text-anchor="middle" x="373" y="-109.3" font-family="sans-serif" font-size="14.00">Provider #3</text> +</g> +<!-- App A--Provider #3 --> +<g id="edge3" class="edge"> +<title>App A--Provider #3</title> +<path fill="none" stroke="black" d="M291.35,-113C302.05,-113 314.66,-113 326.69,-113"/> +</g> +<!-- Provider #4 --> +<!-- App B--Provider #4 --> +</g> +</svg> diff --git a/docs/reference/libtracker-sparql/meson.build b/docs/reference/libtracker-sparql/meson.build index e49b31d8a..43f2e8880 100644 --- a/docs/reference/libtracker-sparql/meson.build +++ b/docs/reference/libtracker-sparql/meson.build @@ -89,6 +89,7 @@ endforeach generated_content_files = [ 'examples.md.in', 'tutorial.md.in', + 'sandboxing.md.in', ] generated_content = [] diff --git a/docs/reference/libtracker-sparql/overview.md b/docs/reference/libtracker-sparql/overview.md index 949d81c3f..cf183fe3d 100644 --- a/docs/reference/libtracker-sparql/overview.md +++ b/docs/reference/libtracker-sparql/overview.md @@ -32,28 +32,3 @@ one exposed by Tracker Miner FS, use [ctor@Tracker.SparqlConnection.bus_new]. To connect to another a database on a remote machine, use [ctor@Tracker.SparqlConnection.remote_new]. This can be used to query online databases that provide a SPARQL endpoint, such as [DBpedia](https://wiki.dbpedia.org/about). - . -## Connecting from Flatpak - -Tracker SPARQL provides a portal for the [Flatpak](https://flatpak.org/) -application sandboxing system. This lets you control which parts of a -database each app can query. - -The app's Flatpak manifest needs to specify which graph(s) the app will -access. See the [example app](https://gitlab.gnome.org/GNOME/tracker/-/blob/master/examples/flatpak/org.example.TrackerSandbox.json) -and the [portal documentation](https://gnome.pages.gitlab.gnome.org/tracker/docs/commandline/#tracker-xdg-portal-3) to see how. - -No code changes are needed in the app, as [ctor@Tracker.SparqlConnection.bus_new] -will automatically try connect via the portal if it can't talk to the -given D-Bus name directly. - -Tracker SPARQL is included in the -[GNOME Flatpak SDK and runtime](https://docs.flatpak.org/en/latest/available-runtimes.html#gnome). -If the app uses a different runtime, you may need to build Tracker -SPARQL in the app manifest. - -The app might use the Tracker Miner FS search index. Ideally this is done via the portal, -using the search index maintained on the host. Since not all OSes ship tracker-miner-fs-3, -we recommend that apps bundle it inside the Flatpak and connect to the bundled version as -a fallback. See [GNOME Music](https://gitlab.gnome.org/GNOME/gnome-music/) -for an example of how to do this. diff --git a/docs/reference/libtracker-sparql/sandboxing.md.in b/docs/reference/libtracker-sparql/sandboxing.md.in new file mode 100644 index 000000000..02fdb0613 --- /dev/null +++ b/docs/reference/libtracker-sparql/sandboxing.md.in @@ -0,0 +1,120 @@ +Title: Sandboxing and portals +slug: sandboxing-and-portals + +There are times when it does make sense to lend advanced querying +capabilities around your data to other processes of the same machine, +or even widely available to any application that might want to make +use of it. One real life example of this is [Tracker Miners](https://gitlab.gnome.org/GNOME/tracker-miners) +used as the [GNOME Desktop](https://gnome.org) indexer. + +But in this day and age, it is naive to make this data available +without constraints on what data can be accessed. Tracker provides a +portal for the [Flatpak](https://flatpak.org/) application sandboxing +system. This provides the mechanisms to filter the available data for +sandboxed users. + +# How it works + +The portal acts as a single entry point for sandboxed applications +to have read access to any D-Bus SPARQL endpoint. + +<div class="docblock"> +{{ images/sandbox-diagram.svg }} +</div> + +The partitioning of the data is decided by the data provider at +the time of inserting this data in the RDF triple store, and relies +on graphs as the natural partitioning scheme of RDF data. As an +example, consider the following updates: + +```SPARQL +INSERT DATA { + GRAPH example:A { + example:item1 a rdfs:Resource ; + } + + GRAPH example:B { + example:item2 a rdfs:Resource ; + } +} +``` + +Resulting in the following simple diagram: + +<div class="docblock"> +{{ images/graph-example-diagram.svg }} +</div> + +At that point, SPARQL queries may target either, both or any graph, e.g.: + +```SPARQL +# This will return example:item1 +SELECT ?element +FROM example:A +{ + ?element a rdfs:Resource +} +``` + +Or perhaps even poke at non-existing graphs: + +```SPARQL +# This will return no elements +SELECT ?element +FROM example:C +{ + ?element a rdfs:Resource +} +``` + +Graphs may overlap with other graphs, or extend each other. + +The data filtering performed by the portal strongly relies on these RDF +semantics for graphs, except that graph access is enforced through the +[`CONSTRAINT` syntax](sparql-and-tracker.html#constraint-syntax). These +policies prevail over any other SPARQL syntax to specify graphs, and +will result in filtered graphs being replaced by an empty graph. + +Likewise, notification of changes through [class@Tracker.Notifier] will +be filtered on the way to sandboxed applications, so that there are only +notifications on changes from the allowed graphs. + +# Using it from data providers + +Data providers are free to decide the data partitioning scheme available +to sandboxed applications, by creating graphs and inserting data to +those. Access to those graphs will be policied by the portal on their +behalf. + +Keep in mind that there are limits on the [number of graphs](limits.html#limits-on-the-number-of-graphs) +that apply on graph creation. + +# Using it from applications + +The portal is transparently integrated in the Tracker library. Applications +may write SPARQL queries so that they work the same while sandboxed or not. +No code changes are needed in the app, as [ctor@Tracker.SparqlConnection.bus_new] +will automatically try connect via the portal if it can not talk to the +given D-Bus name directly. + +The policy on the accessed graphs is usually defined in the flatpak manifest +at the time of bundling the software, e.g.: + +```json +{ + "finish-args" : [ + "--add-policy=Tracker3.dbus:org.example.Endpoint=example:A", + "--add-policy=Tracker3.dbus:org.example.Endpoint=example:B" + ] +} +``` + +The portal will pick the policy from the `/.flatpak-info` file created +by Flatpak, and (with the example arguments) allow access to graphs `example:A` +and `example:B` from the `org.example.Endpoint` D-Bus SPARQL endpoint. +Access to other graphs, or other services will be disallowed. + +The Tracker library is included in the +[GNOME Flatpak SDK and runtime](https://docs.flatpak.org/en/latest/available-runtimes.html#gnome). +If the app uses a different runtime, you may need to build Tracker +SPARQL in the app manifest. |