Protecting And Sharing Linked Data With Virtuoso


Disclaimer: Many of the features presented here are rather new and can not be found in  the open-source version of Virtuoso.

Last time we saw how to share files and folders stored in the Virtuoso DAV system. Today we will protect and share data stored in Virtuoso’s Triple Store – we will share RDF data.

Virtuoso is actually a quadruple-store which means each triple lives in a named graph. In Virtuoso named graphs can be public or private (in reality it is a bit more complex than that but this view on things is sufficient for our purposes), public graphs being readable and writable by anyone who has permission to read or write in general, private graphs only being readable and writable by administrators and those to which named graph permissions have been granted. The latter case is what interests us today.

We will start by inserting some triples into a named graph as dba – the master of the Virtuoso universe:

Virtuoso Sparql Endpoint

Sparql Result

This graph is now public and can be queried by anyone. Since we want to make it private we quickly need to change into a SQL session since this part is typically performed by an application rather than manually:

$ isql-v localhost:1112 dba dba
Connected to OpenLink Virtuoso
Driver: 07.10.3211 OpenLink Virtuoso ODBC Driver
OpenLink Interactive SQL (Virtuoso), version 0.9849b.
Type HELP; for help and EXIT; to exit.
SQL> DB.DBA.RDF_GRAPH_GROUP_INS ('http://www.openlinksw.com/schemas/virtrdf#PrivateGraphs', 'urn:trueg:demo');

Done. -- 2 msec.

Now our new named graph urn:trueg:demo is private and its contents cannot be seen by anyone. We can easily test this by logging out and trying to query the graph:

Sparql Query
Sparql Query Result

But now we want to share the contents of this named graph with someone. Like before we will use my LinkedIn account. This time, however, we will not use a UI but Virtuoso’s RESTful ACL API to create the necessary rules for sharing the named graph. The API uses Turtle as its main input format. Thus, we will describe the ACL rule used to share the contents of the named graph as follows.

@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix oplacl: <http://www.openlinksw.com/ontology/acl#> .
<#rule> a acl:Authorization ;
  rdfs:label "Share Demo Graph with trueg's LinkedIn account" ;
  acl:agent <http://www.linkedin.com/in/trueg> ;
  acl:accessTo <urn:trueg:demo> ;
  oplacl:hasAccessMode oplacl:Read ;
  oplacl:hasScope oplacl:PrivateGraphs .

Virtuoso makes use of the ACL ontology proposed by the W3C and extends on it with several custom classes and properties in the OpenLink ACL Ontology. Most of this little Turtle snippet should be obvious: we create an Authorization resource which grants Read access to urn:trueg:demo for agent http://www.linkedin.com/in/trueg. The only tricky part is the scope. Virtuoso has the concept of ACL scopes which group rules by their resource type. In this case the scope is private graphs, another typical scope would be DAV resources.

Given that file rule.ttl contains the above resource we can post the rule via the RESTful ACL API:

$ curl -X POST --data-binary @rule.ttl -H"Content-Type: text/turtle" -u dba:dba http://localhost:8890/acl/rules

As a result we get the full rule resource including additional properties added by the API.

Finally we will login using my LinkedIn identity and are granted read access to the graph:

SPARQL Endpoint  Login
sparql6
sparql7
sparql8

We see all the original triples in the private graph. And as before with DAV resources no local account is necessary to get access to named graphs. Of course we can also grant write access, use groups, etc.. But those are topics for another day.

Technical Footnote

Using ACLs with named graphs as described in this article requires some basic configuration. The ACL system is disabled by default. In order to enable it for the default application realm (another topic for another day) the following SPARQL statement needs to be executed as administrator:

sparql
prefix oplacl: <http://www.openlinksw.com/ontology/acl#>
with <urn:virtuoso:val:config>
delete {
  oplacl:DefaultRealm oplacl:hasDisabledAclScope oplacl:Query , oplacl:PrivateGraphs .
}
insert {
  oplacl:DefaultRealm oplacl:hasEnabledAclScope oplacl:Query , oplacl:PrivateGraphs .
};

This will enable ACLs for named graphs and SPARQL in general. Finally the LinkedIn account from the example requires generic SPARQL read permissions. The simplest approach is to just allow anyone to SPARQL read:

@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix oplacl: <http://www.openlinksw.com/ontology/acl#> .
<#rule> a acl:Authorization ;
  rdfs:label "Allow Anyone to SPARQL Read" ;
  acl:agentClass foaf:Agent ;
  acl:accessTo <urn:virtuoso:access:sparql> ;
  oplacl:hasAccessMode oplacl:Read ;
  oplacl:hasScope oplacl:Query .

I will explain these technical concepts in more detail in another article.

14 thoughts on “Protecting And Sharing Linked Data With Virtuoso

  1. Pingback: Protecting And Sharing Linked Data With Virtuoso | Bartle Doo Articles

  2. Pingback: Links 3/9/2014: Android Gadgets, New Tails OS | Techrights

  3. Pingback: Conditional Sharing – Virtuoso ACL Groups Revisited | Trueg's Blog

  4. Hi there,
    thanks for this and other posts they are very helpful!
    In a java server application I want to access the entry point on behalf of the user logged in via our client web app, is there some way to use Virtuoso ACL only providing the user URI?

    That is, as a java server, I’d like to get all the graphs a user of mine can read.

    Thank you,
    Danilo

    • Hello Danilo,

      yes, that can be achieved by manually activating the ACLs. However, the sparql endpoint does not allow that atm as it creates the prefix mentioned below itself. You could, however, connect to Virtuoso via JDBC and then enforce ACLs using the sparql extensions we put in place. You could connect as “dba” but I recommend a user which has the SPARQL_UPDATE role and default access to all graphs according to the “classical” graph security in Virtuoso.

      Given a user IRI like “urn:me” the following prefix should be added to each query:

      define sql:gs-app-callback "VAL_SPARQL_PERMS" define sql:gs-app-uid "urn:me"

      I hope this helps.

      Regards,
      Sebastian

      • Hi Sebastian, regarding your reply i’m wondering if the *urn:me* URI identifies a Virtuoso user.
        I mean the java server application stores the users in Virtuoso triple store as type foaf:Person, but does not create the user by using DB.DBA.USER_CREATE procedure.
        Will, your example still work?

        Thanks
        Regards

        • Hi Susanna,

          urn:me is merely an example which is unrelated to any Virtuoso account. The ACL system I present here is independent of Virtuoso users. Thus, if you define ACLs, granting urn:me access to certain graphs, then the prefix I presented will take those into account. There is no Virtuoso user, other than the one you use for JDBC access, involved.

          Regards,
          Sebastian

            • I’m sorry but last doubt came to my mind :)
              In your example you connect via Linkedin account to Virtuoso.
              (This operation is done by using a particular module for Virtuoso i think) and then you try to query the graph.
              So in this case you are acting as a Virtuoso user, I think, and the system will show (or not if you don’t have grants) the triples in the named graph cause your account is identified by URI
              As your previous reply this behaviour could be simulated by our java application by using
              define sql:gs-app-callback “VAL_SPARQL_PERMS” define sql:gs-app-uid “urn:me”
              before the queries
              Am I right?

              Sorry for all these questions :D

              Thanks a lot again.

            • Hello Susanna,

              first of all: do not apologize for asking these questions. I am happy to answer. :)

              When I log into the sparql endpoint with my LinkedIn identity there is no Virtuoso user account involved (there might be a connected one but that is out-of-scope here). That means Virtuoso simply identifies me via my LinkedIn URI which is https://www.linkedin.com/in/trueg.

              In that case the sparql endpoint will use the following prefix:

              define sql:gs-app-callback “VAL_SPARQL_PERMS” define sql:gs-app-uid “https://www.linkedin.com/in/trueg"

              Regards,
              Sebastian

  5. (I can’t reply to the post in question, I suppose we’ve reached the max depth for comments)

    Sebastian,
    you said “Sorry, the ACL engine is restricted to Virtuoso closed source at this point.” but from this page http://virtuoso.openlinksw.com/features-comparison-matrix/ the only missing features in the OS version of virtuoso 7 are:
    – Federated External 3rd Party Databases (Heterogeneous Relational Data Virtualization)
    – Clustering
    – Data replication

    On the other hand it doesn’t even state that it’s included… it just doesn’t mention it (I guess the Row Level ACLS is another thing, right?)

    I understand you work for Openlink and on these very stuff, so you surely know the matter better than I do, but are you sure the ACL engine is not also included in the OS version of Virtuoso 7?

    Thanks a lot,
    Danilo

    • Hello Danilo,

      Virtuoso closed-source only supports the “old” ACL system which allows to define rules mapping certain WebIDs to a Virtuoso SQL user. This SQL user in turn can have access to certain graphs using role-based security.
      Virtuoso 7 closed source has the new ACL system I presented in my blog entries.
      I hope this clears it up. :)

      Regards,
      Sebastian

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s