Skip to content

Commit

Permalink
Change Tomcat Valve to servlet Filter (#11)
Browse files Browse the repository at this point in the history
* Value -> Filter

* Fix build.gradle and add javadoc to SynFilter.

* Update supplied config file and README

* Additional test coverage

* Fix relative settings path, still fails test.

* Code review, fix variable names, use try-with-resource
  • Loading branch information
whikloj authored and dannylamb committed Nov 21, 2018
1 parent 4b3ed30 commit 9482e95
Show file tree
Hide file tree
Showing 24 changed files with 1,805 additions and 1,514 deletions.
55 changes: 20 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## Description

A valve for Tomcat8 that authenticates the JWT tokens created by Islandora in order to provide sessionless Authentication for Fedora4. Named after the Norse goddess [Syn](https://en.wikipedia.org/wiki/Syn_(goddess)).
A ServletFilter that authenticates the JWT tokens created by Islandora in order to provide sessionless Authentication for Fedora4. Named after the Norse goddess [Syn](https://en.wikipedia.org/wiki/Syn_(goddess)).

## Building

Expand All @@ -15,54 +15,39 @@ This project requires Java 8 and can be built with [Gradle](https://gradle.org).
## Installing

### Copy Syn JAR
Copy the JAR that was built above from `build/libs/islandora-syn-X.X.X-all.jar` and place into `$TOMCAT_HOME/lib` directory. Can be found in Ubuntu at: `/var/lib/tomcat8/lib/`. Note that this JAR is built to contain all the dependancies.
Copy the JAR that was built above from `build/libs/islandora-syn-X.X.X-all.jar` and place into `$TOMCAT_HOME/lib` directory or the individual webapps `WEB-INF/lib` directory. Can be found in Ubuntu at: `/var/lib/tomcat8/lib/`. Note that this JAR is built to contain all the dependancies.

### Register Valve
Now register the valve in Tomcat configuration file.
In Ubuntu this file is located at: `/var/lib/tomcat8/conf/context.xml`
### Register Filter
Now register the filter in web applications' `web.xml` file by adding something like.

```xml
<Valve className="ca.islandora.syn.valve.SynValve"
pathname="conf/syn-settings.xml" />
<filter>
<filter-name>SynFilter</filter-name>
<filter-class>ca.islandora.syn.valve.SynFilter</filter-class>
<init-param>
<param-name>settings-path</param-name>
<param-value>/var/lib/tomcat8/conf/syn-settings.yml</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>SynFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```

where:
* ***pathname***: The location of the settings file. Defaults to `$CATALINA_BASE/conf/syn-settings.xml`.

### Enable `security-contraint`
The valve checks if requested url is under **security contraints**. So, valve will activate only if the Fedora4 *web.xml* file contains something like:

```xml
<security-constraint>
<web-resource-collection>
<web-resource-name>Fedora4</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-role>
<role-name>islandora</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>fcrepo</realm-name>
</login-config>
```
Where the **settings-path** `param-value` is the the location of the settings file.

On ubuntu this file can be found at:
`/var/lib/tomcat8/webapps/fcrepo/WEB-INF/web.xml`

### Setup Syn Configuration
Modify the [example configuration](./conf/syn-settings.example.xml) and move it to: `$CATALINA_BASE/conf/syn-settings.xml`.
Modify the [example configuration](./conf/syn-settings.example.yaml) and move it to: `$CATALINA_BASE/conf/syn-settings.xml`. Then use this path when configuring the application's filter `init-param`s.

## Maintainers

* [Jonathan Green](https://github.com/jonathangreen/)
* [Jared Whiklo](https://github.com/whikloj)

## Development

Expand Down
52 changes: 43 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ targetCompatibility = 1.8

def tomcatVersion = '8.0.28'

ext {

versions = [
bcprov : '1.56',
jackson : '2.9.2',
javaJwt : '3.1.0',
junit : '4.12',
logback : '1.0.13',
mockito : '2.7.14',
servlet : '3.0.1',
slf4j : '1.7.12'
]
}

checkstyle {
configFile = rootProject.file('gradle/checkstyle/checkstyle.xml')
configProperties.checkstyleConfigDir = rootProject.file('gradle/checkstyle')
Expand All @@ -24,15 +38,17 @@ repositories {
}

dependencies {
compile group: 'com.auth0', name: 'java-jwt', version:'3.1.0'
compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version:'1.56'
compileOnly group: 'org.apache.tomcat', name: 'tomcat-catalina', version:tomcatVersion
compileOnly group: 'org.apache.tomcat', name: 'tomcat-coyote', version:tomcatVersion

testCompile group: 'junit', name: 'junit', version:'4.12'
testCompile group: 'org.mockito', name: 'mockito-core', version:'2.7.14'
testCompile group: 'org.apache.tomcat', name: 'tomcat-catalina', version:tomcatVersion
testCompile group: 'org.apache.tomcat', name: 'tomcat-coyote', version:tomcatVersion
compile group: 'com.auth0', name: 'java-jwt', version: versions.javaJwt
compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: versions.bcprov
compile group: 'org.slf4j', name: 'slf4j-api', version: versions.slf4j
compile group: 'javax.servlet', name: 'javax.servlet-api', version: versions.servlet
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: versions.jackson
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: versions.jackson

testRuntime group: 'ch.qos.logback', name: 'logback-classic', version: versions.logback

testCompile group: 'junit', name: 'junit', version: versions.junit
testCompile group: 'org.mockito', name: 'mockito-core', version: versions.mockito
}

jacocoTestReport {
Expand All @@ -54,6 +70,13 @@ buildscript {
jar {
baseName = projectName
version = projectVersion
manifest {
attributes("Implementation-Title": baseName,
"Implementation-Version": version,
"Implementation-Vendor": "Islandora",
"Class-Path": configurations.compile.collect { it.getName() }.join(' '))
}

}

shadowJar {
Expand All @@ -62,3 +85,14 @@ shadowJar {
}

assemble.dependsOn(shadowJar);

test {
testLogging {
// Make sure output from
// standard out or error is shown
// in Gradle output.
// showStandardStreams = true
//events 'standard_out'
exceptionFormat = 'full'
}
}
36 changes: 0 additions & 36 deletions conf/syn-settings.example.xml

This file was deleted.

43 changes: 43 additions & 0 deletions conf/syn-settings.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
version: 1
# Sites can be specified with a Key inline, or with a reference to a key
# stored in a file. Both are shown in examples below.
#
# The encoding parameter depends on what algorithm is chosen.
# HS256, HS384, HS512 support: plain and base64.
# RS256, RS384, RS512 support: PEM.

# A site with an inline key
site:
url: http://test.com
algorithm: HS256
encoding: plain
key: my secret key

# A site with a key stored in a file
site:
url: http://test2.com
algorithm: HS256
encoding: base64
path: /somewhere/on/filesystem.key

# A site that allows all GET/HEAD requests
site:
url: http://test3.com
algorithm: HS256
encoding: plain
anonymous: true

# This is how you specify a default site, which will be chosen if no
# other site matches the JWT url claim
site:
algorithm: RS256
encoding: PEM
path: /somewhere/on/filesystem.key
default: true

# This lets you specify a master token for testing. This should be used with care, as it gives anyone
# with this token unlimited access to your repository.
token:
user: test
roles: role1,role2,role3
value: my super secret token
20 changes: 14 additions & 6 deletions src/main/java/ca/islandora/syn/settings/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,37 @@
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonSetter;

public class Config {
private int version = -1;
private List<Site> sites = new ArrayList<>();
private List<Token> tokens = new ArrayList<>();
private final List<Site> sites = new ArrayList<>();
private final List<Token> tokens = new ArrayList<>();

@JsonSetter("site")
public void addSite(final Site site) {
sites.add(site);
this.sites.add(site);
}

public List<Site> getSites() {
return sites;
return this.sites;
}

public int getVersion() {
return this.version;
}

public void setVersion(final int version) {
this.version = version;
}

@JsonSetter("token")
public void addToken(final Token token) {
tokens.add(token);
this.tokens.add(token);
}

public List<Token> getTokens() {
return tokens;
return this.tokens;
}

}
Loading

0 comments on commit 9482e95

Please sign in to comment.