The Sesame framework comes with a pre-packaged web service (often referred to as the Sesame server). This web service enables deployment of Sesame as an online RDF database server, with multiple SPARQL query endpoints and full update capabilities.
In the default setup of the Sesame server, however, there is no security at all: everybody can access all available Sesame repositories, can query them, add data, remove data, and even change the server configuration (e.g. creating new databases or removing existing ones). Clearly this is not a desirable setup for a server which is publicly accessible.
Fortunately, it is possible to restrict access to a Sesame server, using standard Java web application technology: the Deployment Descriptor.
In this recipe, we will look at setting up some basic security constraints for a Sesame server, using the web application’s deployment descriptor, in combination with basic HTTP authentication. For the purpose of this explanation, we assume you have a default Sesame server running on Apache Tomcat 6.
- 1 Sesame HTTP REST protocol
- 2 The deployment descriptor: web.xml
- 3 Security roles
- 4 Authentication configuration
- 5 Security constraints
- 6 User accounts
- 7 Conclusion and further reading
Sesame HTTP REST protocol
The Sesame server implements a RESTful protocol for HTTP communication (it’s a superset of SPARQL protocol). What that comes down to is that the protocol defines specific locations, reachable by a specific URL using a specific HTTP method (GET, POST, etc.), for each repository and each operation on a repository.
This is good news for our security, as it means we can easily reuse HTTP-based security restrictions: since each operation on a repository maps to a specific URL and a specific method, we can have fairly fine-grained access control by simply restricting access to particular URL patterns and/or HTTP methods.
If that sounds vague, here’s an example: suppose we have a Sesame server running at
http://localhost:8080/openrdf-sesame. Retrieving statements from a repository on that server called ‘test’ is done using a
HTTP GET operation on the URL
http://localhost:8080/openrdf-sesame/repositories/test/statements. So if we want to restrict who can view the statements in that ‘test’ repository, all we have to do is define a security constraint on GET requests for that specific URL.
The following is an overview of the resources and HTTP methods that are available from a Sesame server (copied from section 8.1):
<SESAME_URL> /protocol : protocol version (GET) /repositories : overview of available repositories (GET) /<REP_ID> : query evaluation on a repository (GET/POST) /statements : repository statements (GET/POST/PUT/DELETE) /contexts : context overview (GET) /size : #statements in repository (GET) /namespaces : overview of namespace definitions (GET/DELETE) /<PREFIX> : namespace-prefix definition (GET/PUT/DELETE)
In the REST protocol specification, you will find more detailed descriptions of what each URL and each HTTP method does, but for us right now, it is useful to know that read operations are always done via HTTP GET methods, and write operations are always POST, PUT or DELETE methods.
As said before, defining security constraints on URLs and HTTP methods can be done using deployment desciptors. In the next section, we will look at the Sesame deployment desciptor in more detail.
The deployment descriptor: web.xml
The deployment descriptor for the Sesame server is an XML file called
web.xml. In a standard deployment, this file can be found in the directory
As the name implies, the deployment descriptor configures how the Sesame server web application should be deployed. It contains several configuration settings that we will not touch here (such as mappings from URL patterns to servlets), but it can also contain security constraints, authentication config settings, and a collection of security roles that apply to the application.
Security through Java deployment descriptors is role-based: rather than assigning permissions to specific user accounts, we define an abstract entity called a role, assign permissions to this role, and then (separately) make users members of a particular role. Typical roles are ‘Viewer’, ‘Editor’, ‘Admin’, and so on.
In this recipe, we are going to add three roles to our deployment descriptor:
test-viewer– the role for users who have reading rights on the ‘test’ repository, that is, doing SPARQL queries, exporting statements, etc.
test-editor– the role for users who have editing rights on the ‘test’ repository, that is, doing updates and removing data.
sesame-admin– the role for users with administration rights, that is, users who can create new repositories, change configurations and remove old repositories.
Of course, this is just an example for illustration purposes: what roles you need to define for your application depends entirely on your use case. You may have roles that have access to one or more specific repositories, roles that have access to all repositories, roles that can only read, only write, and so on. Figuring out the optimal configuration for your application is up to you.
Back to our recipe: to add these roles, add the following snippet to the
web.xml file (nested inside the
web-app element – a good spot is somewhere after the last
<security-role> <description> The role that is required for read access to the test repository </description> <role-name>test-viewer</role-name> </security-role> <description> The role that is required for write access to the test repository </description> <role-name>test-editor</role-name> </security-role> <security-role> <description> The role that is required to change the Sesame server configuration </description> <role-name>sesame-admin</role-name> </security-role>
By the way, some advice to avoid losing your work: do not edit the
web.xml file while Tomcat is running, and make sure you keep a backup copy of your changes somewhere, in case the file accidentally gets overwritten with the default deployment descriptor (unlikely, but not impossible).
To enable basic HTTP authentication for the Sesame server, we add the following to our deployment descriptor:
<login-config> <auth-method>BASIC</auth-method> <realm-name>Sesame</realm-name> </login-config>
Once we have set this up, we can start defining security constraints for our Sesame server.
A security constraint minimally consists of a collection of web resources (defined in terms of URL patterns and HTTP methods) and an authorization constraint (the role name that has access to the resource collection).
So, let’s have a look at what we need to do to restrict access. We have first of all defined a role ‘test-viewer’, that is, users who have read access to the test repository. Read access means access to operations such as SPARQL querying, as well as exporting statements, reading namespaces, contexts, and so on.
Defining read access: the
First, let us define a security constraint that allows viewers to do SPARQL queries. If we look at the summary of the Sesame REST protocol specification again we see that queries on a repository are always done via either
POST methods on the url pattern
repositories/[REP_ID]. Since we are looking at defining a restriction for a repository with id ‘test’, the security constraint will look like this:
<security-constraint> <web-resource-collection> <web-resource-name>Sesame test repository: SPARQL query access</web-resource-name> <url-pattern>/repositories/test</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>test-viewer</role-name> <role-name>test-editor</role-name> </auth-constraint> </security-constraint>
As you can see, the security constraint consists of two parts: the
web-resource-collection, which defines on which URLs and HTTP methods the constraint applies, and the
auth-constraint, which assigns the constraint to one or more roles.
The above constraint specifies that any authenticated user with the role ‘test-viewer’ or ‘test-editor’ may perform HTTP
POST operations on the URL
Hang on, didn’t I just say that read operations always correspond to
GET methods? What is that
POST method doing here then? This is the proverbial exception that confirms the rule. The exception is necessary because of practical considerations: some HTTP servers have limits on the length of parameter values for
GET requests, so in order to avoid running into that limitation when doing large SPARQL queries,
POST is also allowed.
Now, as said above, SPARQL querying is not the only kind of read access. The Sesame REST protocol defines several other read operations on a repository. In the summary we can see that we can do
GET operations on various the URLs nested under
/repositories/test, such as
/contexts, etc. However, we can also see that several of these patterns, for example
/statements, also allow other methods, such as
DELETE. We want our viewer role to be able to perform read operations, but not write operations, so we define the following constraint:
<security-constraint> <web-resource-collection> <web-resource-name>Sesame test repository viewer access</web-resource-name> <url-pattern>/repositories/test/*</url-pattern> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <role-name>test-viewer</role-name> <role-name>test-editor</role-name> </auth-constraint> </security-constraint>
In this case, we have restricted access to just the
GETmethod (which captures all read operations), and as you can see, we are using a wildcard to capture all resource URL patterns that hang underneath our test repository.
Note, by the way, that at this point we have not yet defined any security constraints on write operations on the test repository. This means that right now, everybody can do write operations on it. We will fix that in the next section.
Defining write access: the
The next set of security constraints should define who is allowed to have write access to the test repository. The role we have in mind for this is
test-editor We have already given this role the same read access priviliges as the
test-viewer role, but we need to specifically restrict write access to the repository as well, so that only users with this role can do write operations. This is very easily achieved with the following constraint:
<security-constraint> <web-resource-collection> <web-resource-name>Sesame test repository: editor write access</web-resource-name> <url-pattern>/repositories/test/*</url-pattern> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>DELETE</http-method> </web-resource-collection> <auth-constraint> <role-name>test-editor</role-name> </auth-constraint> </security-constraint>
As you can see, full write access to the test repository is granted to the
test-editorby simply assigning it to all URL patterns underneath ‘repositories/test/’ for the methods
DELETE. We do not need to specify
GEThere, since we have already specified that method in another security constraint.
Creating repositories: the
Finally, we are also going to set up a specific role for administration purposes, the
sesame-admin role. This role should be allowed to manage the repositories on the server: creating new ones and deleting old ones.
Repository management on the Sesame server is done via a special repository called
SYSTEM, so we can make sure only the
sesame-admin role can manage repositories by restricting access to this repository:
<security-constraint> <web-resource-collection> <web-resource-name>Sesame System Config Restricted access</web-resource-name> <url-pattern>/repositories/SYSTEM/statements</url-pattern> <url-pattern>/repositories/SYSTEM/namespaces</url-pattern> <url-pattern>/repositories/SYSTEM/namespaces/*</url-pattern> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>DELETE</http-method> </web-resource-collection> <auth-constraint> <role-name>sesame-admin</role-name> </auth-constraint> </security-constraint>
As you can see, we do not restrict read access to the
SYSTEMrepository, only write access. The reason is of course that many client tools for Sesame will want to be able to read the server configuration, so they know which repositories are available.
We have now defined our security constraints and the roles to which we want to apply them. However, we have not yet assigned any user accounts to roles. In fact, we haven’t even defined any users yet. This is something that happens outside the deployment descriptor, and is left to the servlet container.
In Apache Tomcat, user accounts and password management are configured via something called a ‘Realm’. We will not go into too much details here on how to configure this, instead we refer you to the Apache Tomcat Realms HowTo.
However, in a default deployment of Apache Tomcat, a default Realm called
UserDatabaseRealm is active. This realm is basically just a plain XML file, called
tomcat-users.xml, and can be found in
[TOMCAT_DIR]/conf/. You can create user accounts and assign them to roles by simply adding lines to this. For example, let’s say we want to create three user accounts
john should only have viewing access on the test repository,
paul should be allowed to edit it, and
ringo should be allowed to edit the test repository as well as do repository management tasks. We can achieve this by adding the following three lines to
<user username="john" password="letitbe" roles="test-viewer"/> <user username="paul" password="heyjude" roles="test-editor"/> <user username="ringo" password="yellowsub" roles="test-editor, sesame-admin"/>
As you can see, you can assign a user to more than one role. What is also immediately apparent is that this way of specifying user accounts is not particularly secure: the passwords are defined in plain-text. Using the default
UserDatabaseRealmis very useful for quick testing and debugging of your security setup, but for production deployments I would strongly recommend looking into some of the more advanced Realm configurations that Apache Tomcat offers.
Conclusion and further reading
In this recipe I have shown how you can configure very basic repository-based security for a Sesame server. You will need to adapt, adopt and improve this basic recipe for your specific purposes: likely you will need different roles, different security constraints. You will probably also need to configure a more secure way of managing user accounts than what is shown here, and perhaps you will also need to use something more secure than basic HTTP authentication (for example, HTTPS Client-Cert authentication).
Some useful links for further reading on these topics:
- web.xml Deployment Descriptor elements – full description of the precise structure and syntax of the web.xml file.
- Understanding Web Security using web.xml – a couple of useful examples of various security constraint patterns.
- Apache Tomcat Realms HowTo
Finally, I should point out one rather lamentable fact: the OpenRDF Workbench, which is the default web-based client tool for Sesame, currently has no support for basic HTTP authentication. Fortunately, other client tools, such as the Sesame Console and the Sesame Windows Client do support HTTP authentication, so you’re not completely on your own.