Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Tomcat Valve to servlet Filter #11

Merged
merged 7 commits into from
Nov 21, 2018
Merged

Conversation

whikloj
Copy link
Member

@whikloj whikloj commented Jan 21, 2018

GitHub Issue: Islandora/documentation#736

Depends on: Islandora/documentation#84
Depends on: Islandora/Crayfish-Commons#15

What does this Pull Request do?

  • Converts the Tomcat Valve to a Filter
  • Replaces the XML configuration with a YAML one.
  • Changes some of the JWT claims to use standard ones.
  • Makes the SettingsParser parse the config only once and then supply the 3 maps from the internal Config object.

What's new?

  • The servletfilter will fail to initialize if it can't access it's settings file or the settings file is invalid.

  • In theory this filter should work on non-Tomcat container, but I haven't tried that.

  • The claim changes are

    • id -> webid
    • name -> sub
    • url -> iss
  • Does this change require documentation to be updated? Documentation has been updated

  • Does this change add any new dependencies? no

  • Does this change require any other modifications to be made to the repository (ie. Regeneration activity, etc.)?

  • Could this change impact execution of existing code?

How should this be tested?

There is no easy way to test this, it will require uninstalling Islandora. But this should hopefully work.

  1. Make sure you have a current version of master from claw-playbook.
  2. Delete your roles/external directory if it exists.
  3. Download this patch to the main claw-playbook directory and apply with git patch <patchfile>.
  4. Run ansible-galaxy install --role-file=requirements.yml --roles-path=roles/external
  5. Now for some manual editing in roles/external/Islandora-Devops.fcrepo-syn
    1. defaults/main.yml change fcrepo_syn_version: 0.1.0 to fcrepo_syn_version: 0.1.1
    2. tasks/install.yml change url: https://github.com/Islandora-CLAW/Syn/releases/download/v{{ fcrepo_syn_version }}/islandora-syn-{{ fcrepo_syn_version }}-all.jar to url: https://github.com/whikloj/Syn/releases/download/v{{ fcrepo_syn_version }}/islandora-syn-{{ fcrepo_syn_version }}-all.jar
  6. Run vagrant up
  7. Once the VM is up and running, log in vagrant ssh
  8. Download and run this script.
  9. When it tells you its ready for testing. Then please test.

You should be able to create a collection or image in Drupal and have it sync to Fedora.

But you should not be able to PUT/POST to fedora without a valid JWT or token. Like

ubuntu@claw:~$ curl -i -XPUT http://localhost:8080/fcrepo/rest/breaking
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1068
Date: Tue, 23 Jan 2018 16:51:21 GMT

