Trouble Enabling SSL on Fuseki Server - jena

I'm hoping some of you may be able to help me with setting up SSL on my fuseki server. I've been battling with it for a few days now and am running out of possible solutions!
OS: RHEL 8.5 (Ootpa)
Fuseki: Version 4.2.0
Currently running as system service with:
ExecStart=/home/fuseki/apache-jena-fuseki-4.2.0/fuseki-server -v -tdb2 -update -config=/home/fuseki/fuseki_data/config.ttl
This is the manual I've been working with- https://jena.apache.org/documentation/fuseki2/fuseki-data-access-control.html
The following are the provided arguments to add in the startup sequence of fuseki-server.
–https=SETUP [Name of file for certificate details.]
& –httpsPort=PORT [The port for https. Default: 3043]
The --https argument names a file in JSON which includes the name of
the certificate file and password for the certificate.
The issue is that no matter how I phrase the arguments the process returns "fuseki-server[9469]: Unknown argument: https" in the journalctl logs.
I have tried -https=dir, --https=dir, & -httpsConf=dir (where dir is the directory to my cert_details.json file).
Based on the docs https should have native support but when I check fuseki-server -help there is no mention of an https argument. I have created a .jks from my cert, have set the correct file permissions, and have allowed 3043.
I have also located the block of code in fuseki that resolves the keystore and passwd from the .json file (which led me to try using -httpsConf=)
private void setHttpsCert(String filename) {
try {
JsonObject httpsConf = JSON.read(filename);
Path path = Path.of(filename).toAbsolutePath();
String keystore = httpsConf.get("keystore").getAsString().value();
// Resolve relative to the https setup file.
this.httpsKeystore = path.getParent().resolve(keystore).toString();
this.httpsKeystorePasswd = httpsConf.get("passwd").getAsString().value();
Not sure what I'm missing here. For what it's worth I'm a chemist and I definitely don't know java all that well so it very well could be me being stupid. Any suggestions/knowledge would be greatly appreciated.

there are two ways to get HTTPS+Fuseki:
The document referred to is for the jar file here: https://repo1.maven.org/maven2/org/apache/jena/jena-fuseki-server/4.2.0/jena-fuseki-server-4.2.0.jar, not the jar in the apache-jena-fuseki download. (BTW It does not have the UI.)
The one in the apache-jena-fuseki can be use HTTPS by using a Jetty configuration using --jetty=jetty.xml (https://www.eclipse.org/jetty/documentation/current/jetty-xml-config.html) -- example: https://github.com/apache/jena/blob/main/jena-fuseki2/examples/fuseki-jetty-https.xml (which will need modifying).

Related

Debug authentication of Bazel's http_file

I want to fetch some data in Bazel over HTTP. There's a http_file method that looks like what I want. The remote server I'm fetching from uses authentication, so I've written it as
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
http_file(
name = "data_file",
urls = ["https://example.com/data.0.1.2"],
sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
downloaded_file_path = "data_file",
)
When I try the build, I get
WARNING: Download from https://example.com/data.0.1.2 failed: class com.google.devtools.build.lib.bazel.repository.downloader.UnrecoverableHttpException GET returned 401 Unauthorized
Followed by fatal errors because the file doesn't exist.
The error makes me think that I'm not authenticating correctly. I have a .netrc file and curl is able to use it to fetch the file.
Is there a way for me to debug? If it was curl, I would pass -v and see the auth header being sent with the request. I'm not sure if bazel is failing to send any authentication or if it's incorrect.
Running Bazel 3.2.0 on Mac OS (Darwin 19.6.0) and on Linux (Ubuntu 18.04).
HTTP 401 indeed sounds like incorrectly or not at all authenticated. .netrc should be supported and recognized. If not explicitly specified with netrc attribute, ${HOME}/.netrc would be tried if HOME is in the environment and bazel runs on non-Windows host (this has been the case since bazel 1.1; and shortly in 0.29) or %USERPROFILE%/.netrc if the variable is in the environment and running on Windows (this has been the case since 3.1). At the risk of stating the obvious, the .netrc should be owned by the same UID under which the process using it runs and its permbits should be 0600. If authentication methods other then http basic are needed, auth_patterns attribute needs to be used to configure that.
I am not aware of there being any ready made repository rule debugging facility such as CLI flag, but in this case it should be viable to copy the implementation of of the rule and functions it uses from tools/build_defs/repo, instrument it to get debugging info from it and use that for the purpose. For starters perhaps just print(auth) of what auth = _get_auth(ctx, all_urls) yielded to see if the that rule got the right idea about how to talk to host in question. It should be a dict with type, login, password information for each individual urls entries. The magic itself happens in use_netrc.

How to reference a pkcs12 keystore in Spring Boot properties

I need to pack a Spring Boot application as a Docker. I have everything running except the inclusion of the pkcs12 keystore needed to have Spring Boot directly support SSL.
I have solved the inclusion of the binary keystore file problem on gradel as explained here:
How to include a pkcs12 binary file in a Spring Boot tar file
This makes the keystore end up along with the properties files... that is in /BOOT-INF/classes/ directory... which is fine but, how can I have embedded Tomcat find it?
I have tried the properties file:
ssl.key-store: /BOOT-INF/classes/tripbruKeystoreWithKey.pkcs12
but that won't work. Tomcat won't find it there.
As I see it there are 2 options:
a) Make the keystore be in a different place (I think that if I can make it go to /BOOT-INF/lib it will be correctly recognized just by:
ssl.key-store: tripbruKeystoreWithKey.pkcs12
b) Correctly set the path in ssl-key-store property so Tomcat finds it in BOOT-INF/classes
What should I do?
The .p12 in the jar will be available as a classpath resource, so you can reference it from your configuration like this:
ssl.key-store: classpath:tripbruKeystoreWithKey.pkcs12

jetty 9: setting up the most basic SSL / https

NOTE: If you want to see the behaviour of this demo app, just go to www.collaborativepowernowinternational.us. Here, select the testssl.PersonController, and you may create a person. Then go and edit the person, where the SSL channel is designated, which will give a redirect loop.
It seems like with Jetty 9 more configuration items went into the start.ini file, I have version 9.05.
In order to test the most basic SSL/https, I am uncommenting the following lines in start.ini:
#===========================================================
# SSL Context
# Create the keystore and trust store for use by
# HTTPS and SPDY
#-----------------------------------------------------------
jetty.keystore=etc/keystore
jetty.keystore.password=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4
jetty.keymanager.password=OBF:1u2u1wml1z7s1z7a1wnl1u2g
jetty.truststore=etc/keystore
jetty.truststore.password=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4
jetty.secure.port=8443
etc/jetty-ssl.xml
#===========================================================
# HTTPS Connector
# Must be used with jetty-ssl.xml
#-----------------------------------------------------------
jetty.https.port=8443
etc/jetty-https.xml
No other Jetty configuration changes. I then built the most basic Grails app (has a Person class) where I set certain controller actions to secure, which works fine on my development machine using an older built in Jetty version (that Grails includes). This is done simply by including spring-security-core and then adding the following lines to a configuration file:
grails.plugins.springsecurity.secureChannel.definition = [
'/person/list': 'REQUIRES_INSECURE_CHANNEL',
'/person/delete/**': 'REQUIRES_SECURE_CHANNEL',
'/person/edit/**': 'REQUIRES_SECURE_CHANNEL',
'/person/show': 'REQUIRES_INSECURE_CHANNEL'
]
grails.plugins.springsecurity.portMapper.httpPort=80
grails.plugins.springsecurity.portMapper.httpsPort=443
When I access the person/edit action I get a redirect loop in the browser (using deployed WAR file to Jetty 9 on dedicated CentOs 6 machine). This is using the provided keystore that comes with Jetty 9, just uncommenting the lines in start.ini to use it.
The main Jetty SSL configuration page I'm reading is here. What isn't clear to me is, is updating the start.ini file enough? If not, how exactly does one add the lines in jetty-https.xml described in this previous link, i.e. the lines:
<New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<Set name="KeyStorePath"><Property name="jetty.home" default="." />/etc/keystore</Set>
<Set name="KeyStorePassword">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
<Set name="KeyManagerPassword">OBF:1u2u1wml1z7s1z7a1wnl1u2g</Set>
<Set name="TrustStorePath"><Property name="jetty.home" default="." />/etc/keystore</Set>
<Set name="TrustStorePassword">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
</New>
Not sure how to add them, but they also seem a duplicate of the start.ini file lines above.
Can you please help help me get the most basic Jetty SSL running? Thanks much.
If not familiar with Grails, one can simply download it, then create a domain class -- there is a command line option for this. Then give it fields String firstName, String lastName. Then there are commands to generate a controller and views for it -- this is all totally automatic. Then one adds the plugin, spring-security-core. In chapter 16/17 of this doc and as I have shown, when lists which controller actions are secure, such as person/edit.
You actually have enough here for just the Jetty portion of this to be working using the default trial keystore we ship in Jetty 9.0.6 distribution.
Simply the blurb you have above is enough to make SSL work within Jetty. I downloaded the 9.0.6 distribution and uncommented those lines and it works. Well, I had to go into the start.d/demo.ini file and remove the last two lines with etc/jetty-ssl.xml and etc/jetty-https.xml because they would get run twice...but I digress.
If you start up Jetty you can navigate to https://localhost:8443 and it will complain about being an untrusted certificate and then load up the jetty distribution page.
Based on that I would say this is likely some sort of grails configuration issue that I sadly don't know the answer too, sorry.
Starting Jetty 9.1, things have changed, and you have to follow the instructions in here for things to look correct, per Jetty developers. Moreover, you are not supposed to change/delete/edit anything in ${jetty.home}'s directories. Here's what you need to do for a self-signed certificate based SSL/HTTPS on Jetty 9.1+:
(a) set up your environment variable $JETTY_HOME to point to where you installed your jetty tar bundle, say /opt/jetty/.
(b) Create a new directory, /tmp/myJettyApp, point it to $JETTY_BASE in your environment.
(c) cd to $JETTY_BASE
(d) Follow instructions in here:
/home/sonny $ cd $JETTY_BASE
/tmp/myJettyApp/ $ java -jar $JETTY_HOME/start.jar --add-to-startd=https,http2
(e) Set your port if you'd like:
/home/sonny $ cd $JETTY_BASE;
/tmp/myJettyApp/ $ java -jar $JETTY_HOME/start.jar jetty.ssl.port=8444
(f) And now, run jetty:
/tmp/myJettyApp/ $ java -jar $JETTY_HOME/start.jar
you will see that HTTPS is running at port 8444. Now, if you want to make jetty listen in the traditional HTTPS port, you have to use sudo to run:
/tmp/myJettyApp/ $ java -jar $JETTY_HOME/start.jar jetty.ssl.port=443
/tmp/myJettyApp/ $ sudo java -jar $JETTY_HOME/start.jar
Note that this already does the self-signed certs etc. automagically.
Now, if you want to generate your own self-signed certificate (say, because you want to modify the validity to an arbitrary large or small value, depending on your needs), follow the instructions in here, generate a new self-signed cert using keytool and then place it in $JETTY_BASE/etc/ and modify the $JETTY_BASE/start.d/ssl.ini for jetty.sslContext.keyStorePassword and jetty.sslContext.keyManagerPassword respectively. BTW, for the last two ssl.ini passwords, you can use the obfuscated plain text password you used when you ran keytool or use the plain text ones. If you want to obfuscate them, run {jetty.home} $ java -cp lib/jetty-util-9.3.6.v20151106.jar org.eclipse.jetty.util.security.Password "MyInterestingAndAwesomePassword"
Hope this helps someone.

How to run Grails Wrapper (grailsw) behind a proxy?

I tried to run grailsw, but the wrapper cannot connect to download grails-2.2.1-download.zip (creates a 0 byte file instead).
I need to use a proxy server to connect to the internet, where do I configure proxy settings for the Grails Wrapper?
After running grails wrapper, your project directory has a new subdirectory called wrapper, with a file grails-wrapper.properties. You can configure your proxy settings in there, with the following properties:
systemProp.http.proxyHost=
systemProp.http.proxyPort=
systemProp.http.proxyUser=
systemProp.http.proxyPassword=
systemProp.http.nonProxyHosts=
I solved this problem for myself.
It is a two step process
1.a) Back up your JRE_HOME\lib\security folder. This is essential because the below steps might corrupt cacerts file under jre.
1.b) You need to install the ssl public key of Github.com to your local file system. To do that you have to use the InstallCert.java program( Link to InstallCert.java )
It is supposed to be run as java InstallCert github.com
and when it asks to enter cert number you need to enter 1
It will create a file with name "jssecacerts" in the current directory
1.c) But this program will not work because it does not know about how to authenticate with proxy. For this you need the code from SSLSocketClientWithTunneling page
Use the above two and create a program that tunnels through the proxy retrieves the ssl key and writes a file called jssecerts
2) Update your grails.bat with addtional options. Add these options to the %JAVA_EXE% command line. Paste them after %DEFAULT_JVM_OPTS%
-Dhttp.proxyHost=YourproxyURL -Dhttp.proxyPort=YourproxyPort -Dhttps.proxyHost=YourproxyURL -Dhttps.proxyPort=YourproxyPort -Dhttp.proxyUser=YourProxyUserID -Dhttp.proxyPassword=YourProxyPassword -Dhttps.proxyUser=YourProxyUserID -Dhttps.proxyPassword=YourProxyPassword -Djavax.net.ssl.trustStore=path-to-your-jssecacerts-created-in-step-1

knownhosts for Ant scp and sshexec tasks

My question is similar to the one asked here:
Ant scp task failure
BUILD FAILED com.jcraft.jsch.JSchException: reject HostKey: ....
My question is why are the keys not found in my knownhosts file?
No matter what kind of known_hosts file I have, the host key is rejected. Connecting via ssh works perfectly fine, and adds the relevant entries, but maybe jsch is unable to read known_hosts files generated by OpenSSH?
The Ant docs mention that the knownhosts file needs to be in SSH2 format, not SSH1. Ironically, the SSH2 format known_hosts file from OpenSSH is supposed to be ~/.ssh/known_hosts2, but the default value for knownhosts is ~/.ssh/known_hosts.
The known hosts files created by SSH2 are in ~/.ssh2/knownhosts/, so it's probably safe to count that out for the expected format. So far I've been unable to get OpenSSH to create a known_hosts2 file, and the man pages aren't much help there either. So what do the docs actually mean that the file needs to be in SSH2 format?
I've tried dsa and rsa keys, and neither work (both work with OpenSSH).
I've searched for two days and the only answers I've found are 'set trust="true'. Yes, that gets the task working, but not without turning a blind eye to security.
Here's a format I found that works with more recent versions of jch:
[xx.xx.xx.xx]:22 ssh-rsa .......
In older versions it was like:
xx.xx.xx.xx ssh-rsa ......
i.e. no square brackets and no port number. (Not sure if the port number is necessary if you're using port 22, but I tested it with a server with a non-default port assigned for SSH. And, in case it's not obvious, xx.xx.xx.xx should be the IP address of the server, or hostname or whatever.)
I found this format by getting the JCraft/jsch library to generate the known_hosts file for me. If you visit www.jcraft.com you can download a zip of the jsch source code, and some examples. Either build the source to make a jar, or download the ready-made jar as well. I unzipped the zip download and then plopped the jar file in that same directory.
There's an examples folder containing KnownHosts.java. You need to compile that file and then run it - it will ask you for your known_hosts file (just create an empty file in the default location first (~/.ssh/known_hosts) and select that. It will then ask you for details to connect to a server... Enter those, for example sshusername#xx.xx.xx.xx, and the program will try to connect and then fill the known_hosts file for you.
For convenience for blundering Windows users like me who can never remember how to do stuff from the command line, here's what you need to compile and run that KnownHosts.java file:
First, navigate to the directory (having unzipped it and put the jar file inside, as I described above).
Then run:
javac -cp jsch-0.1.49.jar examples/KnownHosts.java
to compile KnownHosts.java. And then:
java -cp "examples;jsch-0.1.49.jar" KnownHosts
to run it. Follow through the instructions above and you should have a working known_hosts file.
One final note: the KnownHosts program assumes a port of 22. I edited it to allow me to enter something like sshusername#xx.xx.xx.xx:8888 so I could specify a server with a custom port and have it work as described above. In the source of KnownHosts.java I looked for a line like:
Session session=jsch.getSession(user, host, 22);
and replaced it with:
int port = 22;
final int colonIndex = host.indexOf(':');
if (colonIndex > -1) {
final String[] split = host.split(":");
host = split[0];
port = Integer.parseInt(split[1]);
}
Session session=jsch.getSession(user, host, port);
and then compiled and ran as above.
The sshexec ant task is looking for the file 'known_hosts' by default to ${user.home}/.ssh/known_hosts
Verify the value of 'user.home' system property. Probably it points to unsuspected place.
Or provide the 'knownhosts' value explicitly in the ant task's property.
There are two parameters you might be interested in:
trust: If set to true will trust unknown hosts. The default is set to false.
knownhosts: Set to the location of your known hosts file.
The first will allow you to set the tasks to not check whether or not it's a known host. The second will allow you to specify the file that contains the known hosts. This way, you could specify it as ${user.home}/.ssh/known_hosts2and override the default.
By the way, a good way to do this is to use properties for these values, and then use a property file to override those properties:
[...]
<property name="build.properties" value="build.properties"/>
<property file="${build.properties}"/>
<!-- Can be overridden via 'build.properies' file -->
<property name="knownhosts.file" value="${user.home}/.ssh/knownhosts"/>
<property name="remote.host" value="foo-system"/>
[...]
<scp file="${copy.this.file}"
todir="${user}#{host}:${remote.dir}"
knownhosts="${knownhosts.file}"/>
[...]

Resources