<!DOCTYPE html><html><head><title>Apache Tomcat/8.0.32 (Ubuntu) - Error report</title><style type="text/css">H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}.line {height: 1px; background-color: #525D76; border: none;}</style> </head><body><h1>HTTP Status 401 - Token authentication failed.</h1><div class="line"></div><p><b>type</b> Status report</p><p><b>message</b> <u>Token authentication failed.</u></p><p><b>description</b> <u>This request requires HTTP authentication.</u></p><hr class="line"><h3>Apache Tomcat/8.0.32 (Ubuntu)</h3></body></html>

Additional Notes:

Any additional information that you think would be helpful when reviewing this PR.

Interested parties

Tag (@ mention) interested parties or, if unsure, @Islandora-CLAW/committers

@whikloj whikloj changed the title Issue 736 Change Tomcat Valve to servlet Filter Jan 21, 2018
@codecov
Copy link

codecov bot commented Jan 21, 2018

Codecov Report

Merging #11 into master will increase coverage by 3.35%.
The diff coverage is 92.3%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master      #11      +/-   ##
============================================
+ Coverage     86.11%   89.47%   +3.35%     
+ Complexity      116      112       -4     
============================================
  Files             6        9       +3     
  Lines           353      323      -30     
  Branches         65       53      -12     
============================================
- Hits            304      289      -15     
+ Misses           24       12      -12     
+ Partials         25       22       -3
Impacted Files Coverage Δ Complexity Δ
src/main/java/ca/islandora/syn/settings/Site.java 100% <ø> (ø) 15 <0> (ø) ⬇️
...java/ca/islandora/syn/valve/SynRequestWrapper.java 100% <100%> (ø) 3 <3> (?)
...slandora/syn/settings/SettingsParserException.java 100% <100%> (ø) 2 <2> (?)
...rc/main/java/ca/islandora/syn/settings/Config.java 100% <100%> (ø) 7 <4> (ø) ⬇️
.../ca/islandora/syn/token/InvalidTokenException.java 100% <100%> (ø) 2 <2> (?)
src/main/java/ca/islandora/syn/token/Verifier.java 100% <100%> (+31.25%) 10 <5> (+1) ⬆️
src/main/java/ca/islandora/syn/settings/Token.java 93.75% <100%> (ø) 7 <2> (ø) ⬇️
...java/ca/islandora/syn/settings/SettingsParser.java 80% <83.33%> (-1.94%) 43 <17> (-7)
...rc/main/java/ca/islandora/syn/valve/SynFilter.java 92.22% <92.22%> (ø) 23 <23> (?)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4b3ed30...7f2a556. Read the comment docs.

@whikloj
Copy link
Member Author

whikloj commented Jan 22, 2018

Pinging @acoburn and @ajs6f help to reveal my mistake.

I setup the Filter to attempt to load a relative location of the settings file by using getResource() from the classloader to find it inside the classpath. But the sample test file left in src/test/resource is not located as you can see in this test.

I had to ignore the test it as I am at a loss why this is not working. Alternatively, I'll just required the path to be absolute.

@DiegoPino
Copy link

@whikloj this will sound silly, but, I think, maven puts test resources at the root of your classpath (right?) by default but maybe gradle needs to be told where to look at?, It defines two different resource locations, main v/s tests..

Maybe you need in your build.gradle, for src/test/resources/exampleSettings.yaml to be found
, something like?

sourceSets.test {
    resources.srcDirs = ["src/test"]
}

or something like ?

test { 
    setClasspath(sourceSets.test.runtimeClasspath) 
} 

I'm guessing really here 😢 , you know java is like lava for me, can't swim there but looks tempting and glowing...

I feel it all depends on the output of running SynFilter.class.getClassLoader().getResource(".") and see what that points to when running the tests.

As always dismiss if all this is just me confused and you tried that. good night

@ajs6f
Copy link
Contributor

ajs6f commented Jan 22, 2018

I'm going to defer to @acoburn here, who knows more about Gradle in his little finger than I do in my whole body.

I will offer that loading editable config from the web app itself is generally not a good idea for a Java webapp. Better to have a config location outside the web app. Ideally, the web app itself (on the filesystem) never changes at all and can be deployed packed and operated packed.

Copy link
Contributor

@ajs6f ajs6f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks basically good to me, code-wise. I ran out of time but generally there are a lot of things called testXml that aren't XML and there are a good number of Autocloseable things that aren't being used in try-with-resource and there are a number of for loops that ought to be Iterable::forEachcalls, but these are all niceties that won't affect the operation of the code significantly.

assertEquals(username, requestCaptor.getValue().getUserPrincipal().getName());

for (final String role : finalRoles) {
assertTrue(requestCaptor.getValue().isUserInRole(role));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless order is important, prefer finalRoles.forEach(role -> assertTrue(requestCaptor.getValue().isUserInRole(role)))


final InputStream stream = new ByteArrayInputStream(testXml.getBytes());
final Config settings = SettingsParser.getSitesObject(stream);
final String testXml = String.join("\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not XML. testYaml?


final InputStream stream = new ByteArrayInputStream(testXml.getBytes());
final Config settings = SettingsParser.getSitesObject(stream);
final String testXml = String.join("\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not XML. testYaml?


final InputStream stream = new ByteArrayInputStream(testXml.getBytes());
final Config settings = SettingsParser.getSitesObject(stream);
final String testXml = String.join("\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not XML. testYaml?


final InputStream stream = new ByteArrayInputStream(testXml.getBytes());
final Config settings = SettingsParser.getSitesObject(stream);
final String testXml = String.join("\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not XML. testYaml?

final InputStream stream = new ByteArrayInputStream(testXml.getBytes());
final Config settings = SettingsParser.getSitesObject(stream);
assertEquals(-1, settings.getVersion());
final String testXml = String.join("\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not XML. testYaml?

" multiline",
" key");

final StringReader stream = new StringReader(testXml);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StringReader is Autocloseable; ideally this would be in try-with-resource.

final InputStream stream = new ByteArrayInputStream(testXml.getBytes());
final Config settings = SettingsParser.getSitesObject(stream);
assertEquals(12, settings.getVersion());
final String testXml = String.join("\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not XML. testYaml?

@acoburn
Copy link

acoburn commented Jan 22, 2018

@whikloj from what I can tell, this is the issue:

  1. the test file is loading just fine. no issue there
  2. the test file, when parsed, does not contain a site: section, so when the code (~line 143 in SynFilter) tries to build an algorithmMap, it gets a null value for the algorithm value. And hence, the filter fails.

(That's why the test results show this message: "No key found for site: ...")

@acoburn
Copy link

acoburn commented Jan 22, 2018

@whikloj I have some meetings this AM, but I can do a proper review later today.

@acoburn
Copy link

acoburn commented Jan 22, 2018

@whikloj one more thing (before I forget this) -- I agree with @ajs6f's comment about not allowing an editable config file in the web application. By allowing/encouraging folks to bake a default username/password into an application just opens you up to quite a few security-related issues. I think it's much better to remove that feature altogether and simply require users to have an external configuration file.

@whikloj
Copy link
Member Author

whikloj commented Jan 22, 2018

@ajs6f @acoburn @DiegoPino thanks for having a look. My java experience always lacks a certain flair so I appreciate the help.

I'll work on the code review from @ajs6f and it seems the consensus is to drop the relative file locating. It was a re-framing of the previous finding the resource relative to $CATALINA_HOME which no longer made sense. Instead I'll just require an absolute location to the configuration file.

@Natkeeran
Copy link

@whikloj Let me know if this is ready for testing?

@whikloj
Copy link
Member Author

whikloj commented Feb 7, 2018

@Natkeeran this is ready when ever you are.

@Natkeeran
Copy link

@whikloj

While trying to do the setup to test this, on Step 8, I get the following:

Username for 'https://github.com': Natkeeran
Password for 'https://[email protected]': 
remote: Repository not found.
fatal: repository 'https://github.com/whikloj/islandora-1.git/' not found
error: pathspec 'whikloj/issue-736' did not match any file(s) known to git.

@whikloj
Copy link
Member Author

whikloj commented Mar 27, 2018

@Natkeeran sorry I was cleaning up for Islandora 7.x-1.x stuff and I deleted my repository. We should probably stop making repos with the name of the whole stack. Anyways I recreated it, so you should be good to go.

@Natkeeran
Copy link

@whikloj

I followed the test instructions, still able to PUT without authorization. Since this PR is dependent on two others, I assume those two have to go in first before this can be tested.

@Natkeeran
Copy link

@whikloj

I followed your steps. But, I am still able to put without the token.

 curl -i -XPUT http://localhost:8080/fcrepo/rest/breaking
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
ETag: W/"8d19d54852223328f4cf9fff4b394c758cb16863"
Last-Modified: Mon, 02 Apr 2018 14:41:07 GMT
Location: http://localhost:8080/fcrepo/rest/breaking
Content-Type: text/plain
Content-Length: 42
Date: Mon, 02 Apr 2018 14:41:07 GMT

Are there specific things I can check to make sure I have your changes?

@whikloj
Copy link
Member Author

whikloj commented Apr 2, 2018

I'll try this again and see if I can see what is happening.

@whikloj
Copy link
Member Author

whikloj commented Apr 3, 2018

@Natkeeran ok I had steps 3 and 4 above reversed, I have corrected them. So you can try again.

@dannylamb
Copy link
Contributor

@Natkeeran Can you give this another shot? If you don't think you'll have the time, let me know and I'll see if someone else can hop on it. This has popped back up in Islandora/documentation#966.

@whikloj
Copy link
Member Author

whikloj commented Nov 20, 2018

@dannylamb @Natkeeran I'll try to get this rebased quickly

@dannylamb
Copy link
Contributor

@whikloj I can test when this is ready.

@whikloj
Copy link
Member Author

whikloj commented Nov 20, 2018

I just use the button, I haven't had a problem yet.

@dannylamb
Copy link
Contributor

Crayfish doesn't seem to survive the script in the testing instructions, which is back from when we didn't use features. I'm going to be smart next time and make a snapshot before running the script 🤦‍♂️ I should just be able to strip out most of it and get it working.

@dannylamb
Copy link
Contributor

@whikloj Success! Using this in lieu of your gist:

cd /var/www/html/drupal/web/modules/contrib/islandora
git remote add whikloj https://github.com/whikloj/islandora-1.git
git fetch whikloj
git checkout issue-736

/var/www/html/drupal/vendor/bin/drupal router:rebuild
/var/www/html/drupal/vendor/bin/drupal cache:rebuild all

MODULES="Gemini Milliner Houdini Hypercube"
for i in $MODULES; do
  cd /var/www/html/Crayfish/$i/vendor/islandora/crayfish-commons
  sudo git remote add whikloj https://github.com/whikloj/Crayfish-commons.git
  sudo git fetch whikloj
  sudo git checkout issue-736
done

Made an image and it kicked off derivatives. Everything wound up in Gemini.

mysql> select * from Gemini;
+----------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------+--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+---------------------+---------------------+
| fedora_hash                                                                                                                      | drupal_hash                                                                                                                      | uuid                                 | drupal_uri                                                                                | fedora_uri                                                                          | dateCreated         | dateUpdated         |
+----------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------+--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+---------------------+---------------------+
| 398a2e1c7f6121ffd18a1b5d25fefa134882281ea03bab177a0da342d5f1406fb2cef5d53858ddc4c7790ab7c3c825d186a533c4442e8741605066a941916576 | c792276ca856e53356f65cd8372f1ade6acfaba0da47004db00e5ebf40c482d6bd0130a7b82c6ebb7dd929d02bfa8c9eb41a91546afff509304db80dc5c31ddf | 1d88ce00-7eb3-48b4-bc4a-12b61c2da73a | http://localhost:8000/_flysystem/fedora/2018-11/animal-blurred-background-cat-1521305.jpg | http://localhost:8080/fcrepo/rest/2018-11/animal-blurred-background-cat-1521305.jpg | 2018-11-21 11:35:16 | 2018-11-21 11:35:16 |
| 3fab6c2f7946039b738ce3a2499158068c601e1c6280d44254c9fe476e4ebafda11c30edb472a1afd997b0de5c6784f1281d5641ce4e52c718bc4748c1483a9d | 88e848e9c1c047924e469c5e81f6b23c263a60c1309033c549cd7fd152bfd5996ab498d4ebdd192b749e4659dc335b6745d0c715d19e1a9e2a0f7b6650596891 | 3f2d95ea-a672-4ff7-9dc9-dc6665b3553d | http://localhost:8000/media/2?_format=jsonld                                              | http://localhost:8080/fcrepo/rest/3f/2d/95/ea/3f2d95ea-a672-4ff7-9dc9-dc6665b3553d  | 2018-11-21 11:35:29 | 2018-11-21 11:35:29 |
| b6a0c584eca4d755615a4121e4074ad47c867f6beabb5bd581aee30dcd2134c51ad7fa54f03720d3fc9f5c8363781ab92b8a55fb3ec7a325ff82152dbf18eb9b | fd48cd549436ffe733c96db6c990e780b602d036d8ebecfc95dcbbaaa0ae63bc5b2a9c1e51194b294dbffa8d1ee258cd95cace5dc125e5482aa12bc58c91468c | 5fca55ea-6060-400d-b7c8-10812c4ffa9c | http://localhost:8000/media/3?_format=jsonld                                              | http://localhost:8080/fcrepo/rest/5f/ca/55/ea/5fca55ea-6060-400d-b7c8-10812c4ffa9c  | 2018-11-21 11:35:31 | 2018-11-21 11:35:31 |
| 360e3c746aa4144cb24e2b968a9b136f0713e373549b74b0b704ef529c4f1cf023f5cb180b1271f230a08b5a7c29aa9986621a94e27f05592850cd9d286fc886 | 9e3a4d05bd0bbd6d558bffe43759511425096412ef0ba523201a82b2a0fbf934ecb84d011d01f3866187387135f567b9e82e0dd19bb2ae35407e17814fbe771a | e0d24dd0-45f6-4f74-97a7-9cc3c23ab83e | http://localhost:8000/node/1?_format=jsonld                                               | http://localhost:8080/fcrepo/rest/e0/d2/4d/d0/e0d24dd0-45f6-4f74-97a7-9cc3c23ab83e  | 2018-11-21 11:34:41 | 2018-11-21 11:34:41 |
+----------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------+--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+---------------------+---------------------+

Then I confirmed I can't write as anonymous

vagrant@claw:~$ curl -i -XPUT http://localhost:8080/fcrepo/rest/breaking
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1068
Date: Wed, 21 Nov 2018 17:38:55 GMT

<!DOCTYPE html><html><head><title>Apache Tomcat/8.0.32 (Ubuntu) - Error report</title><style type="text/css">H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}.line {height: 1px; background-color: #525D76; border: none;}</style> </head><body><h1>HTTP Status 401 - Token authentication failed.</h1><div class="line"></div><p><b>type</b> Status report</p><p><b>message</b> <u>Token authentication failed.</u></p><p><b>description</b> <u>This request requires HTTP authentication.</u></p><hr class="line"><h3>Apache Tomcat/8.0.32 (Ubuntu)</h3></body></html>

But can when authenticated

vagrant@claw:~$ curl -i -XPUT -H "Authorization: Bearer islandora" http://localhost:8080/fcrepo/rest/nonbreaking
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
ETag: W/"df48a41106b5c2710de69b35616c42a5ce257122"
Last-Modified: Wed, 21 Nov 2018 17:39:23 GMT
Location: http://localhost:8080/fcrepo/rest/nonbreaking
Content-Type: text/plain
Content-Length: 45
Date: Wed, 21 Nov 2018 17:39:23 GMT

http://localhost:8080/fcrepo/rest/nonbreaking

Copy link
Contributor

@dannylamb dannylamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tested and working and I'm inclined to pull it in.

@dannylamb dannylamb merged commit 9482e95 into Islandora:master Nov 21, 2018
dannylamb added a commit to dannylamb/Syn that referenced this pull request Nov 28, 2018
whikloj pushed a commit that referenced this pull request Nov 28, 2018
* Revert "Change Tomcat Valve to servlet Filter (#11)"

This reverts commit 9482e95.

* Version bump so it gets the right number this time

:man_facepalming:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants